UserOperation
- pseudo-transaction type for user-initiated operations.
These operations are sent to a different transaction mempool and are processed by a new kind of actor, called Bundler
. These UserOperations
are packaged up into a transaction making a handleOps
call to a special contract; that transaction gets included into a block.
Decentralization:
- Achieves key goal of removing the need for EOAs (Externally Owned Accounts).
- Allows any
Bundler
to includeUserOperations
into a block. - Works with all activity happening over a public mempool; users don't need to know about the
Bundler
's private mempool. - Avoids trust assumptions
No consensus changes are needed.
Other use cases:
- Privacy preserving applications
- Atomic multi operations (like EIP-3074)
- Pay tx fees with ERC-20
- Support aggregated signature (like BLS)
UserOperation
is a new pseudo-transaction type.
It contains the following fields:
Parameter | Type | Description |
---|---|---|
sender |
address |
The account contract sending a user operation |
nonce |
uint256 |
Anti-replay protection; also used as the salt for first-time account creation |
to |
address |
|
initCode |
bytes |
initCode of the account (only needed if the account is not yet on-chain and and needs to be created) |
calldata |
bytes |
The data to pass to sender during main execution call |
callGasLimit |
uint256 |
The data to pass to sender during main execution call |
verificationGasLimit |
uint256 |
The amount of gas to allocate for the verification step |
preVerificationGas |
uint256 |
The amount of gas to pay for to compensate the bundler for pre-verification execution and calldata |
maxFeePerGas |
uint256 |
Maximum fee per gas (like EIP-1559) |
maxPriorityFeePerGas |
uint256 |
Maximum priority fee per gas (like EIP-1559) |
paymasterAndData |
bytes |
Paymaster address sponsoring the transaction with extra data (empty for self-sponsored transactions) |
signature |
bytes |
Data passed into the account along with the nonce during the verification step |
Nonce
- anti-replay protection; also used as the salt for first-time account creationEntryPoint
- a singleton contract to execute bundles ofUserOperations
.Bundlers
orClients
whitelist the supported entrypoint.Bundler
- a node that bundles multipleUserOperations
and creates anEntryPoint.handleOps()
transaction.Aggregator
- a helper contract trusted by accounts to validate an aggregated signature.Bundlers
orClients
whitelist the supported aggregator.
A bundle transaction packages up multiple UserOperations
into a single handleOps
call to a pre-published global entry point contract.
The Entry Point Contract core interface looks like this:
interface IEntryPoint {
struct UserOperation {
address sender;
uint256 nonce;
uint256 callGasLimit;
uint256 verificationGasLimit;
uint256 preVerificationGas;
uint256 maxFeePerGas;
uint256 maxPriorityFeePerGas;
bytes initCode;
bytes callData;
bytes paymasterAndData;
bytes signature;
}
function handleOps(
UserOperation[] calldata ops,
address payable beneficiary
) external;
====================
struct UserOpsPerAggregator {
UserOperation[] userOps;
IAggregator aggregator;
// aggregated signature
bytes signature;
}
function handleAggregatedOps(
UserOpsPerAggregator[] calldata opsPerAggregator,
address payable beneficiary
) external;
====================
error ValidationResult(
ReturnInfo returnInfo,
StakeInfo senderInfo,
StakeInfo factoryInfo,
StakeInfo paymasterInfo
);
error ValidationResultWithAggregation(
ReturnInfo returnInfo,
StakeInfo senderInfo,
StakeInfo factoryInfo,
StakeInfo paymasterInfo,
AggregatorStakeInfo aggregatorInfo
);
function simulateValidation(
UserOperation calldata userOp
) external;
struct ReturnInfo {
uint256 preOpGas;
uint256 prefund;
bool sigFailed;
uint48 validAfter;
uint48 validUntil;
bytes paymasterContext;
}
struct StakeInfo {
uint256 stake;
uint256 unstakeDelaySec;
}
struct AggregatorStakeInfo {
address actualAggregator;
StakeInfo stakeInfo;
}
}
ERC 20, approval with account abstraction.