Seed-recovered Guardian account can be permanently locked behind its own rotation gate
- Linguagem predominante
- TypeScript
- Estrelas
- 5
- Forks
- 28
- Merge médio
- 9h 50min
- PRs com merge (30d)
- 123
Descrição
**Trigger:** [protocol#3765](https://github.com/0xMiden/protocol/pull/3765) · **Status:** research / design decision needed
**Not reachable in production today** — see "When this lands".
## Symptom
Recovering a Guardian wallet from its seed phrase on a fee-charging chain can leave the
wallet permanently unusable when the recovered account's vault holds no native asset.
## Why
Three things are individually reasonable and together form a cycle:
1. A seed-only recovery cannot recover the device-bound hot key, so the recovered account
always carries `requiresHotKeyRotation` (`HotKeyRotationGate.tsx`).
2. That gate is a **full-app blocking overlay**. Its own doc: accounts carrying the flag
*"have no usable local hot key and cannot sign, sync, or transact until a `replace_signer`
rotation lands"*, and the gate *"paints a full-screen overlay that blocks all wallet
interaction"*.
3. Since protocol 0.16 the fee is paid inside the auth procedure from the acting account's
own vault. With protocol#3765 the guarded-multisig auth calls `fee::pay_fee`, so the
rotation is a **paid** transaction.
An account with an empty vault therefore cannot pay for the one transaction it is allowed to
make, and cannot make any other transaction to fund itself.
The usual escape from Miden's empty-vault bootstrap — consuming a note credits the vault
before `pay_fee` withdraws, so a claim funds itself — does **not** apply: claiming needs the
hot key, which is exactly what is missing.
## Observed
`guardian-seed-backup-verify` on a localnet at `verification_base_fee = 10000`:
failure
```
[replace-hot-key 8760567b stage=creating-proposal]
Error: failed to execute transaction at anchor: transaction execution failed:
failed to execute transaction kernel program:
assertion failed with error code: 644413868907058392
```
`644413868907058392` decodes to *"failed to remove the fungible asset from the vault since
the amount of the asset in the vault is less than the amount to remove"* — i.e. the fee
withdrawal, against an empty vault. The conversion info IS committed correctly; the account
simply cannot pay.
## When this lands
Not reachable today. The **published** guarded-multisig auth component contains no
`exec.fee::pay_fee`, so a guarded rotation currently moves no assets and costs nothing. This
becomes reachable the moment protocol#3765 ships, which makes it a question to settle
**before** that merges rather than after.
## Verified vs. inferred
Verified: the gate blocks all interaction (source); seed recovery always sets the flag
(source); the rotation fails with a vault-insufficient kernel assertion on a fee-charging
chain (observed, decoded); published guarded multisig has no `pay_fee` (source).
**Inferred, not tested:** that a user cannot escape by having someone send them MIDEN — it
follows from "no hot key ⇒ cannot sign a claim" plus the blocking overlay, but no one has
driven that path. **That is the first thing to check**, because if a background auto-consume
can claim while gated, the severity drops from "locked out" to "confusing wait".
## Directions (unevaluated)
- Let the gate expose receive/claim before the rotation, if a claim is signable without the
hot key. Cheapest if the inference above is wrong.
- Defer the gate: allow read-only use, and prompt for the rotation once the vault can pay.
- Sponsor the rotation, as `fees::collect_sponsored_fees` already does for network accounts —
a protocol/standards decision, not a wallet one.
- Have the guardian pay or co-fund the rotation.
- Detect the unpayable case and say so. Today the wallet surfaces the raw kernel string;
`TRANSACTION_FEE_UNPAYABLE_ERROR` exists but this path does not route through it, so the
user is told nothing actionable even in the recoverable case.
## Reviewers
The inference in "Verified vs. inferred" is the load-bearing part — if a gated account can
still claim, most of this dissolves.
Guia de contribuição
Direção de pesquisa
First, verify if a gated account can still claim notes without the hot key by examining the claim signing logic in the wallet code. Look at the HotKeyRotationGate component and the guarded-multisig auth flow. Check the fee payment mechanism in the protocol, especially after protocol#3765. The goal is to confirm whether the account is permanently locked or can receive funds to pay the rotation fee.
Escrita pelo modelo de indexação a partir do texto da issue.
Avaliação
- Stack de tecnologia
- rust, typescript
- Domínio
- backend, blockchain, security
- Tipo de issue
- Bug
- Dificuldade
- 4/5
- Tempo estimado
- 3-5 dias
- Status de atividade
- Ativa
- Clareza
- Razoavelmente clara
- Facilidade para iniciantes
- 45/100