# Aere Quantum Migration Toolkit > **Note added 2026-11-04 (to the note of 2026-09-24 below).** Its sentences on vote and message attribution since block 24,300,000 had one exception until 2026-10-31 12:27Z: on one path of the second client (the Nethermind-derived one) the author of a proposal was taken at the height named in its payload, so for a payload height below 24,300,000 it was the signer of the ECDSA envelope. Since 2026-10-31 12:27Z that client refuses at decoding a proposal whose block number differs from its payload height. See the correction of 2026-11-01 to rule 3 in section 4 of AIP-22 (aere-research). The note below is kept as it was written. > **Note added 2026-10-30 (consensus).** Since block 25,080,000 (AIP-22 stage 5) headers no longer carry ECDSA commit seals: each carries the Falcon-512 seal of its proposer instead, and a commit still carries the ECDSA commit seal of its validator as an additional check. Where the note of 2026-09-24 below describes the headers, it describes chain 2800 below that block. > **Note added 2026-09-24 (consensus).** Where this document says that consensus is classical secp256k1 ECDSA and not post-quantum, read it as the per-block finality statement it was until block 24,300,000 (AIP-22 stage 4, 2026-10-25). Since that block every validator attributes a consensus vote only through its verified post-quantum seal, and a block is post-quantum final once the next anchor, at most 32 blocks later, carries the certificate that covers it; headers still carry classical ECDSA commit seals until AIP-22 stage 5 (this sentence corrected on 2026-10-25). It no longer describes all of consensus on chain 2800: since 2026-08-14 every anchor block must carry a certificate of validator post-quantum seals under its hash (Falcon-512, with SLH-DSA as well since 2026-09-04), and since 2026-09-05 (block 17,250,000) the nine AERE-client validators (nine of the ten) refuse a commit message without a valid Falcon-512 seal of its author, and since 2026-09-08 (block 17,700,000) any QBFT consensus message without one, while the tenth, the second client, enforced that seal only on commit messages until block 24,300,000 and attributes every consensus message only through it since (this clause corrected on 2026-10-12, 2026-10-25 and 2026-10-28; until 2026-10-28 it dated the refusal of every message type to 2026-09-05, the date of the commit layer alone). (Note applied to this document on 2026-10-28.) A starting toolkit to assess and migrate EVM accounts toward post-quantum readiness on Aere Network (chain 2800), or on any EVM chain reachable by RPC. Aere Network is the post-quantum EVM L1: it ships five live NIST post-quantum precompiles on mainnet, four signature verifiers (Falcon-512, Falcon-1024, ML-DSA-44, SLH-DSA-128s) and the SHAKE256 hash, at `0x0AE1..0x0AE5`, activated at block 9,189,161 (corrected 2026-10-28: this called all five verification precompiles), plus a live Falcon-512-owned smart account and factory. That makes Aere the natural home for tooling that helps others measure their quantum exposure and move to a post-quantum account. This toolkit extends Aere's internal account-migration work outward into something anyone can run. It is a real product with one unified CLI and zero runtime dependencies (pure Node built-ins, Node 18+): 1. `scan.js` / `aere-pqc scan`, a real PQC-readiness scanner (EOA vs contract, and which signature primitives a contract uses). 2. `lib/migrator.js` / `aere-pqc build-migration`, the transaction-CONSTRUCTION SDK: given a classical ECDSA EOA and a target Falcon-512 public key it derives the counterfactual post-quantum account, enumerates the assets to move (read-only), and emits the exact sequence of UNSIGNED transactions a holder would sign. It never signs, deploys, or moves funds. 3. `lib/readiness.js` / `aere-pqc readiness` + `simulate.js` / `aere-pqc simulate`, the quantum-readiness cost simulator: one-time migration gas plus ongoing per-authorization cost, from the measured PQC verify gas. `aere-pqc` is the single entry point that wraps `scan`, `simulate`, `build-migration`, and `readiness`. The lower-level `scan.js`, `plan.js`, `simulate.js` CLIs remain for direct use. ## The scope boundary (this never moves) Migrating an account's authentication to a post-quantum scheme changes how that account authorizes. It does NOT make Aere consensus post-quantum. Mainnet 2800 sealed block headers with classical secp256k1 QBFT commit seals until block 25,080,000; since then (AIP-22 stage 5) headers no longer carry ECDSA commit seals and each carries the Falcon-512 seal of its proposer, while a commit still carries the ECDSA commit seal of its validator as an additional check, and the on-chain ZK verifiers (BN254 Groth16) are classical. Nothing in this toolkit claims otherwise, and the scanner and simulator both restate the boundary in their output. ## Honest status This is a starting toolkit, not a finished product. What is real and verified is listed under "What actually runs" below. What is heuristic, out of scope, or not yet deployed is flagged inline with `[VERIFY]` and `[MEASURE]`, in the code and in the reports the tools print. ## 1. The readiness scanner: `scan.js` Given an EVM address, the scanner reports quantum exposure as a colour: - **RED**, classical-only. An EOA (secp256k1 ECDSA authenticated, so Shor-breakable and unable to hold verification code), or a contract with no detectable post-quantum precompile usage. - **YELLOW**, hybrid. A contract that uses both a classical signature primitive (ecrecover at `0x01`, or P-256 at `0x100`) and Aere's live PQC precompile band. - **GREEN**, PQC-capable. A contract that uses Aere's live native PQC precompiles (`0x0AE1..0x0AE5`). ```bash # live scan over JSON-RPC (this is the only part that needs network access) node scan.js 0x465d9E3b476BF98Aa1393079e240Db5D2a9bEA6A --rpc https://rpc.aere.network # offline: scan a bundled real-bytecode fixture node scan.js --fixture AerePQCAttestation # offline: scan bytecode you already have node scan.js 0xYourContract --bytecode 0x60806040... # machine-readable node scan.js 0x465d... --rpc https://rpc.aere.network --json ``` ### How it detects, and why it is honest The scanner does not grep the hex. A naive search for `610ae1` (PUSH2 0x0AE1) false-positives, because those bytes can sit inside another instruction's push data. Two techniques make the detection real: 1. **Opcode-aware decoding.** The bytecode is walked as an instruction stream, skipping each PUSH's immediate bytes, so a matched constant is a genuine push. 2. **Local stack simulation to resolve CALL targets.** For every CALL/STATICCALL/DELEGATECALL/CALLCODE the scanner recovers the address argument (the second stack item) by simulating the stack per basic block. That distinguishes an actual call to `0x0AE1` from the bare number `0x0AE5` used as a memory length near an unrelated staticcall, which is precisely the false positive a proximity heuristic hits. (An earlier proximity-only version of this tool misread `AereHybridAuth` as hybrid for exactly that reason; the stack-simulation version reads it correctly.) The signature-verify addresses `0x0AE1..0x0AE4` (2785..2788) are not round numbers, so a genuine opcode-aligned push of one is a medium-confidence signal even when the call target is staged through memory and cannot be resolved locally. The common literals `0x01`, `0x100`, and `0x0AE5` are never used as a fallback signal; they count only when stack simulation resolves them as an actual call target. ### Scanner limitations (read these) - Bytecode scanning only sees NATIVE precompile calls. A contract that verifies Falcon through the SOLIDITY `AereFalcon512Verifier` (`0x4E8e...D8fFC`, the path the deployed `AerePQCAccount` and `AereHybridAuth` actually take) delegates to a normal contract address, so it reads as RED here even though it is PQC-capable. The bundled `AereHybridAuth` fixture demonstrates this on purpose. Confirm an auth path against source when the scanner says RED. - `ecrecover` (`0x01`) detection is high confidence only because stack simulation resolves the call target to the exact address `1`. A contract that never calls a signature precompile (authorization is by owner or role) also reads RED, which is correct: it has no quantum-vulnerable signature surface to migrate. - The scanner classifies signature-verification exposure. It does not audit key management, upgradeability, or business logic. ## 2. The migration SDK: `lib/migrator.js` (transaction construction) Given a classical ECDSA EOA and a target NIST Falcon-512 public key, this module builds the exact sequence of UNSIGNED transactions a holder would sign to move their assets onto a post-quantum `AerePQCAccount`. It is the concrete, signable-artifact layer on top of the older `lib/migrate.js` plan builder. ```bash # demo (uses the live sample account's real Falcon key; demo EOA 0x..dEaD) node aere-pqc.js build-migration # real build: derive the target, enumerate a real EOA's assets read-only, and # attach a live gas estimate to each unsigned tx node aere-pqc.js build-migration --eoa 0xYourEoa --falcon 0x09... \ --rpc https://rpc.aere.network --native 1000000000000000 --estimate # atomic sweep via the (audit-gated, not-yet-deployed) AereAccountMigrator node aere-pqc.js build-migration --eoa 0xYourEoa --path migrator \ --migrator 0xVerifiedMigrator --tokens 0xTokenA,0xTokenB --amounts 1000,2000 # machine-readable node aere-pqc.js build-migration --eoa 0xYourEoa --rpc https://rpc.aere.network --json ``` Key functions (`import ... from '@aere/pqc-migration-toolkit/migrator'`): - `predictTargetAddress({ falconPubKey, salt })`: the counterfactual `AerePQCAccount` address, pure CREATE2 math, no RPC. Mirrors `AerePQCAccountFactory.predictAddress` and is verified in `selftest.js` against the live on-chain sample account. - `enumerateAssets({ rpcUrl, owner, tokens })`: READ-ONLY. `eth_getBalance` for native AERE and `eth_call balanceOf(owner)` per ERC-20 candidate; returns which assets have a non-zero balance and therefore need moving. Signs nothing. - `buildMigrationTransactions({ path, eoa, falconPubKey, tokens, nativeWei, ... })`: the core. Returns an array of UNSIGNED tx objects, each stamped `signed:false`, shaped `{ to, from, value, data, chainId }` (nonce/gas left for the signer). Two paths: - `direct` (works today, no extra contract): per-asset `ERC-20 transfer` + native send straight to the target account. Not atomic. - `migrator` (atomic, all-or-nothing): `approve(migrator, amount)` per token then one `AereAccountMigrator.migrateToPqcAccount(...)` that binds the destination to the Falcon key on-chain. REQUIRES an explicit `--migrator` address, because `AereAccountMigrator` is repo source in the audit-gated `notDeployedHeld` set and has NO live mainnet address (see below). - `estimateMigrationGas(plan, rpcUrl)`: attaches a read-only `eth_estimateGas` result to each unsigned tx (or an error string when a step cannot be simulated pre-deploy). Broadcasts nothing. - `encodeMigrateCalldata`, `encodeMigrateToPqcAccountCalldata`, `encodeApproveCalldata`, `encodeTransferCalldata`, `encodeCreateAccountCalldata`: the individual calldata builders, each verified byte-for-byte against ethers v6 (see "What actually runs"). The calldata encoder (`lib/abi.js`) is a zero-dependency Solidity ABI encoder for exactly the types the migrator needs (`uint256, address, bool, bytes, address[], uint256[]`), validated against ethers 6.16.0. ### The migration paths **PQC account (Falcon-512 owned).** Derive the counterfactual account (step 1, off-chain), deploy it through the live factory with `createAccount(falconPubKey, salt)` (step 2, permissionless and idempotent), then move assets and roles off the old EOA into it (step 3). After the move, spending authority is the Falcon-512 key only. There is no ECDSA fallback, so register the key in `AerePQCKeyRegistry` (proof-of-possession) and set PQC social-recovery guardians before moving material value. **Hybrid account (ECDSA + Falcon-512).** Register a hybrid identity in `AereHybridAuth` binding your existing classical address to a Falcon-512 key, then authorize with both legs during the transition. An attacker must break both secp256k1 AND Falcon-512. **EIP-7702 delegation.** Aere supports EIP-7702, so an EOA can temporarily delegate execution to account code to batch a migration move in a single EOA transaction. ### Founder-gated caveat, and what works today The `AerePQCAccountFactory` (`0xd5315Ea7...CE58`) is live, and `createAccount` is permissionless, so deploying a PQC account and moving assets into it with the `direct` path is possible TODAY with no special authority: the whole `direct` sequence is plain factory + ERC-20 + native transactions the holder signs. What is NOT deployed: - `AereAccountMigrator` (the atomic `migrate` / `migrateToPqcAccount` conduit) is repo source (`aere-contracts/contracts/pqc/AereAccountMigrator.sol`) in the audit-gated `notDeployedHeld.externalAuditGated_fundFlow` set. It has NO mainnet address. The `migrator` path therefore refuses to build unless you pass an explicit `--migrator` address, and it prints a `[VERIFY]` warning telling you to confirm that address holds the exact audited bytecode before granting it any approval. - `AereHybridAuth` is repo source with no mainnet address, so the hybrid path's deploy step is a founder/deployer step, flagged `[VERIFY]`. Deploying NEW contracts or a corrected V2 redeploy is signed by the Foundation/deployer key, never by this toolkit. ## 3. The cost simulator: `aere-pqc readiness` and `simulate.js` Two views on cost, both over the MEASURED PQC verify gas from `aere-docs/AERE-BENCHMARK-REPORT.md`: - `aere-pqc readiness
--rpc