Skip to content

[pallet-revive] EIP-7702 (continued)#12229

Draft
0xRVE wants to merge 188 commits into
masterfrom
rve/eip-7702
Draft

[pallet-revive] EIP-7702 (continued)#12229
0xRVE wants to merge 188 commits into
masterfrom
rve/eip-7702

Conversation

@0xRVE
Copy link
Copy Markdown
Contributor

@0xRVE 0xRVE commented May 29, 2026

Continuation of #10851.
evm-test-suite PR: paritytech/evm-test-suite#141

This PR implements EIP-7702 ("Set EOA Account Code") for pallet-revive, enabling Externally Owned Accounts (EOAs) to designate a contract whose code will be executed on their behalf when they are called.

What is EIP-7702?

#9569

EIP-7702 lets an EOA sign an authorization that says "when someone calls me, execute contract X's code". When a transaction includes these authorizations, any subsequent calls to the delegated EOA will execute the target contract's code — but using the EOA's own storage and balance. This enables smart account patterns (batching, gas sponsorship, etc.) without requiring account abstraction (ERC-4337) or proxy contracts.

For background:

Changes

Pallet integration

The eth_call dispatchable now accepts and processes an authorization list before executing the call.

The authorization_list parameter is a BoundedVec capped at limits::AUTHORIZATION_LIST_MAX (256). In normal operation the size is already constrained by the gas-validation logic in eth_transact (each entry costs at least worst_case_delegation_deposit), but the BoundedVec is a defense-in-depth bound for any future call path that might bypass that check. Oversized lists are rejected in into_call with InvalidTransaction::Call.

Note: Updating the eth_call signature is safe — it is not dispatched directly by users but is the inner call of eth_transact, which is signed by an Ethereum wallet and submitted via eth-rpc.

Authorization processing

The Transaction7702 type (with its authorization_list) was already defined and parsed; this PR adds the actual processing logic.

process_authorizations validates each entry (chain ID, signature, nonce, account type), creates the authority account if needed, and sets or clears the delegation. Invalid authorizations are silently skipped per spec.

Key semantics:

  • Authorizations always succeed. A type-4 transaction is only valid if the origin has enough gas to cover the worst case for every authorization entry. Processing itself cannot fail.
  • Authorizations are not reverted. If the transaction's call fails and its state changes revert, the delegation changes from authorization processing persist.

Revive-specific complexity. In Revive the per-authorization pre-dispatch weight/gas is higher than in EVM because:

  • An authorization can touch a new account, so the gas must cover the existential deposit (ED) for account creation.
  • Code is shared across contracts (same blob for init and runtime), so delegating to a contract requires a code lockup deposit and increments a refcount on the code hash to prevent deletion while delegated.

Storage changes

A new AccountType::DelegatedEOA variant is introduced:

  • delegate_target: Option<H160> — the contract address this EOA delegates to.
  • contract_info: ContractInfo — storage accounting (child trie, base deposit) for delegated EOAs.

Key behaviors:

  • Once delegated, an account transitions from EOA to DelegatedEOA permanently.
  • Clearing delegation sets delegate_target = None but the account stays DelegatedEOA.
  • Delegated EOAs get their own child trie for storage, keyed by the EOA's address (not the target).
  • Re-delegating to a different target preserves the child trie — storage survives across target changes.
  • Code refcounts are managed: setting delegation increments the target's code refcount, clearing it decrements.

Deposit lifecycle. Clearing a delegation refunds the storage_base_deposit (the code-lockup portion) but preserves the child trie and per-item storage accounting. To recover the per-item deposit, the user must re-delegate to a contract that lets them clear the stored items through the normal storage path.

Execution changes

During a call, the runtime resolves delegation:

  • If the callee is an EOA with a delegate_target, code is loaded from the target contract but execution uses the EOA's storage.
  • Constructors skip delegation lookup (cannot deploy via delegation).
  • No chain following. Delegation is resolved at most once. If A delegates to B and B delegates to C, calling A looks up code at B directly (without following B's delegation to C). If B is an EOA, calling A behaves like calling a plain EOA.

Benchmarks

  • process_new_account_authorization(n) — worst case: creates n new accounts with delegations.
  • process_existing_account_authorization(n) — best case: processes n authorizations for existing accounts (used for weight-refund calculation).

RPC integration

  • eth-rpc supports submitting and dry-running EIP-7702 transactions.
  • eth_getCode returns the 0xef0100 || address prefix for delegated EOAs (per EIP-7702 spec).

Tests

Test coverage includes:

  • Validation: invalid chain_id, nonce mismatch, duplicate signers, chain_id 0 wildcard, contract accounts rejected.
  • Delegation lifecycle: set, clear, re-delegate, delegation resolution during calls.
  • Storage persistence: re-delegation preserves storage across different targets; clear-then-redelegate preserves the trie and recovers read/write access to previously written state (storage_persists_across_clear_and_redelegate).
  • Deposit accounting: delegation charges, clearing refunds, re-delegation adjustments, code-refcount tracking, EOA → EOA delegations charge no deposit, multiple authorities to the same target each get their own deposit.
  • Edge cases: delegation chains not followed, SELFDESTRUCT preserves delegation, constructors skip delegation, delegation to nonexistent addresses is a no-op.

@0xRVE 0xRVE self-assigned this May 29, 2026
@0xRVE 0xRVE added T7-smart_contracts This PR/Issue is related to smart contracts. A5-run-CI Run CI on draft PR labels May 29, 2026
@0xRVE
Copy link
Copy Markdown
Contributor Author

0xRVE commented May 29, 2026

/cmd prdoc --audience runtime_dev --bump major

@0xRVE
Copy link
Copy Markdown
Contributor Author

0xRVE commented May 29, 2026

/cmd bench --runtime asset-hub-westend --pallet pallet_revive

@github-actions
Copy link
Copy Markdown
Contributor

Command "bench --runtime asset-hub-westend --pallet pallet_revive" has started 🚀 See logs here

@github-actions
Copy link
Copy Markdown
Contributor

Command "bench --runtime asset-hub-westend --pallet pallet_revive" has failed ❌! See logs here

@0xRVE
Copy link
Copy Markdown
Contributor Author

0xRVE commented May 29, 2026

/cmd bench --runtime asset-hub-westend --pallet pallet_revive

@github-actions
Copy link
Copy Markdown
Contributor

Command "bench --runtime asset-hub-westend --pallet pallet_revive" has started 🚀 See logs here

@github-actions
Copy link
Copy Markdown
Contributor

Command "bench --runtime asset-hub-westend --pallet pallet_revive" has finished ✅ See logs here

Details

Subweight results:
File Extrinsic Old New Change [%]
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs own_code_hash 4.93us 6.79us +37.76
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs instr 817.97us 1.07ms +30.27
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs seal_call_data_load 454.00ns 558.00ns +22.91
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs seal_now 444.00ns 543.00ns +22.30
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs seal_block_number 457.00ns 555.00ns +21.44
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs seal_call_data_size 428.00ns 508.00ns +18.69
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs seal_value_transferred 476.00ns 553.00ns +16.18
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs seal_return_data_size 448.00ns 520.00ns +16.07
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs seal_gas_limit 464.00ns 526.00ns +13.36
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs seal_caller 554.00ns 607.00ns +9.57
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs seal_address 539.00ns 589.00ns +9.28
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs caller_is_root 1.95us 2.13us +9.16
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs caller_is_origin 1.99us 2.15us +8.26
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs extcodecopy 41.94us 45.39us +8.21
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs seal_base_fee 1.45us 1.57us +8.12
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs bn128_add 18.20us 19.56us +7.43
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs seal_code_hash 30.98us 33.14us +6.98
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs seal_gas_price 1.43us 1.52us +6.80
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs minimum_balance 2.28us 2.43us +6.66
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs seal_origin 575.00ns 612.00ns +6.43
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs weight_left 2.07us 2.19us +6.05
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs seal_balance 5.45us 5.77us +5.72
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs get_transient_storage_full 2.16us 2.04us -5.87
substrate/frame/revive/src/weights.rs process_new_account_authorization 27.03ms Added
substrate/frame/revive/src/weights.rs process_existing_account_authorization 13.52ms Added
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs process_new_account_authorization 176.30ms Added
cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs process_existing_account_authorization 171.66ms Added
Command output:

✅ Successful benchmarks of runtimes/pallets:
-- asset-hub-westend: ['pallet_revive']

@paritytech-workflow-stopper
Copy link
Copy Markdown

All GitHub workflows were cancelled due to failure one of the required jobs.
Failed workflow url: https://github.com/paritytech/polkadot-sdk/actions/runs/26634359844
Failed job name: test-linux-stable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A5-run-CI Run CI on draft PR T7-smart_contracts This PR/Issue is related to smart contracts.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants