Repository navigation
Import an account by address when its key cannot be derived from the phrase #398
Description
Problem
Split out of #378 as tier 3, and it applies equally to Ready — see #377.
Measured on Mainnet, the phrase alone finds roughly half of real accounts:
| family | discoverable from the phrase alone |
|---|---|
| Braavos | 72/150 (48.0%) |
| Ready / Argent | 81/150 (54%) |
(Corrected 2026-09-21: the Ready row originally read 64/150 (42.7%). That run missed the
constructor shapes Argent 0.4.0 uses. See the correction on #377.)
The remainder are not recoverable from the phrase alone, because their address is not a function
of the phrase. The reason differs by family:
- Braavos: the deploy salt was not the public key, or the signing key was rotated after
deployment. - Ready: mostly a guardian. The guardian is part of the constructor calldata, so it is part of
the address, and it differs per account. 46 of the 69 undiscoverable Ready accounts in the
sample are guardian-ed 0.4.0 accounts that reproduce exactly once the address is known.
No set of class hashes and no index changes that.
For those accounts there is exactly one thing the user can supply that closes the gap: the
account address. They know it — it is in their other wallet, on an explorer, in a transaction
they sent.
Proposed solution
Let a user import an account by pasting its address, and prove control rather than assume it:
- derive the candidate keypairs from the phrase across the scanned index range;
- read the account's owner/signer public key on chain;
- import only if a derived public key matches what the chain reports.
The match is what makes this safe. Without it a user could import an address they do not
control, and the wallet would display a balance it can never move.
Why this is not just a text field
- The public key is read differently per family and per class. Braavos answers
get_public_key; Argent 0.3.x answersget_owner/get_signer. Argent 0.4 answersget_owner
with the raw Stark key whenget_owner_typereports a Stark signer. The wallet already relies
on that pair inrequireCompatibleArgentSigner, and any other owner type must be refused.
(Corrected 2026-09-21: this line originally suggested 0.4 might return a GUID rather than the
key. It does not, for a Stark owner.) Each family and version needs a reader that knows what
it is reading, and a mismatch must fail closed rather than be compared as if it were a key. - A public-key match proves control only for a single-signer account. With Braavos 2FA, an
Argent guardian, or any hardware co-signer, the phrase holds one of several required keys: the
match succeeds and signing still fails. Detection has to happen before import — see Read-only imported accounts for signer configurations the phrase cannot satisfy #395. For
Ready this is the common case, not the edge: most accounts this issue exists to recover have a
guardian, and the wallet refuses to sign for any Argent account with one. Without Read-only imported accounts for signer configurations the phrase cannot satisfy #395 they can
be found, but not usefully imported. - Signing still needs a supported class. Recovering the address is necessary but not
sufficient; the wallet has to build a valid signature for whatever class the account runs.
Accept classes from the known published set, never "whatever is deployed", or we sign for a
contract nobody vetted.
Open questions
- What does the user paste, and how forgiving is it? An address is 64 hex characters that all
look alike. Mistyping one is silent — the lookup simply finds nothing. Worth considering paste
from clipboard, an explorer URL, or a QR. - How far do we scan for the matching index? The key could be at any HD index. The recovery
scan already has bounds (RECOVERY_SCAN_LIMITS); reuse them rather than inventing a second
limit. - What do we say when nothing matches? "This phrase does not control that account" is the
honest message, but it is also what a user sees when they mistyped, or when the account has an
extra signer. Those need distinguishing.
Scope
Both families in one flow. The only per-family part is how the owner key is read; the rest — the
derivation, the comparison, the refusal — is shared. Building it for one family and retrofitting
the other is how the two drift.
Target release / milestone
TBC at triage.
Activity
feat: scan every Argent release during recovery discovery
derek-flossman commentedon Oct 26, 2026
Status update (AI-assisted triage by Claude), posted from @derek-flossman's account.
Proposed design (needs owner sign-off; size M–L):
get_owner+ owner type = Starknet; Braavos first stark signer), derive keys over both ladders within the scan limits, and import only on an exact match.Related: #743 and #756 are likely in this bucket. #734 (Xverse) is in PR #763.
recovery: confirm import-by-address ownership with two chain-checked …
recovery: keep the address finder busy for the whole search
Explain http:// explorer links instead of calling them invalid
Document the SNF-operated trust assumption; tighten owner readings
Point a pasted Bramble OpenZeppelin account at Find my accounts
accounts: hold Ready-key import and discovery to the authorizing session
chore: satisfy colour-token, dead-code and format gates for #777 fixes
Merge pull request #781 from starknet-innovation/feat/398-import-by-a…
derek-flossman commentedon Oct 27, 2026
Fixed by #781, merged into release/v0.10.8. Ships in v0.10.8.