Aere Network public source. Everything here can be checked against the live chain (chain id 2800, https://rpc.aere.network). Scope note, stated up front rather than buried: consensus on chain 2800 is classical secp256k1 ECDSA QBFT. The post-quantum work in this repository is at the signature, precompile, account and transport layers. Nothing here makes the consensus post-quantum, and no document in it should be read as claiming so.
307 lines
17 KiB
Markdown
307 lines
17 KiB
Markdown
# Aere Quantum Migration: Accounts and Network Keys
|
|
|
|
Status: user account migration is REAL and TESTED (contract + Hardhat suite,
|
|
below). Network key rotation is DESIGN ONLY and founder + audit gated. This
|
|
document is the last quantum-resistance layer at the key-management level (quantum
|
|
layer 11), and it is honest about which half is a user-callable contract today and
|
|
which half is a gated network operation.
|
|
|
|
Scope boundary, stated once and never crossed in this document: moving an account
|
|
(or a network operator) from a classical ECDSA key to a post-quantum key changes
|
|
who can authorize. It does NOT make Aere consensus post-quantum. Mainnet chain 2800
|
|
still seals blocks with classical secp256k1 QBFT, and the on-chain ZK verifiers
|
|
(BN254 Groth16) are classical. Validator-key rotation to a post-quantum scheme is
|
|
therefore coupled to the separate, gated consensus-PQC activation, not implied by
|
|
anything here.
|
|
|
|
Two flag conventions are used throughout:
|
|
|
|
- `[VERIFY]` a claim that should be confirmed against live chain state or a
|
|
deployment record before it is relied on.
|
|
- `[MEASURE]` a number or outcome that depends on a measurement or an operational
|
|
run that has not been performed here.
|
|
|
|
---
|
|
|
|
## Part A. User account migration (real, tested)
|
|
|
|
### A.1 Why migrate at all: harvest-now-decrypt-later
|
|
|
|
An Aere externally-owned account (EOA) is authorized by a secp256k1 ECDSA key. Two
|
|
facts make that a long-term liability once a cryptographically relevant quantum
|
|
computer exists:
|
|
|
|
1. ECDSA over secp256k1 is broken by Shor's algorithm. A sufficiently large
|
|
quantum computer recovers the private key from the public key.
|
|
2. An EOA reveals its public key the first time it sends a transaction (the public
|
|
key is recovered from the signature). So the exposure is not hypothetical for
|
|
any account that has ever transacted; the key material an attacker needs is
|
|
already on chain.
|
|
|
|
The threat is not "funds move today." It is "an adversary records the chain now and
|
|
breaks the keys later." That is the harvest-now-decrypt-later threat applied to
|
|
account authorization: long-dormant, high-value holdings sitting under a classical
|
|
key are exactly the accounts most worth attacking on a horizon of years. The
|
|
mitigation is to move such holdings, while the classical key is still safe, onto an
|
|
account whose spending authority is a post-quantum key.
|
|
|
|
Aere already ships the destinations for that move as live primitives. What was
|
|
missing, and what this document delivers, is a clean, no-custody path to perform
|
|
the move. That gap is quantum layer 11 in `aerenew/build-tracker/control.json`.
|
|
|
|
### A.2 The destinations: Aere's live post-quantum account primitives
|
|
|
|
The migration does not invent a new account type. It targets the ones Aere already
|
|
runs:
|
|
|
|
| Primitive | What it is | Auth | Status |
|
|
|---|---|---|---|
|
|
| `AerePQCAccount` | ERC-4337 v0.7 smart account owned solely by a NIST Falcon-512 key (897-byte pubkey) | Falcon-512 only, no ECDSA fallback | live sample `0xa42a5e7F...4326f` `[VERIFY]` |
|
|
| `AerePQCAccountFactory` | CREATE2 factory; account address is a pure function of (falconPubKey, salt) | n/a (permissionless deploy) | live `0xd5315Ea7...CE58` `[VERIFY]` |
|
|
| `AereHybridAuth` | Defense-in-depth: authorizes only if BOTH an ECDSA leg and a Falcon-512 leg verify over the same 32-byte hash | ECDSA AND Falcon-512 | repo source, no mainnet address `[VERIFY]` |
|
|
| `AereFalcon512Verifier` | Live Solidity Falcon-512 verifier the accounts delegate to | n/a | live `0x4E8e9682...D8fFC` `[VERIFY]` |
|
|
| `AerePQCKeyRegistry` | Proof-of-possession key registry | n/a | live `0x1eCa3c5A...3691` `[VERIFY]` |
|
|
|
|
Two destination shapes matter for a holder:
|
|
|
|
- PQC account (Falcon-512 only). Spending authority becomes a single lattice key.
|
|
Strongest post-quantum posture, but there is no ECDSA fallback: lose the Falcon
|
|
key and the account is gone. Register the key in `AerePQCKeyRegistry` and set PQC
|
|
social-recovery guardians BEFORE moving material value.
|
|
- Hybrid account (ECDSA + Falcon-512, via `AereHybridAuth`). Transition-era: an
|
|
attacker must break BOTH secp256k1 and Falcon-512. Good for a staged move while a
|
|
holder still wants a classical leg. `AereHybridAuth` is repo source with no
|
|
mainnet address as of 2026-07-19, so standing it up is a founder/deployer step
|
|
`[VERIFY]`.
|
|
|
|
The counterfactual address of a Falcon key's PQC account is pure CREATE2 math and
|
|
can be derived off-chain (see the migration toolkit, `aerenew/pqc-migration-toolkit`,
|
|
`predictPqcAccountAddress`, verified there against the live sample account). The
|
|
account can receive assets at that address before it is deployed, and be deployed
|
|
later via `createAccount`, which is permissionless and idempotent.
|
|
|
|
### A.3 The contract: `AereAccountMigrator`
|
|
|
|
File: `aerenew/contracts/contracts/pqc/AereAccountMigrator.sol` (solc 0.8.23,
|
|
OpenZeppelin SafeERC20 + ReentrancyGuard).
|
|
|
|
It is a pure conduit that atomically moves a caller-specified set of ERC-20
|
|
balances, and optionally native AERE, from the caller (the old EOA) to a
|
|
destination post-quantum account, in one transaction authorized by the caller's
|
|
ECDSA key. Two entrypoints:
|
|
|
|
- `migrate(destination, tokens[], amounts[], moveNative)`: move to an explicit
|
|
destination address.
|
|
- `migrateToPqcAccount(factory, falconPubKey, salt, expectedDestination, tokens[], amounts[], moveNative)`:
|
|
DERIVE the destination from a Falcon-512 key via the live
|
|
`AerePQCAccountFactory.predictAddress`, so the holder gets cryptographic
|
|
assurance they are sweeping into the post-quantum account their Falcon key
|
|
controls, and nowhere else. `expectedDestination` is an optional guard: if
|
|
non-zero it must equal the derived address, else the call reverts.
|
|
|
|
A read-only `predictPqcAccount(factory, falconPubKey, salt)` lets a frontend
|
|
confirm the destination before signing.
|
|
|
|
#### Authorization: pre-approval, or EIP-7702
|
|
|
|
The move is authorized by the caller's classical ECDSA key. The migrator does not
|
|
invent an authorization scheme; it uses ordinary ERC-20 allowances. Two supply
|
|
patterns, both documented:
|
|
|
|
1. Pre-approval (default, works today, no protocol feature). The holder sends one
|
|
`approve(migrator, amount)` per ERC-20, then calls `migrate`. Each
|
|
`safeTransferFrom` consumes the allowance and moves the tokens straight to the
|
|
destination.
|
|
2. EIP-7702 delegation (single-transaction UX). Aere supports EIP-7702 (see
|
|
`aerenew/docs/AERE-EIP-COMPATIBILITY-MATRIX.md`, row 7702 "Supported", the
|
|
EOA-delegation primitive Aere carries in place of EIP-3074). The EOA can, in one
|
|
transaction, temporarily set its account code to a batching delegate that both
|
|
approves and calls `migrate`, removing the separate approve transactions. The
|
|
migrator is agnostic to which pattern is used; under EIP-7702 the caller is
|
|
still the EOA and every invariant below is unchanged.
|
|
|
|
#### No custody, no admin (the core safety property)
|
|
|
|
- In `migrate` the caller is the `from` of every `SafeERC20.safeTransferFrom`, and
|
|
the caller-specified `destination` is the `to`. Tokens move caller to destination
|
|
in one hop. The migrator is never the recipient, so it never holds an ERC-20
|
|
balance.
|
|
- Native AERE (`msg.value`) is forwarded, in full, to that same `destination`,
|
|
inside the same call, guarded by `nonReentrant`.
|
|
- There is no owner, no admin, no upgrade, no initializer. There is no withdraw,
|
|
rescue, or sweep function, so anything accidentally sent to the migrator can
|
|
never be pulled out by anyone (stuck-but-safe, not drainable).
|
|
- There is no code path that sends value to any address other than the
|
|
caller-specified destination.
|
|
|
|
#### Fail-closed and atomic
|
|
|
|
- `destination` must be non-zero (`ZeroDestination`).
|
|
- Token and amount arrays must be equal length (`LengthMismatch`); each token
|
|
non-zero (`ZeroToken`); each amount non-zero (`ZeroAmount`).
|
|
- Native is strict: `moveNative` true requires non-zero `msg.value` (`ZeroNative`);
|
|
any `msg.value` sent while `moveNative` is false reverts (`StrayNative`), so value
|
|
can never be stranded. An empty request (no tokens, no native) reverts
|
|
(`NothingToMigrate`).
|
|
- A single failing transfer reverts the WHOLE transaction (SafeERC20 reverts on a
|
|
false/failing ERC-20), so the migration is all-or-nothing. It can never leave a
|
|
holder with a partially drained old account.
|
|
|
|
#### The `Migrated` event
|
|
|
|
`Migrated(address indexed oldAccount, address indexed newAccount, address[] tokens, uint256[] amounts, uint256 nativeAmount)`
|
|
binds the old classical account, the new post-quantum account, and the exact asset
|
|
set that moved. This is the on-chain, auditable record of a migration.
|
|
|
|
### A.4 The user flow
|
|
|
|
1. Choose a destination. Generate (or reuse) a Falcon-512 key; derive its
|
|
counterfactual `AerePQCAccount` address off-chain (toolkit
|
|
`predictPqcAccountAddress`, or the on-chain view `predictPqcAccount`). For a
|
|
hybrid transition, register an `AereHybridAuth` identity instead.
|
|
2. Prepare recovery FIRST. If the destination is Falcon-only, register the key in
|
|
`AerePQCKeyRegistry` (proof-of-possession) and set PQC social-recovery
|
|
guardians before moving material value. A Falcon-only account has no ECDSA
|
|
fallback.
|
|
3. Approve. From the old EOA, `approve(migrator, amount)` per ERC-20 (or bundle the
|
|
approvals with the migrate via EIP-7702).
|
|
4. Migrate. Call `migrateToPqcAccount(...)` (recommended, destination is bound to
|
|
your Falcon key) or `migrate(destination, ...)`. One transaction moves the
|
|
whole asset set plus optional native AERE to the destination. The `Migrated`
|
|
event is your receipt.
|
|
5. Deploy the account when convenient. `AerePQCAccountFactory.createAccount` is
|
|
permissionless and idempotent; the account can be deployed before or after the
|
|
assets arrive at its counterfactual address.
|
|
|
|
The migration toolkit (`aerenew/pqc-migration-toolkit`) is the companion that
|
|
scans an account's quantum exposure (RED/YELLOW/GREEN), derives the destination
|
|
address, and prints a step-by-step plan and a gas estimate. This contract is the
|
|
on-chain executor for step 4.
|
|
|
|
### A.5 Test result (real)
|
|
|
|
Suite: `aerenew/contracts/test/account-migrator.test.js`. Run from
|
|
`aerenew/contracts` with `npx hardhat test test/account-migrator.test.js`.
|
|
|
|
Result on 2026-07-19: 9 passing.
|
|
|
|
The destination in the strong-path tests is a REAL `AerePQCAccount` deployed
|
|
through the REAL `AerePQCAccountFactory` (the Falcon verifier is mocked because a
|
|
genuine Falcon-512 signature cannot be produced inside the hardhat process; the
|
|
CREATE2 derivation and every asset movement are fully real). Covered:
|
|
|
|
- a user migrates ERC-20 balances from an EOA to a destination in one tx (both
|
|
`migrate` and the Falcon-derived `migrateToPqcAccount`);
|
|
- native AERE forwards to the destination, with nothing stuck in the migrator;
|
|
- a zero destination reverts (`ZeroDestination`);
|
|
- a failed token transfer reverts the whole migration, and the first (would-be
|
|
successful) token is NOT moved (atomicity);
|
|
- the migrator sends only to the specified destination; an unrelated third party
|
|
receives nothing;
|
|
- no admin function exists (no owner/withdraw/rescue/sweep/transferOwnership/
|
|
initialize in the ABI), and tokens force-sent to the migrator cannot be pulled
|
|
out by anyone;
|
|
- fail-closed native handling (`StrayNative`, `ZeroNative`, `NothingToMigrate`) and
|
|
malformed asset sets (`LengthMismatch`, `ZeroToken`, `ZeroAmount`).
|
|
|
|
---
|
|
|
|
## Part B. Network key rotation (design only, founder + audit gated)
|
|
|
|
This half is DESIGN. Nothing here is a today-action, and nothing here is executed
|
|
by any contract in this repository. It is documented so the end-to-end
|
|
quantum-resistance picture is complete and honest about what remains.
|
|
|
|
There are two network-level classical keys, and they are NOT the same kind of
|
|
problem.
|
|
|
|
### B.1 Foundation operator key rotation (operational key management) `[MEASURE]`
|
|
|
|
What it is. The Foundation operator key is the ECDSA key that holds privileged
|
|
roles on operational contracts (for example NavOracle attestation, compliance
|
|
registries, the deployer/owner roles that have not yet been handed to the
|
|
Timelock). It is a normal account key, not a consensus key.
|
|
|
|
Why rotate it. Same harvest-now-decrypt-later logic as a user account: a long-lived
|
|
operator key under ECDSA is a standing liability on a multi-year horizon.
|
|
|
|
How, honestly. This is an operational key-management step, not a protocol change:
|
|
|
|
1. Stand up the post-quantum destination for the operator authority. The natural
|
|
choice is an `AerePQCAccount` (Falcon-512) or, better for an operator, a
|
|
post-quantum threshold account (the `AereThresholdAccount` family, PQC t-of-n
|
|
4337) so operator authority is not a single key. `[VERIFY]` which threshold
|
|
account is the intended operator destination.
|
|
2. Transfer each privileged role from the old ECDSA operator to the new
|
|
post-quantum account. On contracts that expose role transfer (owner /
|
|
role-grant), this is a sequence of ordinary role-transfer transactions. On
|
|
immutable core-economic contracts (Sink, sAERE, burn) there is no admin to
|
|
rotate, by design, so they need nothing.
|
|
3. Where governance is the intended long-term authority, the path is role to
|
|
Timelock, and the Post-Quantum Governance design
|
|
(`aerenew/docs/AERE-POST-QUANTUM-GOVERNANCE.md`) covers granting a PQC threshold
|
|
account the proposer/executor role on the Timelock.
|
|
|
|
Gating. This is founder-gated because it moves real privileged authority over live
|
|
contracts, and it is signed by the Foundation key, not by any contract here. It is
|
|
NOT coupled to consensus. The cost/outcome of a full rotation across the live role
|
|
set is `[MEASURE]` (it depends on the exact contracts and roles enumerated at
|
|
rotation time). No role is rotated by publishing this document.
|
|
|
|
### B.2 Validator signing key rotation (coupled to consensus-PQC) `[MEASURE]`
|
|
|
|
What it is. Each validator seals QBFT blocks with a classical secp256k1 key. This
|
|
is the consensus signing key, not an application account key.
|
|
|
|
The honest coupling. Today validator seals are classical ECDSA QBFT. Rotating a
|
|
validator's signing key to a post-quantum scheme is NOT an isolated key swap: the
|
|
consensus protocol itself has to accept and verify post-quantum seals. In other
|
|
words, a validator cannot "rotate to a Falcon seal" while the rest of the network
|
|
still expects an ECDSA seal. Validator-key rotation to PQ is therefore coupled to
|
|
the consensus-PQC activation, which is tracked as its own gated item:
|
|
|
|
- The in-place PQC activation work (hybrid ECDSA + Falcon BLOCKING seal, activated
|
|
via an anchor contract on the live chain, proven at small N in isolation) is the
|
|
mechanism that would let the seal set become post-quantum without a re-genesis.
|
|
- That flip is HIGH risk (it can halt the chain), and its gates are: N greater than
|
|
or equal to 9 validators, a soak period, an external consensus audit, and the
|
|
founder's explicit GO. See the mainnet queue in
|
|
`aerenew/build-tracker/control.json` ("Consens post-quantum LIVE", risk MARE).
|
|
|
|
So the sequence is: consensus-PQC activation FIRST (gated), and validator signing
|
|
keys rotate to their post-quantum form AS PART OF that activation, not before it
|
|
and not independently. Doing validator-key rotation "early" has no meaning while
|
|
consensus verifies classical seals.
|
|
|
|
Gating. Founder-gated AND external-audit-gated AND dependent on the consensus-PQC
|
|
item. Not a today-action. Nothing in this repository activates it. The outcome
|
|
(fork-freedom, halt/recover behavior at the target N) is `[MEASURE]` against a real
|
|
soak at N greater than or equal to 9.
|
|
|
|
### B.3 Summary of the network half
|
|
|
|
| Network key | Kind of change | Coupled to consensus? | Gate | Today-action? |
|
|
|---|---|---|---|---|
|
|
| Foundation operator key | Operational role transfer to a PQC account | No | Founder | No (founder-signed op) |
|
|
| Validator signing keys | Consensus seal scheme change | Yes | Founder + external audit + N>=9 + soak | No |
|
|
|
|
The single most important honesty point: none of this makes consensus post-quantum
|
|
by itself. The user account migration in Part A is a real, deployable-today,
|
|
no-custody contract that hardens ACCOUNT authorization. The network half in Part B
|
|
is the operator-key rotation (an operational step) plus the validator-key rotation
|
|
(inseparable from the gated consensus-PQC flip). This is the last quantum-resistance
|
|
layer, and it is largely gated, not a switch to flip tonight.
|
|
|
|
---
|
|
|
|
## Files
|
|
|
|
- `aerenew/contracts/contracts/pqc/AereAccountMigrator.sol` (contract)
|
|
- `aerenew/contracts/test/account-migrator.test.js` (Hardhat suite, 9 passing)
|
|
- `aerenew/pqc-migration-toolkit/` (scanner + derivation + cost simulator)
|
|
- `aerenew/contracts/contracts/pqc/AerePQCAccount.sol`,
|
|
`AerePQCAccountFactory.sol`, `AereHybridAuth.sol` (destinations)
|
|
- `aerenew/docs/AERE-POST-QUANTUM-GOVERNANCE.md` (Timelock role grant to a PQC
|
|
threshold account, the governance path for operator authority)
|
|
- `aerenew/docs/AERE-EIP-COMPATIBILITY-MATRIX.md` (EIP-7702 support)
|