From df5035805db1d72ff9057a58511c949da25072f0 Mon Sep 17 00:00:00 2001 From: FlowmemoryAI <283694809+FlowmemoryAI@users.noreply.github.com> Date: Wed, 13 May 2026 16:11:59 -0500 Subject: [PATCH] Record Base canary source verification --- docs/CURRENT_STATE.md | 5 +- docs/DEPLOYMENTS/2026-05-13-base-canary-v0.md | 27 +++++- docs/OPERATIONS/V0_OPERATOR_POLICY.md | 6 +- .../base-canary-source-verification-plan.json | 2 + ...ase-canary-source-verification-status.json | 97 +++++++++++++++++++ infra/scripts/verify-base-canary-sources.mjs | 41 +++++++- 6 files changed, 166 insertions(+), 12 deletions(-) create mode 100644 fixtures/deployments/base-canary-source-verification-status.json diff --git a/docs/CURRENT_STATE.md b/docs/CURRENT_STATE.md index 837db639..8ed26ce4 100644 --- a/docs/CURRENT_STATE.md +++ b/docs/CURRENT_STATE.md @@ -36,7 +36,7 @@ Contracts foundation: - `contracts/FlowMemoryHookAdapter.sol` is a compileable V0 hook-adapter scaffold. It emits `SWAP_MEMORY_SIGNAL` FlowPulse events for the launch fixture path. It is not a production Uniswap v4 hook. - `contracts/ArtifactRegistry.sol`, `CursorRegistry.sol`, `ReceiptVerifier.sol`, `WorkerRegistry.sol`, `VerifierRegistry.sol`, `WorkReceiptRegistry.sol`, `VerifierReportRegistry.sol`, and `WorkDebtScheduler.sol` provide local/test skeleton surfaces for commitments, cursors, work receipts, verifier reports, and work state. - `contracts/FLOWPULSE_SCHEMA.md` documents event fields, receipt boundaries, and URI/log-data limitations. -- `tests/RootfieldRegistry.t.sol` and `tests/LiveV0Package.t.sol` contain 36 passing Foundry tests. +- `tests/RootfieldRegistry.t.sol` and `tests/LiveV0Package.t.sol` contain 38 passing Foundry tests. - `tests/README.md` documents the current test command. - `contracts/STATIC_ANALYSIS.md`, `contracts/DEPLOYMENT_BOUNDARY.md`, and `contracts/ACCESS_CONTROL_REVIEW.md` define the current hardening, deployment, and access-control boundaries. - `infra/scripts/contracts-static-analysis.ps1` and `infra/scripts/contracts-static-analysis.sh` run the contract hardening baseline. Slither is optional by default and required only when explicitly requested. @@ -61,6 +61,7 @@ Indexer/verifier local package: - `fixtures/deployments/base-canary-v0.json`, committed canary reader output, and `npm run flowmemory:canary-dashboard` now generate a separate Base canary dashboard dataset. - The dashboard has a separate Base canary mode at `/canary` that shows live-read canary FlowPulse observations, Rootflow transitions, canary boundaries, and raw canary JSON without replacing local fixture mode. - `npm run verify:base-canary:sources` produces a dry-run source verification plan for all canary contracts and writes `fixtures/deployments/base-canary-source-verification-plan.json`; `npm run verify:base-canary:sources:submit` submits after `BASESCAN_API_KEY` is configured. +- All 10 deployed Base canary contracts are verified on BaseScan. `FlowMemoryHookAdapter` was verified against deployment-source commit `11d562c` because `main` now contains the newer v4-shaped callback path. - `npm run deploy:base-sepolia` and `npm run deploy:base-sepolia:broadcast` provide Foundry deploy commands for the current V0 Base Sepolia testnet contract set. They require local env values and do not commit credentials. - A Base mainnet V0 canary deployment exists for testing only; deployed addresses and smoke transactions are recorded in `docs/DEPLOYMENTS/2026-05-13-base-canary-v0.md`. @@ -121,7 +122,7 @@ Launch-core specifications: - Production indexer or verifier service runtime. - Production persistence layer, production live RPC reader, production APIs, or hosted services. - Broad Base mainnet reader. -- Completed explorer source verification for the deployed canary contracts. Automation exists, but actual explorer acceptance requires `BASESCAN_API_KEY`. +- Broad production source-verification process for future redeploys. The current Base canary addresses are verified, but future deployments must be verified again before any production claim. - Explorer or hardware console implementation. - FlowRouter firmware, manufacturing, final enclosure work, or field deployment. - Real Meshtastic or LoRa device integration. diff --git a/docs/DEPLOYMENTS/2026-05-13-base-canary-v0.md b/docs/DEPLOYMENTS/2026-05-13-base-canary-v0.md index 460113ef..477363b1 100644 --- a/docs/DEPLOYMENTS/2026-05-13-base-canary-v0.md +++ b/docs/DEPLOYMENTS/2026-05-13-base-canary-v0.md @@ -164,16 +164,33 @@ The script uses `fixtures/deployments/base-canary-v0.json`, requires no private key, redacts the API key in generated plans, and writes a non-secret report to `fixtures/deployments/base-canary-source-verification-plan.json` by default. +## Source Verification Status + +Status: complete for the current Base canary deployment. + +- Verification date: 2026-05-13. +- Status report: + `fixtures/deployments/base-canary-source-verification-status.json`. +- `RootfieldRegistry`, `ArtifactRegistry`, `CursorRegistry`, + `ReceiptVerifier`, `WorkerRegistry`, `VerifierRegistry`, + `WorkReceiptRegistry`, `VerifierReportRegistry`, and `WorkDebtScheduler` + were verified against current `main` source. +- `FlowMemoryHookAdapter` was verified against deployment-source commit + `11d562c` because current `main` now has the newer v4-shaped callback path + that was added after this canary address was deployed. + +This means the current canary addresses are source-verified, not that the newer +`FlowMemoryHookAdapter` source has been redeployed or that the adapter is a +production Uniswap v4 PoolManager hook. + ## Important Gaps Found -1. Contract source verification automation exists, but actual submission - requires `BASESCAN_API_KEY` and explorer acceptance. -2. `FlowMemoryHookAdapter` now exposes a dependency-light Uniswap v4-shaped +1. `FlowMemoryHookAdapter` now exposes a dependency-light Uniswap v4-shaped `afterSwap` callback path, but it is not a production hook deployment wired into PoolManager permissions. -3. Ownership is still direct deployer ownership where applicable. There is no +2. Ownership is still direct deployer ownership where applicable. There is no multisig, governance, recovery, or operational key policy. -4. Verifier and worker registry flows are deployed, but live verifier report +3. Verifier and worker registry flows are deployed, but live verifier report submission, report signing, and verifier economics are not built. ## Notes diff --git a/docs/OPERATIONS/V0_OPERATOR_POLICY.md b/docs/OPERATIONS/V0_OPERATOR_POLICY.md index 6c17302d..17d8e7b2 100644 --- a/docs/OPERATIONS/V0_OPERATOR_POLICY.md +++ b/docs/OPERATIONS/V0_OPERATOR_POLICY.md @@ -30,7 +30,7 @@ with production readiness. Production language remains blocked until a later decision records: -1. source verification completed for every deployed contract; +1. source verification completed for every deployed or redeployed contract; 2. operational owner separation for deployer, worker admin, verifier admin, and emergency response; 3. multisig or comparable account-control decision; @@ -53,8 +53,8 @@ Production language remains blocked until a later decision records: ## Current Gaps -- Source verification automation exists, but actual submission requires - `BASESCAN_API_KEY`. +- Source verification is complete for the current canary addresses. Any + redeploy or new canary address must be verified again. - The canary deployer is still a single account. - There is no multisig, timelock, recovery, or operator separation. - `FlowMemoryHookAdapter` remains a hook-adjacent adapter, not a production diff --git a/fixtures/deployments/base-canary-source-verification-plan.json b/fixtures/deployments/base-canary-source-verification-plan.json index e2057a8e..0bd0a0e1 100644 --- a/fixtures/deployments/base-canary-source-verification-plan.json +++ b/fixtures/deployments/base-canary-source-verification-plan.json @@ -11,6 +11,8 @@ "productionReady": false, "submit": false, "checkBytecode": true, + "continueOnError": false, + "delayMs": 0, "apiKeyEnv": "BASESCAN_API_KEY", "contractCount": 10, "commands": [ diff --git a/fixtures/deployments/base-canary-source-verification-status.json b/fixtures/deployments/base-canary-source-verification-status.json new file mode 100644 index 00000000..a305ab76 --- /dev/null +++ b/fixtures/deployments/base-canary-source-verification-status.json @@ -0,0 +1,97 @@ +{ + "schema": "flowmemory.base_canary_source_verification_status.v0", + "verifiedAt": "2026-05-13T21:09:00Z", + "network": { + "name": "Base mainnet", + "chainId": "8453", + "environment": "mainnet" + }, + "productionReady": false, + "notes": [ + "All current Base canary addresses are source-verified on BaseScan.", + "FlowMemoryHookAdapter was verified against deployment-source commit 11d562c because main now contains a newer v4-shaped callback path added after deployment.", + "This report is not a production-readiness claim and does not make the adapter a production Uniswap v4 PoolManager hook." + ], + "contracts": [ + { + "name": "RootfieldRegistry", + "address": "0x2a7ADd68a1d45C3251E2F92fFe4926124654a97C", + "sourceName": "contracts/RootfieldRegistry.sol:RootfieldRegistry", + "sourceCommit": "328f14a7ae65c38494d373b485fa400927ee7920", + "verified": true, + "url": "https://basescan.org/address/0x2a7add68a1d45c3251e2f92ffe4926124654a97c" + }, + { + "name": "FlowMemoryHookAdapter", + "address": "0x179Df6d52e9DeF5D02704583a2E4E5a9FF427245", + "sourceName": "contracts/FlowMemoryHookAdapter.sol:FlowMemoryHookAdapter", + "sourceCommit": "11d562c90b8bf5d2bb7d860fa45701fd0c4fb89f", + "verified": true, + "url": "https://basescan.org/address/0x179df6d52e9def5d02704583a2e4e5a9ff427245" + }, + { + "name": "ArtifactRegistry", + "address": "0x8F074d0F4e66975b740A4b7a316330c9660a485E", + "sourceName": "contracts/ArtifactRegistry.sol:ArtifactRegistry", + "sourceCommit": "328f14a7ae65c38494d373b485fa400927ee7920", + "verified": true, + "url": "https://basescan.org/address/0x8f074d0f4e66975b740a4b7a316330c9660a485e" + }, + { + "name": "CursorRegistry", + "address": "0x3360689009685eade15c876855D24161b05829C1", + "sourceName": "contracts/CursorRegistry.sol:CursorRegistry", + "sourceCommit": "328f14a7ae65c38494d373b485fa400927ee7920", + "verified": true, + "url": "https://basescan.org/address/0x3360689009685eade15c876855d24161b05829c1" + }, + { + "name": "ReceiptVerifier", + "address": "0x94ba7aA4562f8F8528C327378F6352350f6ddB5B", + "sourceName": "contracts/ReceiptVerifier.sol:ReceiptVerifier", + "sourceCommit": "328f14a7ae65c38494d373b485fa400927ee7920", + "verified": true, + "url": "https://basescan.org/address/0x94ba7aa4562f8f8528c327378f6352350f6ddb5b" + }, + { + "name": "WorkerRegistry", + "address": "0xa8c07eF53Eeb4e57297ee35025a9cD5303fCCD29", + "sourceName": "contracts/WorkerRegistry.sol:WorkerRegistry", + "sourceCommit": "328f14a7ae65c38494d373b485fa400927ee7920", + "verified": true, + "url": "https://basescan.org/address/0xa8c07ef53eeb4e57297ee35025a9cd5303fccd29" + }, + { + "name": "VerifierRegistry", + "address": "0xAf920ca7436Bb72172E27C96E0B716f01dcC5DBd", + "sourceName": "contracts/VerifierRegistry.sol:VerifierRegistry", + "sourceCommit": "328f14a7ae65c38494d373b485fa400927ee7920", + "verified": true, + "url": "https://basescan.org/address/0xaf920ca7436bb72172e27c96e0b716f01dcc5dbd" + }, + { + "name": "WorkReceiptRegistry", + "address": "0x2874cee0D581E4562ac9015BfCf330f1ea58a1F3", + "sourceName": "contracts/WorkReceiptRegistry.sol:WorkReceiptRegistry", + "sourceCommit": "328f14a7ae65c38494d373b485fa400927ee7920", + "verified": true, + "url": "https://basescan.org/address/0x2874cee0d581e4562ac9015bfcf330f1ea58a1f3" + }, + { + "name": "VerifierReportRegistry", + "address": "0x95bC7455AdFD60e1B908ba455c25Ae732C1Ef996", + "sourceName": "contracts/VerifierReportRegistry.sol:VerifierReportRegistry", + "sourceCommit": "328f14a7ae65c38494d373b485fa400927ee7920", + "verified": true, + "url": "https://basescan.org/address/0x95bc7455adfd60e1b908ba455c25ae732c1ef996" + }, + { + "name": "WorkDebtScheduler", + "address": "0xa752e9bC7fAf39f659110D8Cf408E7707db94E34", + "sourceName": "contracts/WorkDebtScheduler.sol:WorkDebtScheduler", + "sourceCommit": "328f14a7ae65c38494d373b485fa400927ee7920", + "verified": true, + "url": "https://basescan.org/address/0xa752e9bc7faf39f659110d8cf408e7707db94e34" + } + ] +} diff --git a/infra/scripts/verify-base-canary-sources.mjs b/infra/scripts/verify-base-canary-sources.mjs index 65c43437..bf89b1d5 100644 --- a/infra/scripts/verify-base-canary-sources.mjs +++ b/infra/scripts/verify-base-canary-sources.mjs @@ -23,6 +23,8 @@ const submit = flags.has("--submit"); const json = flags.has("--json"); const watch = flags.has("--watch"); const checkBytecode = flags.has("--check-bytecode"); +const continueOnError = flags.has("--continue-on-error"); +const delayMs = Number(valueAfter("--delay-ms", "0")); const artifact = JSON.parse(readFileSync(resolve(deploymentPath), "utf8")); if (artifact.schema !== "flowmemory.deployment_artifact.v0") { @@ -64,13 +66,27 @@ function verificationArgs(contract, apiKeyValue) { return result; } +function redact(value) { + if (!apiKey) return value; + return value.replaceAll(apiKey, `<${apiKeyEnv}>`); +} + +function redactArgs(commandArgs) { + return commandArgs.map((arg) => redact(arg)); +} + +function sleep(milliseconds) { + if (milliseconds <= 0) return; + Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, milliseconds); +} + function run(command, commandArgs) { const result = spawnSync(command, commandArgs, { cwd: process.cwd(), stdio: "inherit", }); if (result.status !== 0) { - throw new Error(`${command} ${commandArgs.join(" ")} failed with exit code ${result.status ?? "unknown"}`); + throw new Error(`${command} ${redactArgs(commandArgs).join(" ")} failed with exit code ${result.status ?? "unknown"}`); } } @@ -102,6 +118,8 @@ const plan = { productionReady: false, submit, checkBytecode, + continueOnError, + delayMs, apiKeyEnv, contractCount: artifact.contracts.length, commands: artifact.contracts.map((contract) => ({ @@ -119,7 +137,26 @@ if (json || !submit) { } if (submit) { + const failures = []; for (const contract of artifact.contracts) { - run("forge", verificationArgs(contract, apiKey)); + try { + run("forge", verificationArgs(contract, apiKey)); + } catch (error) { + failures.push({ + name: contract.name, + address: contract.address, + error: redact(error instanceof Error ? error.message : String(error)), + }); + if (!continueOnError) { + throw new Error(failures.at(-1).error); + } + } + sleep(delayMs); + } + if (failures.length > 0) { + const failure = new Error(`source verification completed with ${failures.length} failure(s)`); + failure.failures = failures; + console.error(JSON.stringify({ schema: "flowmemory.base_canary_source_verification_failures.v0", failures }, null, 2)); + process.exitCode = 1; } }