Skip to content
Lattice

Account7702Diamond

Git Source

Inherits: AccountDiamond

Title: Account7702Diamond

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

Optional hardened EIP-7702 delegate (#58 item 7). The bare Diamond's ungated initialize is safe only when onboarding is ATOMIC — the 7702 authorization bundled into the same transaction as the first UserOp, which is the standard 4337+7702 flow. An EOA that instead applies the delegation in a separate, earlier transaction and leaves itself uninitialized is exposed to a front-runner who can initialize it with a hostile blueprint. Delegating to THIS contract closes that window: the unauthenticated initialize is disabled, and onboarding requires the delegating EOA's signature over the exact (cuts, init, calldata), bound to this account and chain.

A front-runner cannot forge the EOA's signature, so cannot substitute a hostile blueprint; replaying the EOA's own signed onboarding only reproduces the intended state (init7702 sets owner = the EOA). The residual is at most a failed first UserOp + retry, never account hijacking. LEFTOVER STORAGE (EIP-7702 keeps storage across re-delegation): module state is ERC-7201 namespaced, but the initializer flag and diamond-lib's owner word sit in Solady's default Initializable (0xff…bf601132) and Ownable (0xff…74873927) slots. An EOA earlier delegated to a Solady-based account that left either slot non-zero cannot onboard: initializeAuthorized reverts InvalidInitialization (the constructor-only exemption needs empty code, and a delegated EOA has the delegation designator) or AlreadyInitialized (from AccountInit's initializeOwner). Clear both slots first, via a delegate that zeroes them. Lattice's values likewise remain for the next delegate. Namespacing these slots is deferred to a coordinated 1.0 change (#247).

Constants

_ONBOARD_TAG

Domain tag separating the onboarding digest from any other message the EOA might sign.

bytes32 private constant _ONBOARD_TAG = keccak256("Lattice.EIP7702.Onboard.v1");

Functions

initialize

Disabled on this delegate — use initializeAuthorized so onboarding is bound to the EOA's key.

function initialize(FacetCut[] calldata, address, bytes calldata) public payable virtual override;

Parameters

NameTypeDescription
_FacetCut[]
_address
_bytes

initializeAuthorized

Initializes the delegated EOA's storage, gated by the EOA's signature over the onboarding.

The initializer guard runs before signature verification — an already-initialized account reverts InvalidInitialization regardless of signature validity.

function initializeAuthorized(
        FacetCut[] calldata _facetCuts,
        address _init,
        bytes calldata _calldata,
        bytes calldata _signature
    ) external payable virtual initializer;

Parameters

NameTypeDescription
_facetCutsFacetCut[]The facet cuts to apply.
_initaddressThe initializer delegatecalled by diamondCut (e.g. AccountInit).
_calldatabytesThe initializer calldata (e.g. AccountInit.init7702()).
_signaturebytesThe delegating EOA's ECDSA signature over onboardingDigest of the above.

onboardingDigest

The digest the delegating EOA signs to authorize an onboarding. Bound to this account (address(this)) and chain, so a signature cannot be replayed onto another account or chain.

function onboardingDigest(FacetCut[] calldata _facetCuts, address _init, bytes calldata _calldata)
        public
        view
        returns (bytes32);

Parameters

NameTypeDescription
_facetCutsFacetCut[]
_initaddress
_calldatabytes

Returns

NameTypeDescription
<none>bytes32

Errors

UnauthorizedOnboarding

The provided onboarding signature did not recover to this account (the delegating EOA).

error UnauthorizedOnboarding();