Skip to main content

ADR-009: BPK Registration Is Only for Autoshield (and Is Mutable)

StatusRejected
Date2026-03-12

Rejection Reason: The notion of BPK ownership is important for the UX. Each registered pair address -> BPK must be immutable and should be reference for the "autoshield" functionality.

Context

The current registerBPK() function associates an EVM address with a BPK on-chain. It is currently presented as serving two purposes:

  1. Autoshield — when an ERC-20 transfer()/transferFrom() targets an address with autoshield enabled, the contract looks up balanceKeys[address] to encrypt the amount.
  2. Address-to-BPK lookup — anyone can call getBPK(address) to discover a user's BPK.

Purpose (2) does not make sense. The EVM address owner and the BPK owner are independent — there is no on-chain proof that the registrant knows the secret key for the BPK they register. Anyone could register any BPK to their address. The mapping is not an identity claim; it's simply a configuration: "when this address receives an ERC-20, encrypt to this BPK."

For private transfers, the sender already knows the recipient's BPK before building the ZK proof (it's a public input to the circuit). BPK discovery happens off-chain — shared directly, via a directory, or via stealth address derivation. The on-chain registry is never used in this flow.

Additionally, registration is currently immutable — once set, a BPK cannot be changed (BPKAlreadyRegistered revert). This is unnecessarily restrictive. Since encrypted balances are keyed by hash(BPK) (not by EVM address), changing the autoshield BPK does not affect existing balances.

Proposal

Rename registerBPK() to registerAutoshieldBPK(), reframe it as purely an autoshield configuration, and make it mutable.

Changes:

  • registerAutoshieldBPK(bpk) sets (or updates) the BPK used for autoshield on msg.sender
  • Remove the BPKAlreadyRegistered check — allow overwriting
  • setAutoshield(enabled) remains unchanged — it toggles whether autoshield is active
  • getBPK(address) remains available but is understood as "the autoshield BPK for this address", not as an identity registry

What this enables:

  • Key rotation: User changes their autoshield BPK at any time, then unshields from the old BPK and re-shields to the new one at their convenience
  • Cleaner semantics: Registration is a setting, not an identity commitment
  • Simpler mental model: "Register" = "tell the contract where to autoshield my incoming tokens"

Consequences

What becomes easier:

  • Key rotation without deploying a new EVM address
  • Users aren't permanently locked into their first BPK choice
  • Simpler to reason about: registration = autoshield config, nothing more

What becomes harder:

  • Nothing meaningful — the immutability provided no real security guarantee since BPK ownership was never verified on-chain

Migration:

  • Remove the BPKAlreadyRegistered revert in registerAutoshieldBPK()
  • Optionally rename to setAutoshieldBPK() for clarity
  • No storage layout changes — balanceKeys mapping stays the same