# Aere Network: new-contracts deployment-readiness runbook Scope: the ~17 new Solidity contracts added under `aerenew/contracts/contracts/` during this build loop. Source review: `aerenew/docs/AERE-SECURITY-REVIEW-NEW-CONTRACTS.md` (no CRITICAL, no HIGH). Applied fixes: `aerenew/docs/AERE-SECURITY-FIXES.md` (M1 fixed, L1 x3 fixed, L2 fixed, L3 documented). Solc 0.8.23, OpenZeppelin v4.9.x. STATUS: NOTHING HERE IS DEPLOYED. Every contract below is founder-gated. This document is the exact, ordered procedure to deploy and verify each one WHEN the founder greenlights it. It does not deploy anything. Confirmed on 2026-07-19 that none of these 17 contracts has a `deployments/*.json` entry and none appears in `aerenew/sdk-js/src/addresses.ts`. Activation is the founder's decision, and where noted it also requires an external audit and, for three of them, a zk circuit that does not yet exist. --- ## 0. Safety rules (read first, applies to every step) 1. DEPLOY FROM THE DESIGNATED DEPLOYER ONLY. The frontier / inert deployer key is `0xbeB33D20dFBBD49eC7AC1F617667f1f02dfd6465`. Ownable contracts start owned by this key and are then transferred to the Foundation `0x0243A4f47D44b40b65D33f20329dE20D00c6f3C3` (or the Timelock) per the per-contract founder actions below. Do not deploy from any other key. 2. SECRET-SCAN THE REPO BEFORE ANY PUBLISH. Run the clean-repo secret scan before pushing source, verification metadata, or any artifact to a public location. No keys, no infra hostnames. 3. NEVER TOUCH THE LIVE VALIDATORS OR THE LIVE INFRA BOX. Do not run heavy compute, provers, or deploy jobs on the infra box that serves the live RPC / explorer / relayer / oracle. Deploy transactions are submitted to `https://rpc.aere.network`; proving and vkey derivation run on a dedicated non-infra box that is deleted after use. Confirm RPC stays sub-second after any activity. 4. NO NEW TOKEN. None of these contracts introduces an ERC-20 or a wrapped/governance token, and none may be modified to do so. Rewards and payments settle in native AERE or an existing allowlisted ERC-20. 5. NEVER MOVE RESERVE OR FOUNDATION FUNDS. These deploys spend only gas from the deployer key. No transfer of Mining Reserve, Ecosystem Reserve, Team Reserve, Airdrop Reserve, or Foundation holdings is part of any step here. 6. CODE-READY IS NOT ACTIVATION. Passing tests and a clean self-review make a contract code-ready. Going live on mainnet 2800 is a separate founder decision, and for the fund-flow contracts and the circuit-gated verifiers it is also gated on an external audit and, respectively, on a real SP1 circuit. 7. NONE OF THESE CHANGES CONSENSUS. Every contract is application / account / settlement layer. Mainnet 2800 still seals blocks with classical secp256k1 QBFT. The Falcon / ML-DSA precompiles and the SP1 gateway are application-layer primitives. Never describe any of this as making consensus post-quantum. --- ## 1. Live addresses these contracts wire to All values below are LIVE on mainnet 2800 and were read from `aerenew/sdk-js/src/addresses.ts` and `aerenew/docs/AERE-EIP-COMPATIBILITY-MATRIX.md`. Pass these EXACT values as constructor arguments where a contract needs them. | Ref | Live address | Notes | |-----|--------------|-------| | Falcon-512 precompile | `0x0AE1` | Live, activated block 9,189,161. Used by name in-contract (constant), not a constructor arg. | | ML-DSA-44 precompile | `0x0AE3` | Live, activated block 9,189,161. Used by name in-contract (constant). | | SP1VerifierGateway | `0x9ca479C8c52C0EbB4599319a36a5a017BCC70628` | Stable Succinct gateway; `verifyProof` reverts on an invalid proof. | | AerePQCKeyRegistry | `0x1eCa3c5ADcBD0b22636D8672b00faC6D89363691` | PQC public-key registry; `verifyWithKey` / `statusOf` / `schemeOf`. | | AereAgentDID | `0xce641d7d7C10553D82b06B7C21d423550e7522C5` | Falcon-rooted agent identity; `agentExists` / `getAgent` / `keyRegistry`. | | AereAIReputation | `0x781ef746c08760aa854cDa4621d54db6734bfeBF` | Composable reputation; attestor set is Foundation-only and immutable. | | AerePQCAccountFactory | `0xd5315Ea7caa60d320c4f34b1bEd70dd9cc02CE58` | CREATE2 factory; `predictAddress(falconPubKey, salt)`. Runtime ref for the migrator, not a constructor arg. | | AERE402FacilitatorV2 | `0xFC2f7FAa94919caF1126b3c995F0F6AcCef291de` | Canonical agentic settlement rail; `settle(...)`. (V1 `0xbA6e…4E56` is deprecated, do not wire.) | | AereAgentV2 | `0x3FAcb997eb4252341052e7c84a86fCa0513c4490` | Machine-account registry the facilitator debits. | | Foundation | `0x0243A4f47D44b40b65D33f20329dE20D00c6f3C3` | Recommended owner / arbiter / governance target. Single-key EOA today, not a multisig. | | Deployer | `0xbeB33D20dFBBD49eC7AC1F617667f1f02dfd6465` | The only key these are deployed from. | | AereZkQbftLightClient | `0xCaDA54FAb6E7AE311d240Cf0C2Df45e974156488` | Origin-side finality client the destination settler's repayment path composes with (reference, not a constructor arg). | | AereOutboundVerifierV2 | `0x08b68bd553116Dffb99E648cb764AA93930da96F` | Origin-side inclusion-proof pattern the settler documents (reference only). | --- ## 2. Topologically-ordered deploy list Deploy in this order. A contract may be deployed only after every contract it takes as a constructor argument already exists. Contracts inside the same wave have no dependency on each other. WAVE A (no constructor dependency on any sibling; wire only to live addresses or nothing): - A1. `pqc/AereAccountMigrator` (no constructor args) - A2. `oracle/AereRandomnessBeaconV2` (no constructor args; the BLS library is internal / inlined, no linking) - A3. `AereRecoveryRegistry` (no constructor args) - A4. `intents/AereDestinationSettler` (no constructor args) - A5. `pqfinality/AerePQAttestationKeyRegistry` (no constructor args; Ownable, owner = deployer) - A6. `compliance/AereBitstringStatusList(nonRevocationVerifier)` (pass `address(0)`, see B/notes) - A7. `erc8004/AereIdentityRegistry8004(did)` (wires to live AereAgentDID) - A8. `erc8004/AereValidationRegistry8004(keyRegistry, did)` (wires to live registry + DID) - A9. `erc8004/AereAP2MandateVerifier(keyRegistry, settlementExecutor)` (wires to live registry) - A10. `compliance/AereTrustRegistry(keyRegistry)` (wires to live registry; Ownable) - A11. `agentic/AereVectorStore(facilitator)` (wires to live AERE402FacilitatorV2) - A12. `depin/AereComputeMarketV3(zkVerifier, arbiter, governance)` (wires to live SP1 gateway + Foundation) WAVE B (depends on a Wave A output): - B1. `erc8004/AereReputationRegistry8004(reputation, identity)` (identity = A7) - B2. `compliance/AereVerifiableCredential(trustRegistry, statusList)` (trustRegistry = A10, statusList = A6) WAVE C (CIRCUIT-GATED, do NOT deploy until the SP1 circuit and its real vkey exist): - C1. `mpc/AerePQAggregateVerifier(gateway, aggregateProgramVKey)` (gateway = live SP1; vkey is [VERIFY]) - C2. `pqfinality/AereFinalityCertificateVerifier(gateway, programVKey, registry)` (registry = A5; vkey is [VERIFY]) WAVE D (depends on a Wave C output, so also circuit-gated): - D1. `modular/AerePQAggregateModule(verifier)` (verifier = C1) Note: A6 through A12 have no dependency on A1 through A5; they are grouped in Wave A only because their sole dependencies are LIVE addresses. B1/B2 must wait for A7 / A10 / A6. C1/C2/D1 must wait for their real vkeys and, for C2 and D1, for A5 / C1. --- ## 3. Gate classification | Contract | Gate | Rationale | |----------|------|-----------| | AereAccountMigrator | DEPLOY-WHEN-READY (external audit recommended: moves user funds) | Pure conduit, no custody, no admin. Review verdict CLEAN. | | AereRandomnessBeaconV2 | DEPLOY-WHEN-READY | Real EIP-2537 BLS verify, fail-closed, no admin. CLEAN. | | AereRecoveryRegistry | DEPLOY-WHEN-READY | Append-only, no admin, Falcon fail-closed. CLEAN (I4 cosmetic). | | AereDestinationSettler | DEPLOY-WHEN-READY; repayment loop is [MEASURE] | Contract deploys with zero args; end-to-end solver repayment needs an off-chain SP1 prover + an origin-chain verifier that do not exist yet. External audit recommended (fund-flow). | | AereIdentityRegistry8004 | DEPLOY-WHEN-READY | Controller-gated metadata over the live DID. CLEAN. | | AereValidationRegistry8004 | DEPLOY-WHEN-READY | PQC-verified validation, no admin. CLEAN (I5 spam note). | | AereAP2MandateVerifier | FOUNDER-CONFIG at deploy: `settlementExecutor` MUST be non-zero | L3: the open path (executor == 0) is replayable and is TEST-ONLY. Production must pin the AERE402 executor. | | AereTrustRegistry | FOUNDER-ACTION: transfer owner to Foundation, then accredit issuers | Ownable trusted-list operator by design. CLEAN. | | AereVerifiableCredential | DEPLOY-WHEN-READY (after A10 + A6) | Binds accreditation + PQC + validity + revocation, fail-closed. CLEAN. | | AereBitstringStatusList | DEPLOY-WHEN-READY; zk non-revocation path is CIRCUIT-GATED | Deploy with verifier `address(0)`; the SP1 non-revocation circuit is [MEASURE], so `nonRevocationVKey` stays 0 (path fail-closed OFF) until it exists. CLEAN (I2 by-design). | | AereComputeMarketV3 | EXTERNAL-AUDIT-GATED (highest-value fund flow) + FOUNDER-CONFIG (arbiter, governance) | Escrow + disputes + PQC settlement. Review CLEAN, L1 fixed, but this is the one contract that custodies escrowed rewards and bonds. | | AereVectorStore | DEPLOY-WHEN-READY (external audit recommended: routes AERE402 funds) | L2 fixed (receipt bound to provider). Settles on the live rail, custodies no balance across calls. | | AerePQAttestationKeyRegistry | FOUNDER-ACTION: enroll validators, each validator registers own PQ key; owner to Timelock later | Append-only, no key-forgery path. CLEAN. Only meaningful in concert with C2. | | AereReputationRegistry8004 | FOUNDER-ACTION for WRITE-THROUGH: register adapter as attestor on a reputation instance; owner to Foundation, add feedback authors | M1 fixed (owner-curated authors). READ path works against the live instance today; write-through needs a Foundation governance step. | | AerePQAggregateVerifier | DEPENDENCY-GATED: do NOT deploy until the SP1 aggregation circuit exists and its real vkey is known | `aggregateProgramVKey` is IMMUTABLE. The ML-DSA-65 aggregation circuit is [MEASURE], not built. L1 fixed (code-less gateway guard). | | AereFinalityCertificateVerifier | DEPENDENCY-GATED: do NOT deploy until the PQ-finality aggregation circuit exists and its real vkey is known | `programVKey` is IMMUTABLE. The circuit is [MEASURE], not built. Already carries the `VerifierHasNoCode` guard. | | AerePQAggregateModule | DEPENDENCY-GATED (through C1) | Cannot be meaningfully deployed before C1, which is circuit-gated. CLEAN. | Summary: - DEPLOY-WHEN-READY (low risk, code-ready today): AereAccountMigrator, AereRandomnessBeaconV2, AereRecoveryRegistry, AereDestinationSettler, AereIdentityRegistry8004, AereValidationRegistry8004, AereVerifiableCredential, AereBitstringStatusList, AereVectorStore. - FOUNDER-CONFIG / FOUNDER-ACTION before they are useful: AereAP2MandateVerifier (executor), AereTrustRegistry (owner + accredit), AereReputationRegistry8004 (attestor grant), AerePQAttestationKeyRegistry (enroll + keys), AereComputeMarketV3 (arbiter + governance). - EXTERNAL-AUDIT-GATED before mainnet (fund flow): AereComputeMarketV3 (strongest), and recommended for AereVectorStore, AereDestinationSettler, AereAccountMigrator. - MUST NOT DEPLOY until a circuit exists: AerePQAggregateVerifier, AereFinalityCertificateVerifier, AerePQAggregateModule, and the zk non-revocation feature of AereBitstringStatusList. --- ## 4. Per-contract runbook Each entry: constructor arguments (with the real value to pass), deploy order / dependencies, post-deploy verification, and the gate. Post-deploy `eth_getCode` should be non-empty for every contract; that check is implied and not repeated each time. ### A1. pqc/AereAccountMigrator - Constructor arguments: NONE. `contract AereAccountMigrator is ReentrancyGuard` has no constructor. - Dependencies / order: none. Wave A. - Runtime references (not constructor args): `migrateToPqcAccount` and `predictPqcAccount` take a `factory` argument at call time. Pass the live AerePQCAccountFactory `0xd5315Ea7caa60d320c4f34b1bEd70dd9cc02CE58`. - Post-deploy verification: - Confirm NO admin: the ABI has no `owner()`, no `withdraw` / `rescue` / `sweep`. A call to `owner()` must revert (function does not exist). - `predictPqcAccount(0xd531…CE58, <897-byte Falcon pubKey>, )` returns the same address as the live factory's own `predictAddress(pubKey, salt)` (CREATE2 parity). - A `migrate` with `moveNative=false` and non-zero `msg.value` reverts `StrayNative`; with an empty token array and `moveNative=false` reverts `NothingToMigrate`. - Run `aerenew/contracts/test/account-migrator.test.js` against a fork / live-like config. - Gate: DEPLOY-WHEN-READY. External audit recommended because it moves user balances (no custody, but it is the tx that sweeps an EOA). Verdict CLEAN. ### A2. oracle/AereRandomnessBeaconV2 - Constructor arguments: NONE. Constants only (`DRAND_CHAIN_HASH`, `DRAND_PERIOD`, `DRAND_GENESIS`). The `AereDrandQuicknetBLS` library is an internal library (all functions `internal` / `private`), so it is inlined at compile time and needs no separate deployment or `--libraries` linking. - Dependencies / order: none. Wave A. Relies on live EIP-2537 precompiles `0x05`, `0x0b`, `0x0f`, `0x10`. - Post-deploy verification: - `DRAND_CHAIN_HASH()` == `0x52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971`, `DRAND_PERIOD()` == 3, `DRAND_GENESIS()` == 1692803367. - `verifyRound(round, sig)` with a REAL drand quicknet round returns true; with a tampered signature returns false (fail-closed). Confirm NO admin (no verification-off switch, no `owner()`). - Run `aerenew/contracts/test/AereRandomnessBeaconV2.test.js`. - Gate: DEPLOY-WHEN-READY. CLEAN. Honest note: drand BLS is classical, verifying it does not make the randomness post-quantum. ### A3. AereRecoveryRegistry - Constructor arguments: NONE. Falcon-512 precompile `0x0AE1` is a hard-coded constant (`PRECOMPILE_FALCON512`). - Dependencies / order: none. Wave A. Requires the live Falcon-512 precompile (block 9,189,161+). - Post-deploy verification: - `PRECOMPILE_FALCON512()` == `0x0AE1`; `RECORD_DOMAIN()` == `keccak256("AereRecoveryRegistry.v1.record")`. - Register a watchtower Falcon key via `registerOperator(pubKey)`, read back `getOperator` / `nonceOf`. - `submitRecovery` with a valid Falcon signature over `recordChallenge(...)` appends a record and bumps the operator nonce; a tampered signature reverts `PQCVerificationFailed` and appends nothing. - Confirm NO owner / admin (append-only, no `owner()`). - Run `aerenew/contracts/test/AereRecoveryRegistry.test.js`. - Gate: DEPLOY-WHEN-READY. CLEAN (I4: `getRecord` on a bad id reverts `UnknownOperator`, cosmetic). ### A4. intents/AereDestinationSettler - Constructor arguments: NONE. `AERE_CHAIN_ID` (2800) and `FILLED_EVENT_SIG` are constants. - Dependencies / order: none for the deploy. Wave A. - Post-deploy verification: - `AERE_CHAIN_ID()` == 2800; `FILLED_EVENT_SIG()` == `keccak256("Filled(bytes32,address,address,uint256,address,bytes32,uint64,uint64)")`. - A `fill` where the delivered token / recipient do not match the declared output reverts `OutputMismatch`; a second `fill` of the same order reverts `AlreadyFilled`; a good fill emits `Filled`, records the `FillRecord`, and `fillCommitment(orderId)` returns a non-zero binder. - Confirm NO custody / admin (solver-to-recipient direct transfer, no `owner()`). - Run `aerenew/contracts/test/destination-settler.test.js`. - Gate: DEPLOY-WHEN-READY for the on-chain filling side. The origin-chain repayment loop (SP1 prover over the `qbft-lightclient-guest` ELF plus an AereOutboundVerifierV2-style verifier deployed on the origin chain) is [MEASURE] and NOT part of this deploy; the settler is complete without it, but a solver is not actually repaid until that off-chain / second-chain machinery exists. External audit recommended (fund-flow, even though this contract takes no custody). CLEAN (I1: fee-on-transfer output token note). ### A5. pqfinality/AerePQAttestationKeyRegistry - Constructor arguments: NONE. `is Ownable`; OpenZeppelin `Ownable` sets `owner = msg.sender` (the deployer). - Dependencies / order: none for the deploy. Wave A. It is a constructor dependency of C2 (AereFinalityCertificateVerifier), so it must exist before C2. - Post-deploy verification: - `owner()` == deployer; `validatorCount()` == 0; `validatorSetRoot()` is a deterministic value over an empty set. - After the founder action below: `validators()` returns the enrolled set in enrollment order, `isSetComplete()` becomes true once every enrolled validator has a key, and `validatorSetRoot()` changes on each enroll / key rotation. - Confirm a non-validator cannot register a key for another address (`registerAttestationKey` uses `msg.sender`), and a non-owner `enrollValidator` reverts `Ownable: caller is not the owner`. - Run `aerenew/contracts/test/AerePQFinalityCertificate.test.js` (covers registry + verifier). - Gate: FOUNDER-ACTION. The owner (Foundation, later the Timelock, founder-signed) enrolls the validator addresses; then EACH validator registers its OWN hash-based attestation key. Transfer ownership to the Foundation / Timelock after deploy. CLEAN. Note: this registry is only useful once C2 is live, which is circuit-gated. ### A6. compliance/AereBitstringStatusList - Constructor arguments: 1. `nonRevocationVerifier_` (address): PASS `address(0)`. This keeps the zk non-revocation path fail-closed OFF (`nonRevocationConfigured()` stays false) until the SP1 non-revocation circuit exists. The constructor guards a NON-ZERO but code-less address with `VerifierHasNoCode` (L1 fix); the zero address is explicitly allowed. Only pass the live SP1 gateway `0x9ca4…0628` here if you intend to wire the zk path, and even then the vkey stays 0 until the circuit is built. - `ADMIN` is set to `msg.sender` (the deployer) and is IMMUTABLE; it cannot be transferred. It can only publish the non-revocation vkey, nothing else. - Dependencies / order: none for the deploy. Wave A. It is a constructor dependency of B2 (AereVerifiableCredential), so it must exist before B2. - Post-deploy verification: - `ADMIN()` == deployer; `NON_REVOCATION_VERIFIER()` == `address(0)` (if you passed zero); `nonRevocationConfigured()` == false; `nonRevocationVKey()` == `bytes32(0)`. - `createList(purpose, capacity)` returns a listId; `setStatus` / `revoke` are controller-only; revocation bits are terminal (clearing reverts `RevocationIsTerminal`), suspension bits are reversible. - `verifyNonRevocation(...)` reverts `NonRevocationNotConfigured` while the circuit is unset (so callers can never mistake "unconfigured" for "not revoked"). - Run `aerenew/contracts/test/aere-pq-screen.test.js` (covers trust registry + VC + status list). - Gate: DEPLOY-WHEN-READY for the bitstring mechanism. The zk non-revocation feature is CIRCUIT-GATED: `ADMIN` calls `setNonRevocationVKey()` only once the SP1 non-revocation circuit is built. CLEAN (I2: status roots are controller-attested by design; `getWord` allows independent recomputation). ### A7. erc8004/AereIdentityRegistry8004 - Constructor arguments: 1. `did` (address): the live AereAgentDID `0xce641d7d7C10553D82b06B7C21d423550e7522C5`. The constructor reads `keyRegistry()` from the DID and stores it as `KEY_REGISTRY`, so you do NOT pass the key registry separately. It reverts `ZeroAddress` on a zero DID or a DID that returns a zero key registry. - Dependencies / order: needs the live AereAgentDID. Wave A. It is a constructor dependency of B1 (AereReputationRegistry8004), so it must exist before B1. - Post-deploy verification: - `DID()` == `0xce64…22C5`; `KEY_REGISTRY()` == `0x1eCa…3691` (confirms the DID rooted into the expected live key registry). - `register(agentId, domain, cardURI)` succeeds only for `msg.sender == KEY_REGISTRY.ownerOf(agentId)` (the current Falcon-root controller) and reverts `NotController` otherwise; `resolveByDomain` / `getAgent` return the bound metadata; `didString(agentId)` == `did:aere:2800:`. - Confirm NO owner / admin. - Run `aerenew/contracts/test/erc8004-adapters.test.js`. - Gate: DEPLOY-WHEN-READY. CLEAN. [VERIFY] against the finalized ERC-8004 identity interface: Aere anchors the id to the Falcon-rooted DID id rather than minting a sequential ERC-721 id (documented divergence). ### A8. erc8004/AereValidationRegistry8004 - Constructor arguments: 1. `keyRegistry_` (address): live AerePQCKeyRegistry `0x1eCa3c5ADcBD0b22636D8672b00faC6D89363691`. 2. `did_` (address): live AereAgentDID `0xce641d7d7C10553D82b06B7C21d423550e7522C5`. Reverts `ZeroAddress` on either being zero. - Dependencies / order: needs live registry + DID. Wave A. - Post-deploy verification: - `KEY_REGISTRY()` == `0x1eCa…3691`; `DID()` == `0xce64…22C5`. - `precompileFor(1)` == `0x0AE1` (Falcon-512), `precompileFor(3)` == `0x0AE3` (ML-DSA-44). - `requestValidation(validatorKeyId, serverAgentId, dataHash)` requires an ACTIVE Falcon/ML-DSA validator key and an existing server agent; `respondValidation` accepts only a valid PQC signature over `responseChallenge(...)` and reverts `PQCValidationFailed` on a tampered proof; a request completes exactly once. - Confirm NO owner / admin. - Run `aerenew/contracts/test/erc8004-adapters.test.js`. - Gate: DEPLOY-WHEN-READY. CLEAN (I5: permissionless request creation is storage-spam only, harmless). ### A9. erc8004/AereAP2MandateVerifier - Constructor arguments: 1. `keyRegistry_` (address): live AerePQCKeyRegistry `0x1eCa3c5ADcBD0b22636D8672b00faC6D89363691`. 2. `settlementExecutor_` (address): [VERIFY: supply the AERE402 settlement-executor that will call `authorizeSpend` atomically with settlement. MUST be non-zero in production.] Passing `address(0)` enables the OPEN accounting path, which the security review (L3) and the fixes doc flag as TEST-ONLY: a public standing Falcon signature is replayable by anyone to exhaust a mandate's cap. There is no live facilitator today that calls `authorizeSpend`, so this address is a founder integration decision (the candidate is AERE402FacilitatorV2 `0xFC2f…91de` or a purpose-built executor once wired). `SETTLEMENT_EXECUTOR` is IMMUTABLE, so this is a deploy-time choice, not a later setter. - Dependencies / order: needs live registry. Wave A. The executor address should exist first if a real contract is used. - Post-deploy verification: - `KEY_REGISTRY()` == `0x1eCa…3691`; `SETTLEMENT_EXECUTOR()` == the non-zero executor you passed. - `verifyMandate(m, sig)` (view) returns true for a valid Falcon mandate signature, false otherwise (never reverts). - `authorizeSpend(m, amount, sig)` from an address other than `SETTLEMENT_EXECUTOR` reverts `NotSettlementExecutor`; from the executor with a valid signature within the window it records the spend and enforces the cap; a cap overflow reverts `MandateCapExceeded`. - Confirm NO owner / admin and NO fund custody (cap is accounting only). - Run `aerenew/contracts/test/erc8004-adapters.test.js` (includes the settlement-executor-gate test). - Gate: FOUNDER-CONFIG at deploy. Production MUST pass a non-zero `settlementExecutor_`. CLEAN except the documented L3 open-path risk, which the non-zero executor closes. ### A10. compliance/AereTrustRegistry - Constructor arguments: 1. `keyRegistry_` (address): live AerePQCKeyRegistry `0x1eCa3c5ADcBD0b22636D8672b00faC6D89363691`. `is Ownable`; owner = deployer at construction. The constructor also reserves issuer index 0 as an inert placeholder. - Dependencies / order: needs live registry. Wave A. It is a constructor dependency of B2 (AereVerifiableCredential), so it must exist before B2. - Post-deploy verification: - `KEY_REGISTRY()` == `0x1eCa…3691`; `owner()` == deployer; `issuerCount()` == 0; `NO_KEY()` == `type(uint256).max`. - After ownership transfer + accreditation: `accreditIssuer` is owner-only; `isAccredited(id, type)` is true only for an ACTIVE issuer with the type in scope; `revokeIssuer` is terminal (a revoked issuer can never be reinstated); `verifyIssuerSignature` is fail-closed. - A non-owner `accreditIssuer` / `suspendIssuer` / `revokeIssuer` reverts `Ownable: caller is not the owner`. - Run `aerenew/contracts/test/aere-pq-screen.test.js`. - Gate: FOUNDER-ACTION. After deploy, transfer ownership to the Foundation (the trusted-list operator), then accredit real issuers. CLEAN. Deploying does not assert any real institution is accredited. ### A11. agentic/AereVectorStore - Constructor arguments: 1. `facilitator` (address): the live AERE402 settlement rail. PASS AERE402FacilitatorV2 `0xFC2f7FAa94919caF1126b3c995F0F6AcCef291de` (canonical; V1 `0xbA6e…4E56` is deprecated). [VERIFY: confirm the deployed facilitator's `settle(uint256,address,address,uint256,bytes32,uint256,uint256,bytes)` ABI matches the `IAERE402Facilitator` interface before relying on paid queries. The store only calls `settle`; the `consumed` view in the interface is not called.] Reverts `ZeroAddress` on zero. - Dependencies / order: needs the live facilitator. Wave A. - Post-deploy verification: - `FACILITATOR()` == `0xFC2f…91de`; `COMMIT_DOMAIN()` and `QUERY_DOMAIN()` match the constants. - `createStore(...)` fixes owner + pricing at creation (no setters); a post-quantum store's `commit` requires a valid Falcon signature over `commitChallenge(...)` (fail-closed), a classical store's requires `msg.sender == owner`. - L2 fix check: `paidQuery(..., provider, ...)` records the receipt bound to `provider`; `attestRetrieval` by any address other than that provider reverts `NotReceiptProvider` and leaves the receipt unconsumed; the bound provider consumes it successfully. - Confirm NO owner / admin and no balance held across calls (delta-measured forward to recipient). - Run `aerenew/contracts/test/aere-vector-store.test.js`. - Gate: DEPLOY-WHEN-READY. External audit recommended (routes AERE402 payments). CLEAN with L2 fixed. ### A12. depin/AereComputeMarketV3 - Constructor arguments: 1. `zkVerifier` (address): live SP1VerifierGateway `0x9ca479C8c52C0EbB4599319a36a5a017BCC70628`. The constructor reverts `VerifierHasNoCode` if this address has no code (L1 fix), so it MUST be the live gateway. 2. `arbiter` (address): [FOUNDER DECISION. Recommended: Foundation `0x0243A4f47D44b40b65D33f20329dE20D00c6f3C3`.] Can only route a DISPUTED job's escrow; cannot drain. IMMUTABLE. 3. `governance` (address): [FOUNDER DECISION. Recommended: Foundation `0x0243…f3C3`.] Can only flip the ERC-20 reward-token allowlist; cannot move funds. IMMUTABLE. Reverts `ZeroAddress` on any of the three being zero. - Dependencies / order: needs the live SP1 gateway (code check) and the two chosen roles. Wave A. - Post-deploy verification: - `ZK_VERIFIER()` == `0x9ca4…0628`; `ARBITER()` == chosen arbiter; `GOVERNANCE()` == chosen governance; `FALCON512_PRECOMPILE()` == `0x0AE1`. - `setTokenAllowed` reverts `NotGovernance` for a non-governance caller; `resolveDispute` reverts `NotArbiter` for a non-arbiter caller. - `isSolvent(address(0))` and `isSolvent()` are true after any sequence of job lifecycle calls (the per-asset solvency invariant: balance >= totalLiabilities). A ZK_VERIFIED job pays only inside `submitResultZK` after `verifyProof`; a `pqcSettlement` job's payout requires a valid Falcon signature over `settlementDigest(...)` or reverts `NotPQCAuthorized`. - Confirm NO owner and no sweep (only arbiter routing + governance allowlist). - Run `aerenew/contracts/test/AereComputeMarketV3.test.js` (includes the L1 construction-guard test). - Gate: EXTERNAL-AUDIT-GATED before mainnet (it is the highest-value fund-flow contract: escrowed rewards + provider / challenger bonds). FOUNDER-CONFIG for arbiter and governance. CLEAN, L1 fixed. ### B1. erc8004/AereReputationRegistry8004 - Constructor arguments: 1. `reputation` (address): an AereAIReputation instance. For the READ path, pass the LIVE `0x781ef746c08760aa854cDa4621d54db6734bfeBF`. For WRITE-THROUGH, pass the reputation instance that LISTS THIS ADAPTER as an attestor. [VERIFY: the live instance's attestor set is Foundation-only and immutable, so write-through requires a NEW AereAIReputation instance that includes this adapter; supply that instance's address if write-through is intended.] 2. `identity` (address): the AereIdentityRegistry8004 deployed in A7. `is Ownable`; owner = deployer. Reverts `ZeroAddress` on either being zero. - Dependencies / order: needs A7 (identity adapter) and a reputation instance. Wave B. - Post-deploy verification: - `REPUTATION()` == the instance passed; `IDENTITY()` == the A7 address; `owner()` == deployer. - `getScore(agentId)` / `getStats(agentId)` read straight from the live reputation (READ works today). - M1 fix check: `giveFeedback` from an address NOT in `isAuthorizedFeedbackAuthor` reverts `NotAuthorizedFeedbackAuthor` and writes nothing; after `addFeedbackAuthor(x)` (owner-only), `x` can submit feedback in `{-1,0,+1}`; `removeFeedbackAuthor` re-blocks; only the owner manages the allowlist. - `canWriteThrough()` is true only when the reputation instance lists this adapter as an attestor (`AdapterNotAttestor` otherwise). - Run `aerenew/contracts/test/erc8004-adapters.test.js`. - Gate: FOUNDER-ACTION for write-through. READ path is deploy-when-ready against the live instance. For write-through the Foundation must deploy / point a reputation instance that lists this adapter, then the owner authorizes feedback authors. Transfer ownership to the Foundation. M1 fixed. ### B2. compliance/AereVerifiableCredential - Constructor arguments: 1. `trustRegistry_` (address): the AereTrustRegistry deployed in A10. 2. `statusList_` (address): the AereBitstringStatusList deployed in A6. Reverts `ZeroAddress` on either being zero. - Dependencies / order: needs A10 and A6. Wave B. - Post-deploy verification: - `TRUST_REGISTRY()` == A10 address; `STATUS_LIST()` == A6 address; `DID_METHOD()` == `"did:aere"`; `VC_DOMAIN()` matches the constant. - `verifyPresented(c, sig)` returns true only when accreditation + Falcon signature + validity + not-revoked all hold (fail-closed, never reverts). `anchorCredential` reverts `NotAccredited` / `NotYetValid` / `Expired` / `SignatureInvalid` on the respective failure and records nothing; `anchorCredentialWithDid` enforces the `did:aere:` prefix and the `subjectDidHash` match. - `isValid(id)` flips to false the instant the issuer is suspended / revoked in A10 or the credential's status bit is set in A6. - Confirm NO owner / admin. - Run `aerenew/contracts/test/aere-pq-screen.test.js`. - Gate: DEPLOY-WHEN-READY (after A10 + A6). CLEAN. ### C1. mpc/AerePQAggregateVerifier - Constructor arguments: 1. `gateway` (address): live SP1VerifierGateway `0x9ca479C8c52C0EbB4599319a36a5a017BCC70628`. The constructor reverts `VerifierHasNoCode` if code-less (L1 fix), so it MUST be the live gateway. 2. `aggregateProgramVKey` (bytes32): [VERIFY: supply the REAL SP1 verification key of the audited ML-DSA-65 aggregation circuit at deploy time.] This value is IMMUTABLE and pins the one circuit this verifier will ever accept. The circuit is [MEASURE] in `docs/AERE-PQ-AGGREGATE.md` and is NOT implemented, so a real vkey does not exist yet. Deploying now would permanently pin a placeholder. Reverts `ZeroVKey` on zero. - Dependencies / order: Wave C. It is a constructor dependency of D1 (AerePQAggregateModule). - Post-deploy verification (only meaningful once a real circuit + vkey exist): - `SP1_GATEWAY()` == `0x9ca4…0628`; `AGGREGATE_PROGRAM_VKEY()` == the pinned real vkey. - `registerCommittee(root, t, n, scheme)` enforces `1 <= t <= n` and a non-zero scheme; `verifyAggregate` is fail-closed on every binding mismatch (root / threshold / size / scheme / digest / below-threshold) and delegates the one cryptographic check to `verifyProof`. - Confirm NO owner / admin and no fund custody. - Run `aerenew/contracts/test/AerePQAggregate.test.js` (uses a MOCK gateway; the real circuit is not exercised, so passing tests do NOT prove end-to-end aggregation). - Gate: DEPENDENCY-GATED. DO NOT DEPLOY until the SP1 aggregation circuit exists and its real vkey is derived on a dedicated non-infra box. L1 fixed. ### C2. pqfinality/AereFinalityCertificateVerifier - Constructor arguments: 1. `gateway` (address): live SP1VerifierGateway `0x9ca479C8c52C0EbB4599319a36a5a017BCC70628`. Reverts `VerifierHasNoCode` if code-less (guard already present). 2. `programVKey` (bytes32): [VERIFY: supply the REAL SP1 vkey of the audited PQ-finality aggregation circuit at deploy time.] IMMUTABLE; pins the one circuit. The circuit is [MEASURE] in `docs/AERE-PQ-FINALITY-CERTIFICATE.md` and is NOT implemented. Reverts `ZeroVKey` on zero. 3. `registry` (address): the AerePQAttestationKeyRegistry deployed in A5. Reverts `ZeroRegistry` on zero. The constructor also derives `attestationDomain = keccak256(DOMAIN_PREFIX, chainid, registry)`. - Dependencies / order: needs A5 and a real vkey. Wave C. - Post-deploy verification (only meaningful once a real circuit + vkey exist): - `SP1_GATEWAY()` == `0x9ca4…0628`; `PROGRAM_VKEY()` == the pinned real vkey; `REGISTRY()` == A5 address; `attestationDomain()` == `keccak256(abi.encode(DOMAIN_PREFIX, 2800, ))`. - `currentQuorumThreshold()` == ceil(2N/3) for the live registry set (N=7 gives 5). `verifyCertificate` is fail-closed on root / size / domain / quorum mismatch; a rotation in A5 invalidates old certificates. - Confirm NO owner / admin. - Run `aerenew/contracts/test/AerePQFinalityCertificate.test.js` (MOCK gateway; real circuit not exercised). - Gate: DEPENDENCY-GATED. DO NOT DEPLOY until the PQ-finality aggregation circuit exists and its real vkey is known, AND A5 is deployed with the validator set enrolled and keyed. Additive to consensus, never a consensus flip. CLEAN, already carries the `VerifierHasNoCode` guard. ### D1. modular/AerePQAggregateModule - Constructor arguments: 1. `verifier` (address): the AerePQAggregateVerifier deployed in C1. Reverts `BadVerifier` on zero. - Dependencies / order: needs C1. Wave D. Transitively circuit-gated. - Post-deploy verification: - `VERIFIER()` == C1 address; `isModuleType(1)` == true; `name()` == `"aere.pq-aggregate-validator.1.0.0"`. - `onInstall(abi.encode(committeeId))` reverts `UnknownCommittee` unless the committee is registered in C1; `validateUserOp` returns 0 only when the signature carries a valid aggregate proof for the account's committee over `userOpHash`, else 1 (never reverts on a malformed signature). - Confirm NO owner / admin (singleton, per-account state keyed by `msg.sender`). - Run `aerenew/contracts/test/AerePQAggregate.test.js`. - Gate: DEPENDENCY-GATED (through C1). [VERIFY] the ERC-7579 signature-unwrapping against the specific account stack (Safe7579 / Kernel / Nexus) you install it under. CLEAN. --- ## 5. Consolidated [VERIFY] list (must be supplied at deploy time) Addresses: - AereAP2MandateVerifier constructor arg 2, `settlementExecutor_`: the non-zero AERE402 settlement-executor that calls `authorizeSpend`. MUST NOT be `address(0)` in production (L3). Founder integration decision. - AereReputationRegistry8004 constructor arg 1, `reputation`: `0x781e…feBF` for READ; for WRITE-THROUGH, a reputation instance that lists this adapter as an attestor (the live instance's attestor set is immutable and Foundation-only, so a new instance is required). - AereVectorStore constructor arg 1, `facilitator`: recommended AERE402FacilitatorV2 `0xFC2f…91de`; confirm the deployed `settle` ABI matches the interface. - AereComputeMarketV3 constructor args 2 and 3, `arbiter` and `governance`: founder-chosen (Foundation `0x0243…f3C3` recommended). vkeys (IMMUTABLE, pin a circuit that does NOT yet exist, so these contracts must NOT deploy until the circuit is built and its real vkey is derived on a dedicated non-infra box): - AerePQAggregateVerifier constructor arg 2, `aggregateProgramVKey`: real SP1 vkey of the ML-DSA-65 aggregation circuit ([MEASURE]). - AereFinalityCertificateVerifier constructor arg 2, `programVKey`: real SP1 vkey of the PQ-finality aggregation circuit ([MEASURE]). - AereBitstringStatusList post-deploy `setNonRevocationVKey(vkey)`: real SP1 vkey of the zk non-revocation circuit ([MEASURE]); set by `ADMIN` (the deployer) only once the circuit exists. The contract itself deploys today with `nonRevocationVerifier_ = address(0)`. Interface confirmations ([VERIFY] against a finalized external spec, not a deploy blocker): - ERC-8004 identity / reputation / validation selector conformance (the adapters keep ERC-8004 semantics but anchor ids to the Falcon-rooted DID id by design). - x402 / AP2 mandate field set (AereAP2MandateVerifier struct). - W3C VC 2.0 JSON member mapping (AereVerifiableCredential anchors a digest, not the JSON-LD document). - ERC-7579 signature unwrapping for the target account stack (AerePQAggregateModule). --- ## 6. What is NOT in this runbook - No consensus change. None of these deploys touches validator keys, QBFT config, or genesis. - No fund movement beyond deployer gas. No Reserve / Foundation transfer is part of any step. - No off-chain build. The SP1 aggregation circuits (finality, committee, non-revocation) and the destination-settler origin-side repayment prover are [MEASURE] research / engineering items tracked separately; this runbook covers only the on-chain contract deploys and their verification.