/** ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation. ** Only one instance required on each chain. **/ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.12; /* solhint-disable avoid-low-level-calls */ /* solhint-disable no-inline-assembly */ /* solhint-disable reason-string */ import "./UserOperation.sol"; import "./IStakeManager.sol"; import "./IAggregator.sol"; interface IEntryPoint is IStakeManager { /*** * An event emitted after each successful request * @param requestId - unique identifier for the request (hash its entire content, except signature). * @param sender - the account that generates this request. * @param paymaster - if non-null, the paymaster that pays for this request. * @param nonce - the nonce value from the request * @param actualGasCost - the total cost (in gas) of this request. * @param actualGasPrice - the actual gas price the sender agreed to pay. * @param success - true if the sender transaction succeeded, false if reverted. */ event UserOperationEvent(bytes32 indexed requestId, address indexed sender, address indexed paymaster, uint256 nonce, uint256 actualGasCost, uint256 actualGasPrice, bool success); /** * An event emitted if the UserOperation "callData" reverted with non-zero length * @param requestId the request unique identifier. * @param sender the sender of this request * @param nonce the nonce used in the request * @param revertReason - the return bytes from the (reverted) call to "callData". */ event UserOperationRevertReason(bytes32 indexed requestId, address indexed sender, uint256 nonce, bytes revertReason); /** * a custom revert error of handleOps, to identify the offending op. * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it. * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero) * @param paymaster - if paymaster.validatePaymasterUserOp fails, this will be the paymaster's address. if validateUserOp failed, * this value will be zero (since it failed before accessing the paymaster) * @param reason - revert reason * Should be caught in off-chain handleOps simulation and not happen on-chain. * Useful for mitigating DoS attempts against batchers or for troubleshooting of wallet/paymaster reverts. */ error FailedOp(uint256 opIndex, address paymaster, string reason); /** * error case when a signature aggregator fails to verify the aggregated signature it had created. */ error SignatureValidationFailed(address aggregator); //UserOps handled, per aggregator struct UserOpsPerAggregator { UserOperation[] userOps; // aggregator address IAggregator aggregator; // aggregated signature bytes signature; } /** * Execute a batch of UserOperation. * no signature aggregator is used. * if any wallet requires an aggregator (that is, it returned an "actualAggregator" when * performing simulateValidation), then handleAggregatedOps() must be used instead. * @param ops the operations to execute * @param beneficiary the address to receive the fees */ function handleOps(UserOperation[] calldata ops, address payable beneficiary) external; /** * Execute a batch of UserOperation with Aggregators * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator wallets) * @param beneficiary the address to receive the fees */ function handleAggregatedOps( UserOpsPerAggregator[] calldata opsPerAggregator, address payable beneficiary ) external; /** * generate a request Id - unique identifier for this request. * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid. */ function getRequestId(UserOperation calldata userOp) external view returns (bytes32); /** * Simulate a call to wallet.validateUserOp and paymaster.validatePaymasterUserOp. * Validation succeeds if the call doesn't revert. * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the wallet's data. * In order to split the running opcodes of the wallet (validateUserOp) from the paymaster's validatePaymasterUserOp, * it should look for the NUMBER opcode at depth=1 (which itself is a banned opcode) * @param userOp the user operation to validate. * @param offChainSigCheck if the wallet has an aggregator, skip on-chain aggregation check. In thus case, the bundler must * perform the equivalent check using an off-chain library code * @return preOpGas total gas used by validation (including contract creation) * @return prefund the amount the wallet had to prefund (zero in case a paymaster pays) * @return actualAggregator the aggregator used by this userOp. if a non-zero aggregator is returned, the bundler must get its params using * aggregator. * @return sigForUserOp - only if has actualAggregator: this value is returned from IAggregator.validateUserOpSignature, and should be placed in the userOp.signature when creating a bundle. * @return sigForAggregation - only if has actualAggregator: this value is returned from IAggregator.validateUserOpSignature, and should be passed to aggregator.aggregateSignatures * @return offChainSigInfo - if has actualAggregator, and offChainSigCheck is true, this value should be used by the off-chain signature code (e.g. it contains the sender's publickey) */ function simulateValidation(UserOperation calldata userOp, bool offChainSigCheck) external returns (uint256 preOpGas, uint256 prefund, address actualAggregator, bytes memory sigForUserOp, bytes memory sigForAggregation, bytes memory offChainSigInfo); /** * Get counterfactual sender address. * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. * must be called from zero-address. * @param initCode the constructor code to be passed into the UserOperation. */ function getSenderAddress(bytes memory initCode) external returns (address); /** * return the storage cells used internally by the EntryPoint for this sender address. * During `simulateValidation`, allow these storage cells to be accessed * (that is, a wallet/paymaster are allowed to access their own deposit balance on the * EntryPoint's storage, but no other account) */ function getSenderStorage(address sender) external view returns (uint256[] memory senderStorageCells); }