Account

This directory includes contracts to build accounts for ERC-4337.

Core

AccountCore

import "@openzeppelin/contracts/account/AccountCore.sol";

A simple ERC4337 account implementation. This base implementation only includes the minimal logic to process user operations.

Developers must implement the AbstractSigner._rawSignatureValidation function to define the account’s validation logic.

Implementing a mechanism to validate signatures is a security-sensitive operation as it may allow an attacker to bypass the account’s security measures. Check out SignerECDSA, SignerP256, or SignerRSA for digital signature validation implementations.
Modifiers
  • onlyEntryPointOrSelf()

  • onlyEntryPoint()

Functions
  • entryPoint()

  • getNonce()

  • getNonce(key)

  • validateUserOp(userOp, userOpHash, missingAccountFunds)

  • executeUserOp(userOp, )

  • _signableUserOpHash(userOp, )

  • _payPrefund(missingAccountFunds)

  • _checkEntryPoint()

  • _checkEntryPointOrSelf()

  • receive()

EIP712
  • _domainSeparatorV4()

  • _hashTypedDataV4(structHash)

  • eip712Domain()

  • _EIP712Name()

  • _EIP712Version()

AbstractSigner
  • _rawSignatureValidation(hash, signature)

Events
IERC5267
  • EIP712DomainChanged()

Errors
  • AccountUnauthorized(sender)

Internal Variables
  • bytes32 constant _PACKED_USER_OPERATION

onlyEntryPointOrSelf() modifier

Revert if the caller is not the entry point or the account itself.

onlyEntryPoint() modifier

Revert if the caller is not the entry point.

entryPoint() → contract IEntryPoint public

Canonical entry point for the account that forwards and validates user operations.

getNonce() → uint256 public

Return the account nonce for the canonical sequence.

getNonce(uint192 key) → uint256 public

Return the account nonce for a given sequence (key).

validateUserOp(struct PackedUserOperation userOp, bytes32 userOpHash, uint256 missingAccountFunds) → uint256 public

Validates a user operation.

  • MUST validate the caller is a trusted EntryPoint

  • MUST validate that the signature is a valid signature of the userOpHash, and SHOULD return SIG_VALIDATION_FAILED (and not revert) on signature mismatch. Any other error MUST revert.

  • MUST pay the entryPoint (caller) at least the “missingAccountFunds” (which might be zero, in case the current account’s deposit is high enough)

Returns an encoded packed validation data that is composed of the following elements:

  • authorizer (address): 0 for success, 1 for failure, otherwise the address of an authorizer contract

  • validUntil (uint48): The UserOp is valid only up to this time. Zero for “infinite”.

  • validAfter (uint48): The UserOp is valid only after this time.

executeUserOp(struct PackedUserOperation userOp, bytes32) public

Executes a user operation.

_signableUserOpHash(struct PackedUserOperation userOp, bytes32) → bytes32 internal

Returns the digest used by an offchain signer instead of the opaque userOpHash.

Given the userOpHash calculation is defined by ERC-4337, offchain signers may need to sign again this hash by rehashing it with other schemes (e.g. ERC-191).

Returns a typehash following EIP-712 typed data hashing for readability.

_payPrefund(uint256 missingAccountFunds) internal

Sends the missing funds for executing the user operation to the entryPoint. The missingAccountFunds must be defined by the entrypoint when calling validateUserOp.

_checkEntryPoint() internal

Ensures the caller is the entryPoint.

_checkEntryPointOrSelf() internal

Ensures the caller is the entryPoint or the account itself.

receive() external

Receive Ether.

AccountUnauthorized(address sender) error

Unauthorized call to the account.

bytes32 _PACKED_USER_OPERATION internal constant

Account

import "@openzeppelin/contracts/account/Account.sol";

Extension of AccountCore with recommended feature that most account abstraction implementation will want:

  • {ERC721Holder} and {ERC1155Holder} to accept ERC-712 and ERC-1155 token transfers transfers.

  • ERC7739Signer for ERC-1271 signature support with ERC-7739 replay protection

To use this contract, the {ERC7739Signer-_rawSignatureValidation} function must be implemented using a specific signature verification algorithm. See SignerECDSA, SignerP256 or SignerRSA.
Functions
ERC7739Signer
  • isValidSignature(hash, signature)

ERC1155Holder
  • supportsInterface(interfaceId)

  • onERC1155Received(, , , , )

  • onERC1155BatchReceived(, , , , )

ERC721Holder
  • onERC721Received(, , , )

AccountCore
  • entryPoint()

  • getNonce()

  • getNonce(key)

  • validateUserOp(userOp, userOpHash, missingAccountFunds)

  • executeUserOp(userOp, )

  • _signableUserOpHash(userOp, )

  • _payPrefund(missingAccountFunds)

  • _checkEntryPoint()

  • _checkEntryPointOrSelf()

  • receive()

EIP712
  • _domainSeparatorV4()

  • _hashTypedDataV4(structHash)

  • eip712Domain()

  • _EIP712Name()

  • _EIP712Version()

AbstractSigner
  • _rawSignatureValidation(hash, signature)

Events
IERC5267
  • EIP712DomainChanged()

Errors
AccountCore
  • AccountUnauthorized(sender)

Extensions

AccountSignerERC7702

import "@openzeppelin/contracts/account/extensions/AccountSignerERC7702.sol";

Account implementation whose low-level signature validation is done by an EOA.

Functions
  • _rawSignatureValidation(hash, signature)

AccountCore
  • entryPoint()

  • getNonce()

  • getNonce(key)

  • validateUserOp(userOp, userOpHash, missingAccountFunds)

  • executeUserOp(userOp, )

  • _signableUserOpHash(userOp, )

  • _payPrefund(missingAccountFunds)

  • _checkEntryPoint()

  • _checkEntryPointOrSelf()

  • receive()

EIP712
  • _domainSeparatorV4()

  • _hashTypedDataV4(structHash)

  • eip712Domain()

  • _EIP712Name()

  • _EIP712Version()

Events
IERC5267
  • EIP712DomainChanged()

Errors
AccountCore
  • AccountUnauthorized(sender)

_rawSignatureValidation(bytes32 hash, bytes signature) → bool internal

Validates the signature using the EOA’s address (ie. address(this)).