docs
Understanding ERC-4337
Account contract

Account Contract

In ERC-4337, an account is a contract that is able to hold user assets and interact with contracts on the user's behalf.

ERC-4337 does not require a specific account contract implementation. However, it does require that account contracts implement a specific interface. This interface is defined in the ERC-4337 Specification (opens in a new tab), and contains only a single function, validateUserOp, which is used to verify the signature of a UserOperation.

The interface is defined as follows:

import "./PackedUserOperation.sol";
interface IAccount {
    function validateUserOp(
        PackedUserOperation calldata userOp,
        bytes32 userOpHash,
        uint256 missingAccountFunds
    ) external returns (uint256 validationData);
}

The validateUserOp function is called by the EntryPoint contract to verify the signature of a UserOperation. The UserOperation is passed as a PackedUserOperation object, which is a tightly packed representation of the UserOperation object. The userOpHash is the hash of the UserOperation object, and is used to verify the signature.

The missingAccountFunds parameter is the amount of funds that are required to be deposited into the EntryPoint in order to cover the maximum costs to execute the transaction. This value will be 0 when a paymaster is used.

Transaction execution

ERC-4337 does not require a specific interface for executing transactions. This is because the transaction execution calldata is defined in the UserOperation object, and is not dependent on the account contract.

Authentication and authorization

The precise mechanism for authentication and authorization is left to the account contract implementation. However, the account contract must be able to verify the signature of a UserOperation using the validateUserOp function.

Nonces and replay protection

Nonce and replay protection is provided by the EntryPoint and there is no requirement for the Account to implement their own nonce or replay protection.

Sample implementation

The ERC-4337 core team has implemented SimpleAccount.sol (opens in a new tab), a sample minimal account that extends BaseAccount.sol (opens in a new tab), which implements the IAccount (opens in a new tab) interface.

The SimpleAccount contract is a minimal account contract that is able to hold user assets and interact with contracts on the user's behalf. It is expected to be deployed as a proxy via the SimpleAccountFactory contract.

This account contract has a single EOA based owner that can execute any transaction. The owner must sign the UserOperation using an ECDSA signature of the UserOperation hash. More information about these signature can be found in OpenZeppelin's ECDSA library (opens in a new tab).

Execution of the UserOperation is done by calling the execute function, which is able to execute any transaction on behalf of the user. The execute function is able to call any contract and pass any calldata to the contract. This execute function can only be called by the EntryPoint contract, as so will only be executed once the UserOperation has been validated. See the interface for the execute function below.

interface ISimpleAccount {
    function execute(address dest, uint256 value, bytes calldata func) external;
}

logo
logologologo

© 2023 Ethereum Foundation. All Rights Reserved.