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.
6.3 KiB
6.3 KiB
Aere Network: adversarial-review fixes (pre-deploy hardening)
Source review: aerenew/docs/AERE-SECURITY-REVIEW-NEW-CONTRACTS.md
Repo: aerenew/contracts (solc 0.8.23, OpenZeppelin v4.9.x). All contracts founder-gated, not deployed.
Guard pattern for L1 copied from contracts/pqfinality/AereFinalityCertificateVerifier.sol (gateway.code.length == 0 revert).
Per-finding status
M1 (MEDIUM) FIXED, with proof
File: contracts/erc8004/AereReputationRegistry8004.sol
- Made the adapter
Ownable(OZ v4,@openzeppelin/contracts/access/Ownable.sol, matching the repo). - Added
mapping(address => bool) public isAuthorizedFeedbackAuthor, owner functionsaddFeedbackAuthor/removeFeedbackAuthor(withFeedbackAuthorSetevent and a zero-address guard on add), and a new errorNotAuthorizedFeedbackAuthor(address). - Gated
giveFeedback: first line now revertsNotAuthorizedFeedbackAuthorunlessisAuthorizedFeedbackAuthor[msg.sender]. The rest of the flow (agent-registered, delta clamp, adapter-is-attestor) is unchanged. - Design choice (documented in NatSpec): owner-curated author allowlist, mirroring the live AereAIReputation curated-attestor model. Scope is authorization-only: the owner cannot set a reputation value, cannot exceed the
{-1,0,+1}delta clamp every author is held to, and moves no funds. No re-entrancy, no fund/reputation-value backdoor. Read path (getScore,getStats,liveKeyOf,canWriteThrough) untouched.
L1 (LOW) FIXED (x3), with proof
Added the sibling's codeless-gateway guard to each verify path. New error VerifierHasNoCode() in each.
contracts/mpc/AerePQAggregateVerifier.solconstructor: reverts ifgateway.code.length == 0(after the existingZeroGatewaycheck).contracts/depin/AereComputeMarketV3.solconstructor: reverts ifzkVerifier.code.length == 0(after the existingZeroAddresscheck).contracts/compliance/AereBitstringStatusList.solconstructor: reverts ifnonRevocationVerifier_ != address(0) && nonRevocationVerifier_.code.length == 0. The zero address is still allowed (keeps the zk non-revocation path fail-closed OFF until configured), which preserves existing behavior. Verifier is immutable, so the constructor is the correct place.
L2 (LOW) FIXED, with proof
File: contracts/agentic/AereVectorStore.sol
- Bound each paid-query receipt to an intended provider. Added
address providerto theQueryReceiptstruct. paidQuerynow takesaddress provider(validated non-zero via existingZeroAddress) and records it in the receipt. Signature is nowpaidQuery(storeId, queryHash, provider, agentId, amount, nonce, deadline, authSig). The settlement/forwarding flow (AERE402 rail, fee to sink, delta-measured forward to recipient) is unchanged;receiptIdformula unchanged.attestRetrievalpriced branch now reverts new errorNotReceiptProvider()unlessmsg.sender == receipt.provider, so a third party (or the payer) cannot front-run the honest provider and burn the receipt with a junk resultRoot.getReceiptview extended to also returnprovider.
L3 (LOW) DOCUMENTED (accepted risk), not code-changed
File: contracts/erc8004/AereAP2MandateVerifier.sol
- Chose DOCUMENT over CODE-CHANGE, per the task's guidance, because the two candidate code fixes are unsuitable: (a) a per-authorization nonce would break the intended standing-mandate ("sign once, spend repeatedly up to the cap") semantics that the design and tests rely on; (b) "bind consumption to the executor" is already the built-in
SETTLEMENT_EXECUTORgate. - Strengthened the contract-level and
authorizeSpendNatSpec: the open accounting path (SETTLEMENT_EXECUTOR == address(0)) is verification/test-only and MUST NOT be used in production; production MUST setSETTLEMENT_EXECUTORto the AERE402 facilitator so a mandate's cap is only ever consumed alongside a real settlement. No funds at risk (this contract holds none); the vector is cap-exhaustion griefing only. - The existing test "enforces the settlement-executor gate when one is configured" already proves the mitigation works (a non-executor is rejected, the configured executor succeeds). No new test needed.
Tests added / changed
test/erc8004-adapters.test.js:deployRepnow authorizesotheras a feedback author (both branches). Two pre-existing tests that relied on the ungatedgiveFeedbackwere updated to call as the authorizedother(legitimate behavior change from the M1 gate). Added new test "gates giveFeedback to owner-authorized feedback authors (M1)": unauthorized caller revertsNotAuthorizedFeedbackAuthorand writes nothing, owner authorizes -> same call succeeds and moves the live score to 10, owner revokes -> re-blocked, and only the owner may manage the allowlist.test/AerePQAggregate.test.js: added "rejects a code-less SP1 gateway at construction (L1 fail-open guard)" (EOA gateway revertsVerifierHasNoCode, zero revertsZeroGateway, real mock deploys).test/AereComputeMarketV3.test.js: added "construction guards" > "rejects a code-less ZK verifier at construction (L1)" (EOA revertsVerifierHasNoCode, zero revertsZeroAddress, real mock deploys).test/aere-pq-screen.test.js: added "rejects a non-zero code-less non-revocation verifier at construction, but allows zero (L1)" (EOA revertsVerifierHasNoCode; zero deploys andnonRevocationConfigured()==false; real mock deploys).test/aere-vector-store.test.js: the twopaidQuerycalls updated to passprovider.address; the paid-query test extended to assert the receipt is bound to the provider and that a third party (operator) and even the payer (consumer) are rejectedNotReceiptProviderwith the receipt left unconsumed, then the bound provider consumes it successfully (L2 proof).
Real re-run results (npx hardhat test , from aerenew/contracts)
- test/erc8004-adapters.test.js .... 19 passing
- test/aere-vector-store.test.js ... 8 passing
- test/AerePQAggregate.test.js ..... 18 passing
- test/AereComputeMarketV3.test.js . 14 passing
- test/aere-pq-screen.test.js ...... 13 passing
npx hardhat compile: green (compiled successfully, then "Nothing to compile" on re-run).
Notes
- No contracts outside the findings were touched. No existing guard was weakened. The L1 zero-address behavior for AereBitstringStatusList was intentionally preserved. Prose contains no em-dashes or "--".