Cross-Chain Account Portability
TL;DR
EIP-8130 defines two portability primitives. First, the same CREATE2 inputs can produce the same account address on each chain where the Keystore infrastructure is deployed consistently. The account still has to be deployed separately on every chain where it will execute. Second, chain_id = 0 makes one signed account change valid for replay against each deployment's multichain sequence counter. A wallet or relayer must submit that payload on every chain; the protocol does not broadcast or synchronize it.
Both ideas trace back to the original submission, PR #11186. “Portable” means address-deterministic and replayable, not globally deployed or automatically synchronized. Account Lock is local-only and can block an update on one chain, while multichain actor-change messages carry no message-level expiry by design.
1. The Problem Being Solved
A plain EOA is already cross-chain portable by accident: the address is a function of a public key, not of any per-chain contract state, so the same secp256k1 key authenticates identically everywhere (aside from chain_id domain separation). Smart accounts break this. Their owner/signer configuration lives in per-chain contract storage, so rotating a key or adding a new signer means resending a separately signed, separately paid transaction to every chain the account has ever been deployed on, and it is easy to miss one.
EIP-8130's own Abstract frames the design goal directly: "the contract infrastructure is designed to be shared across chains as a common base layer for account management" (per the spec's Abstract section). The two mechanisms below are how that claim is actually implemented.
2. Primitive 1: Deterministic CREATE2 Addressing
Account addresses are derived as:
leaf_i = keccak256(encode(initial_actor_i))
actors_commitment = keccak256(leaf_0 || leaf_1 || ...)
effective_salt = keccak256(user_salt || actors_commitment)
deployment_code = DEPLOYMENT_HEADER(len(code)) || code
address = keccak256(0xff || KEYSTORE_ADDRESS || effective_salt || keccak256(deployment_code))[12:]The per-actor leaf hashing landed in PR #12135. The user-controlled salt, sorted initial-actor commitment, and bytecode are chain-independent. If KEYSTORE_ADDRESS is also identical, the same inputs produce the same address on every chain. Code and storage remain chain-local, and the account must still be created where it will execute.
The guarantee remains conditional on deploying the Keystore at the same address everywhere. PR #12135 makes the canonical Base contracts authoritative for deployment mechanics, but the cross-chain address claim still depends on coordinated deployment rather than a global protocol invariant.
Freshness matters too: a create entry only applies against a CREATE2-fresh address (code_size(sender) == 0 && nonce(sender) == 0), a check tightened by community contributor pochenai's PR #11609 (merged June 2, 2026) to match CREATE2 semantics exactly, closing a path where a create entry could otherwise be replayed against a counterfactual address that already had transaction history.
3. Primitive 2: The chain_id = 0 Config-Change Channel
Every account tracks a monotonic multichain sequence plus a local epoch and sequence, packed into account state:
struct ChangeSequences {
uint64 multichain; // chain_id 0
uint32 localEpoch;
uint32 localSequence;
}PR #12135 replaced the actor-only function with one signed-change entry point:
function applySignedAccountChanges(address account, SignedAccountChanges calldata changes, bytes calldata auth) external;The Multichain channel targets chain_id = 0 and binds against multichain_sequence. The Local channel binds to the current chain and packs its epoch and sequence into a signed uint64. Local UNSEQUENCED changes can land in any order within an epoch, while IncrementLocalEpoch invalidates any that remain unlanded. The multichain channel stays strictly ordered.
The mechanism is deliberately simple: nothing bridges or broadcasts the message. An owner signs one multichain update, and a relayer or wallet submits that payload to each Keystore deployment. Each chain checks its own sequence and applies the change independently. Because the Keystore is callable during ordinary EVM execution, propagation does not require native EIP-8130 transaction support, only compatible contracts.
Config-change authority remains the admin predicate (scope == 0x00). Lock and Unlock now share applySignedAccountChanges with actor changes, but they are local-channel operations. Lock state is therefore still per chain and cannot be set or cleared by a multichain message.
This cross-chain intent is not a late addition. The first merged submission, PR #11186, already carried portable key_changes. PR #11367 unified mutation under account_changes; PR #11764 renamed owners to actors and introduced applySignedActorChanges; PR #12135 replaced that function with applySignedAccountChanges and the local epoch. The multichain sequence remained ordered throughout.
Degrading gracefully on non-8130 chains
The same portability story extends to chains that have not adopted EIP-8130 as a native protocol feature, per the spec's own Portability comparisons:
| Component | EIP-8130-native chain | Non-8130 chain (EVM only) |
|---|---|---|
| Keystore | Same contract, also recognized by node-level mempool/validation rules | Standard ERC-4337-compatible contract, same address and bytecode |
| Nonce tracking | Nonce Manager precompile | "Existing systems (e.g., ERC-4337 EntryPoint)" |
| Code delegation | Delegation entry in account_changes, EOA-only authorization in this version | "Standard EIP-7702 transactions (ECDSA authority)" |
| Multichain config changes | applySignedAccountChanges | Same function, callable as ordinary EVM execution, no AA_TX_TYPE support required |
4. What This Enables
- One address, deployed lazily per chain. A wallet can hand out one counterfactual address and place code only on the chains a user actually uses.
- One signature, multiple submissions. Rotating an admin actor, adding a session key, or revoking a compromised key needs one
chain_id = 0signature, but still requires a transaction or relayed call on each deployment. - Existing multi-chain smart accounts can opt in.
importAccount()lets an already-deployed account (e.g. an ERC-4337 wallet) bootstrap into the same actor/authenticator model via an ERC-1271 signature over a digest that itself carrieschainId(0 or local), joining the same multichain channel going forward. Import is a one-time hook, though: it requires both sequence channels to be zero, so it only applies once per address and does not itself link accounts that were deployed at different addresses on different chains before EIP-8130 existed.
A related but distinct discussion on the EthMagicians thread is worth noting for context. Starting at post #12 (karlb, June 5, 2026), karlb and chunter-cb worked through how a chain could set a default authenticator at the protocol level to let existing Celo CIP-64 accounts adopt EIP-8130 semantics "without modifying the state of all user accounts" (post #12), eventually converging (posts #19-#22, June 29-July 8, 2026) on an RPC-shim migration path and a transaction-type renumbering (0x7b/0x7c to 0x79/0x7a) to avoid colliding with CIP-64's existing OP Stack allocation. That is a migration-continuity problem, not the chain_id = 0 replay mechanism described above, but it reflects the same underlying design pressure: making an account's identity and configuration survive a system transition without touching every account individually.
Base's July 17 Native Account Abstraction announcement turns that portability claim into an adoption commitment. The current Cobalt upgrade page lists both Sepolia and mainnet in planning for September 2026. This is a rollout plan, not evidence that cross-chain configuration is already operating in production.
5. Contrast: The Alternatives Don't Address This
| Proposal | Cross-chain account portability |
|---|---|
| EIP-8141 | Frame Transaction — Frame modes, APPROVE, and the default-code EOA are all chain-local concepts; no config-propagation or address-portability mechanism appears in its spec |
| EIP-8175 | Composable Transaction — Ed25519 EOAs derive new addresses under its own scheme, but nothing propagates an account's signer configuration across chains |
| EIP-8202 | Scheme-Agile Transactions — scheme-agility applies to sender authentication at the transaction layer, not to account-configuration continuity across chains |
| EIP-8223 | Contract Payer Transaction — a single-chain payer-registry predeploy; not an account-portability proposal at all |
| EIP-8224 | Counterfactual Transaction — a ZK shielded-funding mechanism for gas privacy; not an account-portability proposal |
| EIP-XXXX (Tempo-like) | Fixed UX primitives (batching, validity windows, 2D nonces, passkeys); no cross-chain propagation feature is documented |
This is an absence, not a rebuttal: EIP-8130's own spec text draws zero explicit comparison to any of these six proposals (a full-text search of the spec turns up no mention of "8141" or the others), so this table reflects what each proposal's own spec does and does not describe, not a claim made by any of the proposals about each other. Among these six proposals, EIP-8130 is the only one whose base spec defines a mechanism for propagating an account's owner/actor configuration across chains without a bridge.
6. Limits and Risks
No message-level expiry on multichain changes, by design. Community contributor pochenai's PR #11612 flagged this as concern C3. Author chunter-cb rejected the proposed expiry as intentional: multichain changes are meant for full owners, while local changes cover per-chain policy. A chain_id = 0 update can therefore remain replayable on a future deployment if its expected sequence matches. Nothing applies it automatically, and an actor's own expiry is a separate liveness field rather than an expiry for the signed change message.
Lock is local, so propagation can silently stop at one chain. The following is editorial analysis built on the sourced mechanics above. Because Lock and Unlock use the local channel, a multichain update can succeed everywhere the account is unlocked and fail on a separately locked deployment. The owner may only discover the gap operationally.
Sequence counters require ordered catch-up. This is editorial analysis. A signature commits to one sequence value. If one deployment misses an update, a later signature for the advanced sequence is rejected there until the missing earlier update is submitted. If the older payload is unavailable or blocked by local lock state, the protocol provides no automatic reconciliation mechanism.
Propagation is relay, not push. Nothing in the sourced spec text describes a bridge, keeper network, or broadcast mechanism for chain_id = 0 messages. That is a real strength, no cross-chain messaging trust assumption is introduced, but it also means the entire portability guarantee depends on some party, the owner or a relayer, actually submitting the same payload to every chain the account exists on. A relayer that simply fails to reach one chain looks, from the account holder's perspective, identical to no problem at all until that chain is checked.
Summary
EIP-8130 treats cross-chain account portability as a first-class design goal. Deterministic CREATE2 inputs can preserve an address across consistently deployed infrastructure, and chain_id = 0 lets one signature authorize the same ordered actor change on multiple deployments. Neither feature creates global state: deployment, relaying, fees, sequence catch-up, and lock state are all per chain. “Portable” describes reproducible addresses and replayable authorization, not automatic synchronization.
See Authenticator Model for how actors and authenticators work within a single chain, or EIP-8141: Frame Transaction for the comparison point this doc leans on most.