Alert Source Discuss
⚠️ Draft Standards Track: ERC

ERC-8286: Modular Accounts for Frame Transactions

EIP-8141 native account abstraction validation extension for ERC-7579 modular accounts

Authors Chiranjeev Mishra (@chiranjeev13), Pedro Gomes (@pedrouid), Alex Forshtat (@forshtat)
Created 2026-06-04
Discussion Link https://ethereum-magicians.org/t/erc-8286-modular-accounts-for-frame-transactions/28695
Requires EIP-7579, EIP-8141

Abstract

ERC-7579 standardizes a core module system for modular smart accounts: module types, the module lifecycle, installation, and account configuration. This proposal extends that system to EIP-8141 native account abstraction by defining the validation flow for frame transactions. It reuses ERC-7579’s module structure unchanged: a validator returns an approval mode, and the account applies it through EIP-8141’s APPROVE instruction during a VERIFY frame. Keeping the module system in ERC-7579 and layering account-abstraction-specific validation flows as extensions lets a single module ecosystem serve accounts across multiple account abstraction implementations, without forking modules or vendor lock-in.

Specification

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 and RFC 8174.

Relationship to ERC-7579

This standard is an extension to ERC-7579 and does not redefine its module system. A compliant account and its modules MUST conform to ERC-7579 for:

  • module types and their identifiers,
  • the module lifecycle interface (onInstall, onUninstall, isModuleType),
  • module installation and configuration (installModule, uninstallModule, isModuleInstalled), and
  • account configuration (accountId, supportsModule, supportsExecutionMode).

ERC-7579’s execution interface (execute, executeFromExecutor) is not required, see Execution.

This standard adds only what EIP-8141 native account abstraction requires: the approval-mode validation flow and the interfaces defined below. It is the EIP-8141 analogue of ERC-7579’s own validation flow. Where ERC-7579 defines validateUserOp for its ERC-4337 target, this standard defines validateFrame.

Approval Mode

This standard defines the approval mode: a uint8 bearing the value of the EIP-8141 APPROVE instruction’s scope operand. It is the result of validation as defined in this standard — a validator returns an approval mode to the account, and the account applies it by executing the APPROVE instruction with that value during a VERIFY frame.

The bit semantics are equivalent to those of the EIP-8141 scope operand. The two least significant bits form a bitmask:

  • bit 0 (payment): the account approves paying the transaction’s total gas cost.
  • bit 1 (execution): the account approves subsequent frames acting on its behalf as sender.

This yields the following modes, which an account MUST interpret consistently with EIP-8141’s APPROVE scope operand:

Mode Name Payment Execution
0x0 APPROVE_NONE no no
0x1 APPROVE_PAYMENT yes no
0x2 APPROVE_EXECUTION no yes
0x3 APPROVE_EXECUTION_AND_PAYMENT yes yes

APPROVE_SCOPE_MASK is defined as 0x3. A frame’s allowed scope is frame.flags & APPROVE_SCOPE_MASK, equivalently FRAMEPARAM(frameIndex, 0x06).

Accounts are NOT REQUIRED to grant every mode. The account MUST NOT approve a mode outside the allowed scope of the executing VERIFY frame, and APPROVE_EXECUTION is only valid when the frame’s resolved target is tx.sender. If validation does not succeed, the account MUST NOT call APPROVE, which leaves the mode at APPROVE_NONE and invalidates the transaction.

An account MUST declare which approval modes it supports through supportsApprovalMode (see below), and MUST NOT call APPROVE with a mode it does not support.

EIP-8141 Frame Validator

ERC-7579 defines validateUserOp validators and assigns module type id 1 to them.

An EIP-8141 frame validator is a module that determines the approval mode a transaction is entitled to. This standard assigns frame validators a new module type id: 11 . A module MAY additionally be an ERC-7579 validator (type id 1) and serve both targets.

When the account’s code executes in a VERIFY frame, the account selects a frame validator and calls it. The validator returns an approval mode, which the account then applies via APPROVE.

In place of ERC-7579’s validateUserOp validation function, an EIP-8141 validator MUST implement ERC-7579’s IERC7579Module interface and the IFrameValidator interface below:

interface IFrameValidator is IERC7579Module {
    /**
     * @dev Validates the active VERIFY frame and returns the approval mode the
     *      validator authorizes for the transaction.
     * @param sigHash      the canonical transaction signing hash, i.e. TXPARAM(0x08).
     * @param frameIndex   the index of the executing VERIFY frame, i.e. TXPARAM(0x0A).
     * @param allowedScope the approval mode permitted by the frame flags, i.e.
     *                      FRAMEPARAM(frameIndex, 0x06).
     * @param data         validator-specific calldata supplied by the account, e.g. a
     *                      signature envelope or policy parameters.
     *
     * MUST NOT modify state; the validator is invoked within the STATICCALL context of
     * a VERIFY frame.
     * MUST return APPROVE_NONE (0x0) if validation fails.
     * MAY revert to indicate failures not related to the core validation logic directly (e.g. decoding errors).
     * The returned approval mode SHOULD be a subset of `allowedScope`; the account is
     * the final authority and MUST mask the result with `allowedScope` before approving.
     */
    function validateFrame(
        bytes32 sigHash,
        uint256 frameIndex,
        uint8 allowedScope,
        bytes calldata data
    ) external view returns (uint8 approvalMode);
}

The account’s behavior when running in a VERIFY frame targeting itself is:

  1. Read the allowed scope allowedScope = FRAMEPARAM(frameIndex, 0x06).
  2. Select an installed validator. This standard does not dictate the selection mechanism (see Validator Selection). The account MUST verify the selected module is an installed frame validator (module type id 11 ).
  3. Call validateFrame on the selected validator with all correctly specified input parameters, and the validator-specific calldata, then mask the result: approvalMode = approvalMode & allowedScope.
  4. If approvalMode has the execution bit (bit 1) set, the account MUST check the modes presented by the transaction’s SENDER frames (see SENDER Frame Execution Modes) against the execution modes it supports (supportsExecutionMode, inherited from IERC7579AccountConfig). If supportsExecutionMode returns false for any presented mode, the account MUST clear the execution bit, leaving approvalMode = approvalMode & APPROVE_PAYMENT.
  5. If the resulting approvalMode is APPROVE_NONE, the account MUST NOT call APPROVE; the frame reverts and the transaction is invalid.
  6. Otherwise the account MUST call APPROVE(approvalMode).

The raw signature bytes of EIP-8141 tx.signatures are intentionally not accessible from the EVM. A validator therefore obtains its authorization material either by reading the metadata of an already protocol-validated signature via the SIGPARAM instruction (for the natively supported SECP256K1 and P256 schemes), or by receiving a self-contained signature envelope in data and verifying it itself (for module-defined schemes such as passkeys, multisig, or BLS).

Because EIP-8141 permits only a frame’s resolved target (or code it DELEGATECALLs into) to call APPROVE, a validator reached via STATICCALL cannot approve on its own. The account remains the sole caller of APPROVE.

SENDER Frame Execution Modes

This standard defines four execution modes describing the shape of a transaction’s SENDER frames. They extend ERC-7579’s mode encoding with two new callType values; the execType values keep their ERC-7579 meanings, which apply to frames verbatim:

  • callType 0x02 : the transaction has exactly one SENDER frame.
  • callType 0x03 : the transaction has multiple SENDER frames.
  • execType 0x00 (revert-all): the frame belongs to an atomic-batch group (all-or-nothing).
  • execType 0x01 (try): the frame is not part of an atomic batch; a revert discards only that frame.

The mode constants, encoded per ERC-7579’s mode layout (callType in byte 0, execType in byte 1, all remaining bytes zero):

Constant callType execType Meaning
FRAME_MODE_SINGLE 0x02 0x01 one standalone SENDER frame
FRAME_MODE_SINGLE_ATOMIC 0x02 0x00 one SENDER frame inside an atomic batch
FRAME_MODE_BATCH 0x03 0x01 multiple SENDER frames, reverting independently
FRAME_MODE_BATCH_ATOMIC 0x03 0x00 multiple SENDER frames in an atomic batch

A transaction presents a mode for each of its SENDER frames: callType is 0x02 if the transaction has exactly one SENDER frame and 0x03 otherwise; execType is 0x00 if the frame belongs to an atomic batch and 0x01 otherwise. A transaction may present several modes at once — for example, an atomic group alongside an ungrouped frame presents both FRAME_MODE_BATCH_ATOMIC and FRAME_MODE_BATCH.

The account supports a transaction’s SENDER frames only if supportsExecutionMode returns true for every presented mode.

These modes are declarations for supportsExecutionMode and the validation-time check in step 4 above; they are never passed to execute, and the new callType values define no execute dispatch behavior.

Account Interface

A compliant account MUST implement the following interface. It extends ERC-7579’s IERC7579AccountConfig and IERC7579ModuleConfig, so module installation and approval-mode capability are exposed through a single account interface alongside the EIP-8141 validation flow. It adds no execution interface; ERC-7579’s applies unchanged where the account dispatches execution (see Execution):

interface IERC8286FrameAccount is IERC7579AccountConfig, IERC7579ModuleConfig {
    /**
     * @dev Validates the active VERIFY frame and approves the transaction.
     *      Intended to be the call encoded in a VERIFY frame's `data`. The account
     *      selects an installed validator, obtains an approval mode from it, and masks
     *      that mode with the frame's allowed scope. It then checks the result against the
     *      approval modes it supports (`supportsApprovalMode`) and, when the execution
     *      bit is set, checks the transaction's SENDER frames against the execution modes
     *      it supports (`supportsExecutionMode`), before calling APPROVE with the result
     *      (see "EIP-8141 Frame Validator").
     * @param data validator selection and validator-specific calldata.
     * @return approvalMode the approval mode granted (also applied via APPROVE).
     *
     * MUST revert if the executing frame's mode is not VERIFY.
     * MUST NOT modify state other than via the APPROVE instruction; it executes within
     * the STATICCALL context of a VERIFY frame.
     * MUST NOT call APPROVE with a mode outside the frame's allowed scope.
     * MUST clear the execution bit if the transaction's SENDER frames present an
     * execution mode the account does not support (`supportsExecutionMode`, see
     * "SENDER Frame Execution Modes").
     * MUST NOT call APPROVE if validation fails (leaving the mode at APPROVE_NONE).
     */
    function verify(bytes calldata data) external returns (uint8 approvalMode);

    /**
     * @dev Returns whether the account supports a given approval mode.
     * @param approvalMode the approval mode (see "Approval Mode" above), a uint8
     *        bitmask in the range 0x0..0x3.
     *
     * MUST return true if the account is capable of granting this mode during
     * validation and false otherwise.
     */
    function supportsApprovalMode(uint8 approvalMode) external view returns (bool);
}

Execution

An EIP-8141 frame transaction executes operations over two routes:

  • Protocol-dispatched: a SENDER frame calls its target directly with caller = tx.sender. No account code takes part in the call, so the account has no execution-time enforcement point. Any policy over SENDER frames MUST be enforced at validation time, by the validator inspecting them before approving (see Security Considerations).
  • Contract-dispatched: DEFAULT frames are expected to target a dispatching contract — typically the tx.sender account — invoking ERC-7579’s execute or executeFromExecutor with caller = ENTRY_POINT. The account’s code performs the calls itself, and ERC-7579 execution semantics — execution modes, supportsExecutionMode, hooks — apply unchanged.

Note that this distinction is not enforced by the protocol and the SENDER frame’s target may be set to tx.sender as well.

This standard therefore defines no new execution interface: ERC-7579 already covers contract-dispatched DEFAULT frame execution, and no interface can cover SENDER frames.

An account MAY omit the execute and executeFromExecutor functions, supporting only the protocol-dispatched route.

An account that accepts execute calls in frame context MUST NOT authorize them by msg.sender == ENTRY_POINT alone. In EIP-8141 the ENTRY_POINT address as caller carries no authorization — unlike an ERC-4337 EntryPoint, which calls the account only after validating its user operation. The account MUST authenticate the call itself, by confirming that its own VERIFY frame in this transaction has succeeded (FRAMEPARAM(i, 0x05)), or by applying its ordinary ERC-7579 access control.

Rationale

Extension to ERC-7579 rather than a standalone standard

The value of a modular account standard is a portable module ecosystem: a validator, executor, or hook written once should work across accounts and wallets. Defining an independent module system for EIP-8141 would fork that ecosystem, forcing modules and tooling to choose between account abstraction implementations. Instead, this standard reuses ERC-7579’s module system unchanged and adds only the EIP-8141 validation flow.

This follows the upgrade path ERC-7579 describes for itself: as modular accounts are built on account abstraction implementations other than its original ERC-4337 target, the implementation-specific validation flow is moved into a separate, optional extension. This proposal is that extension for EIP-8141. The intended end state is ERC-7579 as the implementation-agnostic core module system, with per-implementation validation extensions layered on top.

Approval mode as the validation result

ERC-7579 standardizes a compact encoding for the execution side (its execution mode), letting an account express execution behavior in a single value. EIP-8141 provides the protocol-native counterpart for the validation side: the APPROVE scope. This standard surfaces validation results as that scope so the account never has to translate between a foreign validation-data encoding and the protocol’s own approval semantics. supportsApprovalMode complements ERC-7579’s supportsExecutionMode: the former declares which approval scopes the account can grant, the latter which execution shapes it will honor.

No new execution interface

ERC-7579’s execute is the point where an account enforces execution policy: it decodes the mode, checks the call type against supportsExecutionMode, and reverts if unsupported. Under EIP-8141 that flow can be reused on the contract-dispatched route: a DEFAULT frame calls the account’s execute, the account performs and checks the calls exactly as it would under ERC-4337.

On the protocol-dispatched route there is nothing to attach an interface to: the protocol calls a SENDER frame’s target directly — no account code is involved in making the call — and the only gate is the transaction-scoped sender_approved flag set once by APPROVE_EXECUTION.

For SENDER frames the enforcement point therefore moves entirely to the validation frames: a validator inspects the transaction’s SENDER frames during the VERIFY frame and only approves if they satisfy policy. supportsExecutionMode accordingly answers two kinds of query: for ordinary ERC-7579 modes it reports what the account’s execute can process, and for the frame modes defined in “SENDER Frame Execution Modes” it declares which frame shapes the account’s validators are willing to authorize — a policy enforced at validation time, not a capability checked at execution time.

Frame modes are policy declarations

The frame modes cover only the single/batch and atomic/non-atomic dimensions because the other ERC-7579 mode dimensions have no SENDER-frame counterpart: a SENDER frame is a plain protocol-orchestrated CALL, so there is no delegatecall analogue (account-level delegation exists only via EIP-7702 at the frame level), no staticcall analogue (the STATICCALL context in EIP-8141 is the VERIFY frame, not execution), and no room for custom modeSelector/modePayload semantics (the protocol owns dispatch).

The frame modes also describe a policy choice rather than a capability. In ERC-4337 an account must implement code to handle a batch, so supportsExecutionMode reports whether that code exists. Under EIP-8141 the protocol performs batching, atomicity, and dispatch with no account code, so every account is structurally capable of all of them; what an account or validator declares and enforces is which shapes it is willing to authorize (for example, refusing to approve a multi-frame transaction), not which it is able to perform.

Validator Selection

One recommended approach for accounts to select the validator module, where EIP-8250 keyed nonces are available, is to derive the validator from the keyed nonce, for example by interpreting the validator’s address as encoded in TXPARAM(0x0B) (nonce_keys[0]); because keyed nonces are committed by the canonical signing hash (TXPARAM(0x08)), this binds validator selection to the signed transaction.

Security Considerations

Execution is unconditional once approved

Granting APPROVE_EXECUTION (or APPROVE_EXECUTION_AND_PAYMENT) is a one-shot, transaction-wide authorization. After a VERIFY frame sets sender_approved, every subsequent SENDER frame in the transaction executes with caller = tx.sender and is not checked again. EIP-8141 consults no allow-list, target restriction, or execution-mode support on the account, and no account code mediates those calls. A validator that returns APPROVE_EXECUTION therefore authorizes arbitrary calls (arbitrary targets, values, and calldata) on the account’s behalf.

Because EIP-8141 provides no execution-time fallback for SENDER frames, all execution policy MUST be enforced at validation time. This includes both the account’s declared supportsExecutionMode set and any validator-level constraint (allow-list, spend limit, target restriction). Before granting APPROVE_EXECUTION, the account and its validator MUST inspect the transaction’s SENDER frames (their resolved target, value, and calldata) and MUST NOT approve if any frame presents an unsupported execution mode or falls outside policy. Frame contents are available during validation through EIP-8141’s introspection instructions (FRAMEPARAM, FRAMEDATALOAD, FRAMEDATACOPY); an account MAY surface them to the validator directly (see “EIP-8141 Frame Validator”). Validators SHOULD grant the narrowest sufficient approval mode rather than APPROVE_EXECUTION_AND_PAYMENT by default.

DEFAULT frames and the ENTRY_POINT caller

An EIP-8141 DEFAULT frame executes its target with caller = ENTRY_POINT and requires no prior approval, so any frame transaction can invoke the account’s code with that caller. EIP-8141 gates APPROVE on the executing frame’s resolved target and flags, not on its mode; only a VERIFY frame, however, runs under STATICCALL restrictions and invalidates the whole transaction when it reverts. An account MUST NOT take msg.sender == ENTRY_POINT as evidence that it is executing in a VERIFY frame: it MUST check the frame’s mode via FRAMEPARAM before approving, as required of verify (see “Account Interface”). Without that check, a DEFAULT frame targeting the account runs the validation flow without STATICCALL protection, and a failed validation reverts only that frame while the rest of the transaction proceeds.

The same caution applies to execution entrypoints: a DEFAULT frame can call the account’s execute with caller = ENTRY_POINT in a transaction the account never validated, so execute MUST NOT be authorized by caller identity alone (see Execution).

Validator trust

An installed validator is fully trusted with respect to the account: because approval is unconditional, a malicious or buggy validator that approves execution can drain or take over the account. Accounts MUST apply the same authorization control to installing a validator as to any other account-critical operation.

Copyright and related rights waived via CC0.

Citation

Please cite this document as:

Chiranjeev Mishra (@chiranjeev13), Pedro Gomes (@pedrouid), Alex Forshtat (@forshtat), "ERC-8286: Modular Accounts for Frame Transactions [DRAFT]," Ethereum Improvement Proposals, no. 8286, June 2026. Available: https://eips.ethereum.org/EIPS/eip-8286.