-
Notifications
You must be signed in to change notification settings - Fork 12.4k
Add Paymaster, PaymasterERC20, PaymasterERC20Guarantor, PaymasterERC721Owner and PaymasterSigner #6370
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
ernestognw
wants to merge
5
commits into
OpenZeppelin:master
Choose a base branch
from
ernestognw:feat/paymasters
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Add Paymaster, PaymasterERC20, PaymasterERC20Guarantor, PaymasterERC721Owner and PaymasterSigner #6370
Changes from 1 commit
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| 'openzeppelin-solidity': minor | ||
| --- | ||
|
|
||
| `PaymasterERC721Owner`: Extension of `PaymasterCore` that approves sponsoring of user operation based on ownership of an ERC-721 NFT. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| 'openzeppelin-solidity': minor | ||
| --- | ||
|
|
||
| `PaymasterERC20`: Extension of `PaymasterCore` that sponsors user operations against payment in ERC-20 tokens. | ||
ernestognw marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| 'openzeppelin-solidity': minor | ||
| --- | ||
|
|
||
| `PaymasterSigner`: Extension of `PaymasterCore` that approves sponsoring of user operation based on a cryptographic signature verified by the paymaster. | ||
ernestognw marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| 'openzeppelin-solidity': minor | ||
| --- | ||
|
|
||
| `Paymaster`: Add a simple ERC-4337 paymaster implementation with minimal logic. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| pragma solidity ^0.8.20; | ||
|
|
||
| import {ERC4337Utils} from "../utils/draft-ERC4337Utils.sol"; | ||
| import {IEntryPoint, IPaymaster, PackedUserOperation} from "../../interfaces/draft-IERC4337.sol"; | ||
|
|
||
| /** | ||
| * @dev A simple ERC4337 paymaster implementation. This base implementation only includes the minimal logic to validate | ||
| * and pay for user operations. | ||
| * | ||
| * Developers must implement the {Paymaster-_validatePaymasterUserOp} function to define the paymaster's validation | ||
| * and payment logic. The `context` parameter is used to pass data between the validation and execution phases. | ||
| * | ||
| * The paymaster includes support to call the {IEntryPointStake} interface to manage the paymaster's deposits and stakes | ||
| * through the internal functions {deposit}, {withdraw}, {addStake}, {unlockStake} and {withdrawStake}. | ||
| * | ||
| * * Deposits are used to pay for user operations. | ||
| * * Stakes are used to guarantee the paymaster's reputation and obtain more flexibility in accessing storage. | ||
| * | ||
| * NOTE: See [Paymaster's unstaked reputation rules](https://eips.ethereum.org/EIPS/eip-7562#unstaked-paymasters-reputation-rules) | ||
| * for more details on the paymaster's storage access limitations. | ||
| */ | ||
| abstract contract Paymaster is IPaymaster { | ||
| /// @dev Unauthorized call to the paymaster. | ||
| error PaymasterUnauthorized(address sender); | ||
|
|
||
| /// @dev Revert if the caller is not the entry point. | ||
| modifier onlyEntryPoint() { | ||
| _checkEntryPoint(); | ||
| _; | ||
| } | ||
|
|
||
| modifier onlyWithdrawer() { | ||
| _authorizeWithdraw(); | ||
| _; | ||
| } | ||
|
|
||
| /// @dev Canonical entry point for the account that forwards and validates user operations. | ||
| function entryPoint() public view virtual returns (IEntryPoint) { | ||
| return ERC4337Utils.ENTRYPOINT_V09; | ||
| } | ||
|
|
||
| /// @inheritdoc IPaymaster | ||
| function validatePaymasterUserOp( | ||
| PackedUserOperation calldata userOp, | ||
| bytes32 userOpHash, | ||
| uint256 maxCost | ||
| ) public virtual onlyEntryPoint returns (bytes memory context, uint256 validationData) { | ||
| return _validatePaymasterUserOp(userOp, userOpHash, maxCost); | ||
| } | ||
|
|
||
| /// @inheritdoc IPaymaster | ||
| function postOp( | ||
| PostOpMode mode, | ||
| bytes calldata context, | ||
| uint256 actualGasCost, | ||
| uint256 actualUserOpFeePerGas | ||
| ) public virtual onlyEntryPoint { | ||
| _postOp(mode, context, actualGasCost, actualUserOpFeePerGas); | ||
| } | ||
|
|
||
| /** | ||
| * @dev Internal validation of whether the paymaster is willing to pay for the user operation. | ||
| * Returns the context to be passed to postOp and the validation data. | ||
| * | ||
| * The `requiredPreFund` is the amount the paymaster has to pay (in native tokens). It's calculated | ||
| * as `requiredGas * userOp.maxFeePerGas`, where `required` gas can be calculated from the user operation | ||
| * as `verificationGasLimit + callGasLimit + paymasterVerificationGasLimit + paymasterPostOpGasLimit + preVerificationGas` | ||
| */ | ||
| function _validatePaymasterUserOp( | ||
| PackedUserOperation calldata userOp, | ||
| bytes32 userOpHash, | ||
| uint256 requiredPreFund | ||
| ) internal virtual returns (bytes memory context, uint256 validationData); | ||
|
|
||
| /** | ||
| * @dev Handles post user operation execution logic. The caller must be the entry point. | ||
| * | ||
| * It receives the `context` returned by `_validatePaymasterUserOp`. Function is not called if no context | ||
| * is returned by {validatePaymasterUserOp}. | ||
| * | ||
| * NOTE: The `actualUserOpFeePerGas` is not `tx.gasprice`. A user operation can be bundled with other transactions | ||
| * making the gas price of the user operation to differ. | ||
| */ | ||
| function _postOp( | ||
| PostOpMode /* mode */, | ||
| bytes calldata /* context */, | ||
| uint256 /* actualGasCost */, | ||
| uint256 /* actualUserOpFeePerGas */ | ||
| ) internal virtual {} | ||
|
|
||
| /// @dev Calls {IEntryPointStake-depositTo}. | ||
| function deposit() public payable virtual { | ||
| entryPoint().depositTo{value: msg.value}(address(this)); | ||
| } | ||
|
|
||
| /// @dev Calls {IEntryPointStake-withdrawTo}. | ||
| function withdraw(address payable to, uint256 value) public virtual onlyWithdrawer { | ||
| entryPoint().withdrawTo(to, value); | ||
| } | ||
|
|
||
| /// @dev Calls {IEntryPointStake-addStake}. | ||
| function addStake(uint32 unstakeDelaySec) public payable virtual { | ||
| entryPoint().addStake{value: msg.value}(unstakeDelaySec); | ||
| } | ||
|
|
||
| /// @dev Calls {IEntryPointStake-unlockStake}. | ||
| function unlockStake() public virtual onlyWithdrawer { | ||
| entryPoint().unlockStake(); | ||
| } | ||
|
|
||
| /// @dev Calls {IEntryPointStake-withdrawStake}. | ||
| function withdrawStake(address payable to) public virtual onlyWithdrawer { | ||
| entryPoint().withdrawStake(to); | ||
| } | ||
|
|
||
| /// @dev Ensures the caller is the {entrypoint}. | ||
| function _checkEntryPoint() internal view virtual { | ||
| address sender = msg.sender; | ||
| if (sender != address(entryPoint())) { | ||
| revert PaymasterUnauthorized(sender); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * @dev Checks whether `msg.sender` withdraw funds stake or deposit from the entrypoint on paymaster's behalf. | ||
| * | ||
| * Use of an xref:api:access.adoc[access control] | ||
| * modifier such as {Ownable-onlyOwner} is recommended. | ||
| * | ||
| * ```solidity | ||
| * function _authorizeUpgrade() internal onlyOwner {} | ||
| * ``` | ||
ernestognw marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| */ | ||
| function _authorizeWithdraw() internal virtual; | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.