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.
522 lines
37 KiB
Markdown
522 lines
37 KiB
Markdown
# 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>, <salt>)` 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(<real vkey>)` 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:<agentId>`.
|
|
- 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(<token>)` 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, <A5 address>))`.
|
|
- `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.
|