Skip to content

Commit

Permalink
Merge branch 'develop' into AA-222-delegate-and-revert
Browse files Browse the repository at this point in the history
  • Loading branch information
drortirosh committed Dec 10, 2023
2 parents 73c5023 + e775dc0 commit 62afc47
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 398 deletions.
20 changes: 2 additions & 18 deletions contracts/core/EntryPoint.sol
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,6 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,

UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps);

emit BeforeExecution();

uint256 opIndex = 0;
for (uint256 a = 0; a < opasLen; a++) {
UserOpsPerAggregator calldata opa = opsPerAggregator[a];
Expand All @@ -208,6 +206,8 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
}
}

emit BeforeExecution();

uint256 collected = 0;
opIndex = 0;
for (uint256 a = 0; a < opasLen; a++) {
Expand Down Expand Up @@ -425,7 +425,6 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
address sender = mUserOp.sender;
_createSenderIfNeeded(opIndex, opInfo, op.initCode);
address paymaster = mUserOp.paymaster;
numberMarker();
uint256 missingAccountFunds = 0;
if (paymaster == address(0)) {
uint256 bal = balanceOf(sender);
Expand Down Expand Up @@ -612,10 +611,6 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
revert FailedOp(opIndex, "AA25 invalid account nonce");
}

// A "marker" where account opcode validation is done and paymaster opcode validation
// is about to start (used only by off-chain simulateValidation).
numberMarker();

bytes memory context;
if (mUserOp.paymaster != address(0)) {
(context, paymasterValidationData) = _validatePaymasterPrepayment(
Expand Down Expand Up @@ -769,17 +764,6 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
}
}

/**
* Places the NUMBER opcode in the code.
* This is used as a marker during simulation, as this OP is completely banned from the simulated code of the
* account and paymaster.
*/
function numberMarker() internal view {
assembly {
mstore(0, number())
}
}

/// @inheritdoc IEntryPoint
function delegateAndRevert(bytes calldata data) external {
(bool success, bytes memory ret) = address(this).delegatecall(data);
Expand Down
2 changes: 0 additions & 2 deletions contracts/core/EntryPointSimulations.sol
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,7 @@ contract EntryPointSimulations is EntryPoint, IEntryPointSimulations {
paymasterValidationData
);

numberMarker();
uint256 paid = _executeUserOp(0, op, opInfo);
numberMarker();
bool targetSuccess;
bytes memory targetResult;
if (target != address(0)) {
Expand Down
163 changes: 0 additions & 163 deletions contracts/samples/DepositPaymaster.sol

This file was deleted.

18 changes: 9 additions & 9 deletions contracts/samples/TokenPaymaster.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ import "../core/BasePaymaster.sol";
import "./utils/UniswapHelper.sol";
import "./utils/OracleHelper.sol";

// TODO: note https://github.com/pimlicolabs/erc20-paymaster-contracts/issues/10
// TODO: set a hard limit on how much gas a single user op may cost (postOp to fix the price)
/// @title Sample ERC-20 Token Paymaster for ERC-4337
/// @notice Based on Pimlico 'PimlicoERC20Paymaster' and OpenGSN 'PermitERC20UniswapV3Paymaster'
/// This Paymaster covers gas fees in exchange for ERC20 tokens charged using allowance pre-issued by ERC-4337 accounts.
/// The contract refunds excess tokens if the actual gas cost is lower than the initially provided amount.
/// The token price cannot be queried in the validation code due to storage access restrictions of ERC-4337.
Expand Down Expand Up @@ -54,12 +51,14 @@ contract TokenPaymaster is BasePaymaster, UniswapHelper, OracleHelper {

TokenPaymasterConfig private tokenPaymasterConfig;

// TODO: I don't like defaults in Solidity - accept ALL parameters of fail!!!
/// @notice Initializes the PimlicoERC20Paymaster contract with the given parameters.
/// @notice Initializes the TokenPaymaster contract with the given parameters.
/// @param _token The ERC20 token used for transaction fee payments.
/// @param _entryPoint The EntryPoint contract used in the Account Abstraction infrastructure.
/// @ param _tokenOracle The Oracle contract used to fetch the latest token prices.
/// @ param _nativeAssetOracle The Oracle contract used to fetch the latest native asset (ETH, Matic, Avax, etc.) prices.
/// @param _wrappedNative The ERC-20 token that wraps the native asset for current chain.
/// @param _uniswap The Uniswap V3 SwapRouter contract.
/// @param _tokenPaymasterConfig The configuration for the Token Paymaster.
/// @param _oracleHelperConfig The configuration for the Oracle Helper.
/// @param _uniswapHelperConfig The configuration for the Uniswap Helper.
/// @param _owner The address that will be set as the owner of the contract.
constructor(
IERC20Metadata _token,
Expand Down Expand Up @@ -90,7 +89,7 @@ contract TokenPaymaster is BasePaymaster, UniswapHelper, OracleHelper {
}

/// @notice Updates the configuration for the Token Paymaster.
/// @param _tokenPaymasterConfig The new price markup percentage (1e6 = 100%).
/// @param _tokenPaymasterConfig The new configuration struct.
function setTokenPaymasterConfig(
TokenPaymasterConfig memory _tokenPaymasterConfig
) public onlyOwner {
Expand Down Expand Up @@ -192,6 +191,7 @@ contract TokenPaymaster is BasePaymaster, UniswapHelper, OracleHelper {
}

/// @notice If necessary this function uses this Paymaster's token balance to refill the deposit on EntryPoint
/// @param _cachedPrice the token price that will be used to calculate the swap amount.
function refillEntryPointDeposit(uint256 _cachedPrice) private {
uint256 currentEntryPointBalance = entryPoint.balanceOf(address(this));
if (
Expand All @@ -205,7 +205,7 @@ contract TokenPaymaster is BasePaymaster, UniswapHelper, OracleHelper {

function getGasPrice(uint256 maxFeePerGas, uint256 maxPriorityFeePerGas) internal view returns (uint256) {
if (maxFeePerGas == maxPriorityFeePerGas) {
//legacy mode (for networks that don't support basefee opcode)
// legacy mode (for networks that don't support the 'basefee' opcode)
return maxFeePerGas;
}
return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);
Expand Down
46 changes: 44 additions & 2 deletions eip/EIPS/eip-4337.md
Original file line number Diff line number Diff line change
Expand Up @@ -596,9 +596,13 @@ Given UserOperation optionally without gas limits and gas prices, return the nee
The signature field is ignored by the wallet, so that the operation will not require user's approval.
Still, it might require putting a "semi-valid" signature (e.g. a signature in the right length)

**Parameters**: same as `eth_sendUserOperation`
**Parameters**:
* Same as `eth_sendUserOperation`\
gas limits (and prices) parameters are optional, but are used if specified.
`maxFeePerGas` and `maxPriorityFeePerGas` default to zero, so no payment is required by neither account nor paymaster.
* Optionally accepts the `State Override Set` to allow users to modify the state during the gas estimation.\
This field as well as its behavior is equivalent to the ones defined for `eth_call` RPC method.


**Return Values:**

Expand All @@ -621,7 +625,14 @@ Return a UserOperation based on a hash (userOpHash) returned by `eth_sendUserOpe

**Return value**:

`null` in case the UserOperation is not yet included in a block, or a full UserOperation, with the addition of `entryPoint`, `blockNumber`, `blockHash` and `transactionHash`
* If the UserOperation is included in a block:
* Return a full UserOperation, with the addition of `entryPoint`, `blockNumber`, `blockHash` and `transactionHash`.

* Else if the UserOperation is pending in the bundler's mempool:
* MAY return `null`, or: a full UserOperation, with the addition of the `entryPoint` field and a `null` value for `blockNumber`, `blockHash` and `transactionHash`.

* Else:
* Return `null`

#### * eth_getUserOperationReceipt

Expand Down Expand Up @@ -895,6 +906,37 @@ An array of reputation entries with the fields:
}
```

#### * debug_bundler_addUserOps

Accept UserOperations into the mempool.
Assume the given UserOperations all pass validation (without actually validating them), and accept them directly into th mempool

**Parameters:**

* An array of UserOperations

```json=
# Request
{
"jsonrpc": "2.0",
"id": 1,
"method": "debug_bundler_addUserOps",
"params": [
[
{ sender: "0xa...", ... },
{ sender: "0xb...", ... }
]
]
}
# Response
{
"jsonrpc": "2.0",
"id": 1,
"result": "ok"
}
```

## Backwards Compatibility

This EIP does not change the consensus layer, so there are no backwards compatibility issues for Ethereum as a whole. Unfortunately it is not easily compatible with pre-[ERC-4337](./eip-4337.md) accounts, because those accounts do not have a `validateUserOp` function. If the account has a function for authorizing a trusted op submitter, then this could be fixed by creating an [ERC-4337](./eip-4337.md) compatible account that re-implements the verification logic as a wrapper and setting it to be the original account's trusted op submitter.
Expand Down
Loading

0 comments on commit 62afc47

Please sign in to comment.