Skip to content

Make the EIP-7702 derivation path fully customizable (chain-scoped) - #25

Merged
zy0n merged 3 commits into
mainfrom
feat/7702-customizable-path
Jul 24, 2026
Merged

Make the EIP-7702 derivation path fully customizable (chain-scoped)#25
zy0n merged 3 commits into
mainfrom
feat/7702-customizable-path

Conversation

@zy0n

@zy0n zy0n commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Makes the RAILGUN Ledger EIP-7702 auth-signing derivation path fully caller-customizable while keeping it chain-scoped.

Model

The 7702 EOA is derived at m/…/7702'/W0'/W1'/W2' with W0 = account, W1 = chainId, W2 = ephemeralIndex. chainId stays in the path, so each chain yields a distinct EOA — a wallet can operate on multiple chains at once without reusing a 7702 address. (Device-verified: slot (0,0,0) and (0,1,0) derive different addresses.)

Changes

  • get7702Signer now honors a custom railgunAccountIndex (optional on Railgun7702SignerRequest, defaulting to the signer's account). This was the one place the account was hard-coded; every other entry point (prepareEthereumSigner, the engine signer provider, the controller) already threaded all three words, so the whole stack is now fully customizable.
  • Chain-scoping guard: when an explicit path is passed to signEip7702Authorization, its chainId word (W1) must equal the authorization's target chainId — so a path can't derive one chain's EOA while authorizing on another. Session/fallback paths are built from the chainId and are unaffected.
  • Docs: each path word is a hardened BIP-32 index and must fit in 31 bits, so EVM chains with chainId >= 2**31 are rejected fail-closed (never collapsed onto another chain's slot).

Tests

  • get7702Signer override wins over the signer's account (a revert to the hard-coded account now fails).
  • Distinct chain-scoped suffix per chain; account/index independent, caller-customizable.
  • Explicit path whose W1 differs from the auth chainId is rejected.

Reviewed (correctness + security); typecheck + lint clean; full suite green. The signing paths are device-verifiable with scripts/probe-clear-sign-v1.ts.

zy0n added 3 commits July 24, 2026 18:13
The EOA path is [account(W0), chainId(W1), ephemeralIndex(W2)] — chainId is
part of the derivation, so each chain yields a distinct EOA and a wallet can
operate on multiple chains at once without reusing a 7702 address.

All three words are already caller-settable through prepareEthereumSigner, the
engine signer provider, and the controller; the one gap was get7702Signer,
which hard-coded the account. Expose it via an optional railgunAccountIndex on
Railgun7702SignerRequest (defaulting to the signer's account). Lock the
chain-scoped, per-word-customizable behavior with a multi-chain unit test.
Address review of the customizable-path change:
- Add a get7702Signer test that a custom railgunAccountIndex overrides the
  signer's own account (the branch the change exists to enable) — a revert to
  the hard-coded account would now fail the suite, not pass silently.
- Document that each path word (account/chainId/ephemeralIndex) is a hardened
  BIP-32 index and must fit in 31 bits, so EVM chains with chainId >= 2**31 are
  rejected fail-closed (never collapsed onto another chain's slot).
…th chainId

Defense-in-depth for chain-scoping: when a caller passes an explicit derivation
path to signEip7702Authorization, assert its chainId word (W1) equals the
authorization's target chainId, so a path can't derive one chain's EOA while the
authorization targets another. Session and fallback paths are built from the
chainId and are unaffected.
@zy0n
zy0n merged commit 5ca6eb1 into main Jul 24, 2026
3 checks passed
@zy0n zy0n mentioned this pull request Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant