ADR-009: BPK Registration Is Only for Autoshield (and Is Mutable)
| Status | Rejected |
| Date | 2026-03-12 |
Rejection Reason: The notion of BPK ownership is important for the UX. Each registered pair
address -> BPKmust 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:
- Autoshield — when an ERC-20
transfer()/transferFrom()targets an address with autoshield enabled, the contract looks upbalanceKeys[address]to encrypt the amount. - 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 onmsg.sender- Remove the
BPKAlreadyRegisteredcheck — allow overwriting setAutoshield(enabled)remains unchanged — it toggles whether autoshield is activegetBPK(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
BPKAlreadyRegisteredrevert inregisterAutoshieldBPK() - Optionally rename to
setAutoshieldBPK()for clarity - No storage layout changes —
balanceKeysmapping stays the same