Skip to content
Lattice

AccountInit

Git Source

Title: AccountInit

Author: David Dada <daveproxy80@gmail.com> (https://github.com/dadadave80)

One-shot initializer for a single-owner ERC-4337 Diamond account. Delegatecalled by the proxy's diamondCut during Diamond.initialize (so address(this) is the account), it seeds the owner, the trusted EntryPoint, and registers the account interfaces.

The EntryPoint is fixed per factory deployment (immutable, read from this contract's own code even under delegatecall). The account administers itself — DEFAULT_ADMIN_ROLE is granted to the account address, AND the account is its own diamond-lib Ownable owner (the DiamondCutFacet gate), so owner/EntryPoint/module changes AND upgrades flow through the validated execution path (a self-call via the ERC-7821 executor / EntryPoint), never a raw external admin. Without the initializeOwner step the blueprint's cut facet was a decoy: the owner slot stayed zero and diamondCut reverted Unauthorized() for every caller, freezing the account forever. init is safe to expose: each __*_init asserts the initializing window, so a direct call (outside a diamondCut) reverts.

Constants

ENTRY_POINT

The EntryPoint every account from this blueprint trusts to call validateUserOp.

address public immutable ENTRY_POINT;

Functions

constructor

constructor(address entryPoint_);

Parameters

NameTypeDescription
entryPoint_address

init

Runs the account module initializers. MUST be invoked via diamondCut's _init delegatecall.

function init(address owner) external;

Parameters

NameTypeDescription
owneraddressThe account's initial ECDSA signing owner.

init7702

EIP-7702 onboarding (#58 item 7): identical to init but the owner is the account itself — i.e. the delegated EOA, whose own key is the signer. Taking no owner argument keeps the 0x7702 initCode uniform for every EOA. Runs against the EOA's own storage via its 7702 delegate code.

SECURITY — onboarding MUST be atomic. The bare Diamond initialize that delegatecalls this is ungated, so the 7702 authorization MUST be bundled into the SAME transaction as the first UserOp (the standard 4337+7702 flow: the auth in the handleOps tx's authorization_list). Then delegation + init run in one tx and cannot be front-run. Applying the delegation in a SEPARATE, earlier tx and leaving the account uninitialized opens a window where anyone can initialize it with a hostile blueprint. Integrators who cannot guarantee atomicity should delegate to Account7702Diamond instead, whose signed onboarding closes that window on-chain. LEFTOVER STORAGE: the EOA's Solady-default Initializable and Ownable slots must be zero. A value left by an earlier Solady-based delegate makes either delegate's initializer revert, or makes initializeOwner revert AlreadyInitialized (details on Account7702Diamond).

function init7702() external;

_init

function _init(address owner) private;

Parameters

NameTypeDescription
owneraddress