Skip to content

Commit b4a6d42

Browse files
Mayakovskyclaude
andauthored
Finish Gnosis registration prep + chain-scoped observeOnly (directive-100/101) (#54)
* feat(mech-adapter): finish Gnosis registration prep + chain-scoped observeOnly (directive-100/101) register-live.ts gains --chain (base default/gnosis), reusing CHAINS from directive-97/98 rather than hardcoding Base's RPC/chain id. The passphrase-gated signing path is untouched -- this only changes which chain's RPC/contracts a Forces-run signed call targets. Fresh dry-run confirms it resolves to the same already-verified create() target (predicted serviceId 3789 on real Gnosis state). config.ts/main.ts: loadChainId()/loadMechIdentity() let the production entry point run against a chain other than Base without touching Base's default behavior -- verified byte-identical when no new env vars are set (same chain id, same hardcoded mech/multisig addresses, same RPC). On any non-Base chain, mech/multisig addresses are required via env and fail closed if missing, since they don't exist until that chain's real ServiceRegistry lifecycle actually completes. New grey-mech-adapter-gnosis.service is the actual fix for directive-100 Sec1.3's finding: MECH_ADAPTER_OBSERVE_ONLY was one flag on one shared process. Entirely separate unit, own EnvironmentFile, own observeOnly value -- flipping Gnosis's can never touch Base's live one. Not installed on the VPS yet: real MECH_ADDRESS/MECH_MULTISIG_ADDRESS don't exist until the pending registration lands, and loadMechIdentity() fails closed without them, so there's nothing to meaningfully start yet. vitest run: 91 passed, 2 skipped, 0 failed. tsc --noEmit clean on all three gated configs. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoiqDXzQQeejwguqcQFzBL * fix(mech-adapter): urgent -- register-live.ts had no way to resume a real serviceId across restarts (directive-103) D-101's --chain gnosis support hardcoded EXISTING_SERVICE_ID = undefined for any non-Base chain. Real, live consequence: Forces' terminal closed between two runs, the script forgot serviceId 3789 (real create(), tx 0xb780b849...) and created a second, orphaned service 3790 (tx 0x8c6d25b0...) instead of resuming. No funds harmed (create() sends no value), but a real gap. Adds registrationResume.ts's resolveExistingServiceId: a --service-id <n> flag (validated against getService before trusting it -- fails closed on NonExistent), plus a balanceOf-based safety check when no default/flag is given. ServiceRegistryL2 supports balanceOf but not owner-indexed enumeration (tokenOfOwnerByIndex reverts, confirmed live), so the check can only report a count -- enough to abort the exact silent-duplicate-create scenario that produced 3790, not enough to recover which id to resume, hence the flag is still required. Base is unchanged: hardcoded default 635n still wins when no flag is passed. FINAL SUMMARY output now says RESUMING vs CREATING A NEW SERVICE explicitly, and the abort happens before the passphrase prompt. Both real paths proven per directive-103's own instruction, via mocks (no real chain touch) in test/registrationResume.test.ts, then independently re-checked against real current Gnosis state: omitting --service-id now correctly aborts (balanceOf=2, would have prevented the real 3790 duplicate); --service-id 3789 correctly resolves to resume. 3790 is a real, confirmed orphan -- left untouched per directive-103 Sec2, no cheap way to reclaim/delete it and no further cost from leaving it in PreRegistration. Next real command for Forces: pnpm register:live -- --chain gnosis --service-id 3789 vitest run: 97 passed (91 + 6 new), 2 skipped, 0 failed. tsc --noEmit clean on all three gated configs. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoiqDXzQQeejwguqcQFzBL * fix(mech-adapter): urgent -- deploy() and createMech hardcoded Base's multisig/factory regardless of chain (directive-104) Real, live consequence: Forces ran register-live.ts --chain gnosis --service-id 3789 for the deploy step. Pre-flight simulateContract reverted UnauthorizedMultisig(0x22bE...B83) -- caught before broadcast, no funds touched, service 3789 unchanged at FinishedRegistration. Root cause: mechAdapter.ts:709 read SERVICE_REGISTRY_ADDRESSES .gnosisSafeMultisig directly, Base's hardcoded constant, regardless of which chain the adapter is actually running on. D-97/98's chain-parameterization covered the client constructors but missed this direct import inside mechAdapter.ts's deploy path. Audit (per this directive's own instruction) found a second, not-yet-hit gap of the same shape: mechAdapter.ts:722's createMech step read MARKETPLACE_ADDRESSES.factories[paymentType] directly -- would have broken the very next real step past deploy, the same way. Fix: ServiceRegistryClient now exposes gnosisSafeMultisig (resolved from its own chainId at construction, mirroring how it already resolves serviceManagerProxy/serviceRegistryL2). MarketplaceClient now exposes getFactoryAddress(paymentType), same pattern, failing closed if the requested payment type has no factory on that chain (Gnosis has 3 factories, not Base's 5 -- confirmed D-97). mechAdapter.ts reads both from the injected clients instead of importing the bare Base constants, which are no longer imported into this file at all. Both paths proven (Base unchanged, Gnosis now correct) per directive-104 Sec2's own instruction: test/chainParameterization.test.ts -- client-level resolution for both chains, plus two mechAdapter-level tests proving runDeployStep/runCreateMechStep actually read from the injected clients (using deliberately distinctive fake values that would fail if the code regressed to importing the hardcoded constants again). Also independently re-confirmed against real, current Gnosis state (read- only, no key material): the same deploy() call that reverted now simulates cleanly, predicting multisig 0x5587335a6Fa1Dc7C421f2b87D91C7E9def095872 -- notably, identical to Grey's already-deployed real Base multisig, plausible given deterministic CREATE2 Safe-proxy addressing, flagged plainly rather than silently noted. vitest run: 104 passed (97 + 7 new), 2 skipped, 0 failed. tsc --noEmit clean on all three gated configs. Next command for Forces is unchanged: pnpm register:live -- --chain gnosis --service-id 3789 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoiqDXzQQeejwguqcQFzBL * fix(infra): point Gnosis systemd unit at isolated staging checkout, not shared main (directive-106) Base's live grey-mech-adapter.service and all other grey-* units share one checkout at /opt/grey/grey, still on main pre-arc. Repointing this unit's WorkingDirectory at a separate, isolated checkout (/opt/grey/grey-gnosis-staging, checked out to this same PR branch) means deploying it touches zero shared state -- no merge required, no risk to Base's live process on any future restart. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoiqDXzQQeejwguqcQFzBL * fix(mech-adapter): main.ts never injected a chain-aware marketplaceClient (directive-106) Third instance of the D-104 bug class, caught live during the Gnosis staging deploy: MechAdapter.start() called numMechs() against Base's marketplace proxy address while running on Gnosis's own RPC ("returned no data"). Root cause: MechAdapter's constructor default (createMarketplaceClient(rpcUrl), no chainId) silently resolves to 8453 whenever no marketplaceClient is injected -- main.ts never injected one, on any chain, since it was first written. Fix: main.ts now constructs createMarketplaceClient(config.rpcUrl, undefined, chainId) explicitly and passes it in. register-live.ts was already correct (constructs both clients with chainId explicitly, directive-103). vitest run: 104 passed, 2 skipped, 0 failed. tsc --noEmit clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoiqDXzQQeejwguqcQFzBL * fix(mech-adapter): requiredAddress()/loadMechIdentity never checksum-normalized addresses (directive-106) Fourth real bug caught live in the same Gnosis staging deploy: MechAdapter.start()'s checkMech() call threw "Address must match its checksum counterpart" -- the real MECH_ADDRESS env value (copied directly from D-105's mail field) was shape-valid but not in strict EIP-55 checksum case. requiredAddress() only ever validated hex shape via regex, never checksum, so a wrongly-cased address slipped through silently and only failed deep inside viem's own strict enforcement, far from where the real problem (a manually-transcribed env value) originated. Fix: requiredAddress() now runs every resolved address through viem's getAddress(), which accepts any validly-shaped input and normalizes to the correct checksum -- safe for the many already-correct addresses already in production, and closes this specific gap for any future env-provided address regardless of how it's capitalized. Also fixed loadMechIdentity's Base-override path, which bypassed requiredAddress entirely. vitest run: 106 passed (104 + 2 new), 2 skipped, 0 failed. tsc --noEmit clean on both gated configs. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoiqDXzQQeejwguqcQFzBL * docs(mech-adapter): author Gnosis's off-chain offering-set metadata (directive-107 e3-g2) service-config-gnosis.json/mech-payload-gnosis.json mirror Base's real tool/pricing content (prediction_market_research/resolution_evidence_ compiler, CACHE_ONLY 0.65x), noting the real 3 payment types Gnosis actually has (NATIVE/TOKEN/NVM_NATIVE, not Base's 5 -- directive-97). Descriptive only, explicitly marked as such in both files: service 3789's real on-chain configHash stays Base's own, permanently, per Forces' directive-106 decision (GREY_DID is one cross-chain identity anchor by design, and ServiceRegistryL2.update() requires PreRegistration state -- already closed for 3789 regardless). Added the same note to GREY_MECH_REGISTERED_TOOLS's own doc comment in config.ts, the closest thing this codebase has to a documented offering set for a human reader, so nobody mistakes the permanent Base hash for a bug later. No new IPFS pin yet -- would need the VPS's Filebase credentials, which this pass didn't touch; these files are ready to pin whenever that's wanted, but pinning isn't required for anything real to work since the on-chain hash never references them. tsc --noEmit clean, vitest run 106 passed unchanged (comment-only config.ts change). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoiqDXzQQeejwguqcQFzBL * Revert "docs(mech-adapter): author Gnosis's off-chain offering-set metadata (directive-107 e3-g2)" This reverts commit bac3221. * fix(mech-adapter): urgent -- register-live.ts's createMech step never encoded a real delivery rate (directive-110) Real, live consequence: Grey's Gnosis mech (0x1A235555..., real serviceId 3789) is permanently unable to receive a valid payment. maxDeliveryRate() reads back byte-for-byte identical to GREY_MECH_PAYLOAD_HASH -- the IPFS metadata hash, reinterpreted as a uint256, is astronomically large. Exact same bug as directive-51 on Base, which D-53/55 only ever worked around (a second, corrected mech) without fixing this script -- so it reproduced identically the first time this script's createMech step actually ran on a second chain. Root-cause fix, register-live.ts: a required-when-needed --delivery-rate <wei> flag; the createMech payload is now genuinely encodeAbiParameters(['uint256'], [deliveryRateWei]), never the raw hash. If the resolved next step turns out to be createMech and no --delivery-rate was given, this now fails closed with an explicit error before the REGISTER prompt -- extracted as registrationResume.ts's resolveMechPayload so the encoding is independently unit-tested (test/mechPayload.test.ts), not just provable by re-running the real script. Fork-proved the corrected registration for real (Hardhat fork of current Gnosis mainnet state, hardhat.config.cts's pin bumped past the real deploy()/createMech() lifecycle so the fork sees service 3789 already Deployed): MechMarketplace.create(3789, NATIVE_FACTORY, abi.encode(uint256(130000000000000000))) succeeds via hardhat_impersonateAccount (no private key), and the resulting mech's maxDeliveryRate() reads back exactly 130000000000000000 (0.13 xDAI/ETH, Forces' confirmed real price) -- test/fork/ correctedGnosisMech.forkcheck.ts, run via the new test:fork:gnosis-corrected-mech script. This does NOT execute the real signed call -- that stays Forces' passphrase-gated action. config.ts: renamed/documented the broken address as GNOSIS_MECH_ADDRESS_ORIGINAL_INERT (mirrors GREY_MECH_ADDRESS_ORIGINAL_ INERT's own permanent doc-comment discipline), and prepared (not yet applied) the audit list of every place referencing it as if it were live, to update once the real corrected mech exists. vitest run: 110 passed (106 + 4 new), 2 skipped, 0 failed. tsc --noEmit clean on all three gated configs. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoiqDXzQQeejwguqcQFzBL * fix(mech-adapter): resolve step+payload before preflight simulate (BION-DIRECTIVE-111) register-live.ts computed the real createMech payload only AFTER calling MechAdapter.registerAsMechStep to learn the next step -- but that call both determines AND simulates the step in one shot, so the preflight simulate ran with the stale '0x' placeholder. Forces' real run hit exactly this and aborted safely at pre-flight, before any confirmation prompt. Extract nextStepForState(state) into registrationResume.ts as the single source of truth for the state->step mapping (mechAdapter.ts now uses it internally too, so the two call sites can't drift). register-live.ts now reads real service state, derives the step, and resolves the real ABI-encoded payload via resolveMechPayload -- all before constructing params or ever calling registerAsMechStep -- so the preflight simulate runs with the correct payload on the first attempt. Add test/fork/registerLivePreflightOrdering.forkcheck.ts: a real Hardhat fork proof against Gnosis service 3789 (still Deployed) exercising the same real shared functions in the same real order, including a negative control that proves simulating with the old placeholder actually reverts on this same forked state -- demonstrating this proof would have caught the D-111 bug, unlike D-110's fork proof, which never exercised the buggy call order. vitest: 110 passed, 2 skipped, 0 failed. tsc --noEmit clean on all three gated configs. New fork proof: 2 passed. Existing D-110 fork proof: 2 passed, unaffected. * feat(mech-adapter): add real GNOSIS_MECH_ADDRESS constant (BION-DIRECTIVE-112) Forces ran the D-111-corrected register-live.ts for real: tx 0x62c919b2ff77016fc42fea9123db6e7c884c1a9f008070733c3946c28fd1e747, service 3789's createMech step. Desktop independently re-confirmed on-chain: maxDeliveryRate() reads back exactly 130000000000000000 wei (0.13 xDAI) -- this mech is real, correctly priced, and payable. Adds GNOSIS_MECH_ADDRESS = 0xf482B2Abbd0230b960320096B7b132fABc66830b, same doc-comment discipline as GREY_MECH_ADDRESS. Corrects the systemd unit's now-stale comment naming the superseded, permanently-unpayable GNOSIS_MECH_ADDRESS_ORIGINAL_INERT as "the real mech" -- points at config.ts instead of hardcoding an address that can go stale again. tsc --noEmit clean, vitest 110/110 passing. * feat(mech-adapter): build the real self-test request script (BION-DIRECTIVE-113) Forces authorized the self-directed test request (real request -> deliver -> settle cycle against the live, corrected Gnosis mech). Adds scripts/self-test-request.ts -- same operator-runs-this/Kov-builds-this split as register-live.ts: interactive-TTY-only passphrase, preflight simulateContract before any broadcast, typed confirmation before executing for real. Resolves every real value (mech's own maxDeliveryRate/paymentType, the pinned request-content hash) before any passphrase prompt or simulate, per D-111's own ordering lesson. Pins the real request content to Filebase first (same real pin-and-verify mechanism responsePinner.ts already proves for response content) so the live adapter can actually fetch it. After a real submission, watches getRequestStatus() for Delivered, then fetches and prints the real delivered response content -- proof of the whole cycle, not just a landed transaction. Real, fork-proof-discovered finding: MechMarketplace.request() enforces responseTimeout in [60, 300] seconds (OutOfBounds otherwise) -- not documented anywhere, found by the fork proof reverting on a 900s guess. 300s is therefore both the real protocol max AND coincides with the live adapter's own default poll interval (config.ts's loadPollIntervalMs) -- flagged as a real, load-bearing timing risk this creates, not glossed over. New test/fork/selfTestRequest.forkcheck.ts: real Hardhat fork proof against the real, live GNOSIS_MECH_ADDRESS -- the exact live-read values + derived content hash + request() call the script makes, succeeding for real and recording a real pending (RequestedPriority) request; plus a negative control proving the [60, 300] responseTimeout bound. Bumped the Gnosis fork pin (hardhat.config.cts) past the real corrected-mech creation tx so the fork can see GNOSIS_MECH_ADDRESS at all. vitest: 110 passed, 2 skipped, 0 failed. tsc --noEmit clean on all three gated configs. All three Gnosis fork proofs (D-110, D-111, D-113): 6 passed. * fix(mech-adapter): self-test-request.ts must route around the known-broken gateway (BION-DIRECTIVE-114) Forces ran pnpm self-test:request twice for real; both failed identically at Filebase pin-verification (ResponsePinVerificationError) before any keystore/passphrase interaction. Root cause, confirmed live, not assumed: the script built createFilebasePinner without an explicit gatewayBaseUrl, so it silently used the hardcoded default, gateway.autonolas.tech -- whose IPFS-resolution backend was already found genuinely broken once before (BION-DIRECTIVE-57, 2026-08-13) and is still broken today (re-confirmed live during this directive: a curl against that same old, definitely-still- pinned D-57 CID timed out completely, 20s, zero bytes, while ipfs.io resolved the identical content in 0.2s). Not a propagation-delay issue a wider retry budget would fix -- the gateway doesn't respond at all, so retrying more just wastes more time against a dead backend. Production (main.ts's loadGatewayOverride) already has the real, proven fix: route both gateway-dependent legs (pin-verify and request-content-fetch) through MECH_ADAPTER_PIN_VERIFY_GATEWAY_URL, set to https://ipfs.io on the live Base unit. self-test-request.ts now does the same -- reads the same env var, defaulting to https://ipfs.io directly (rather than the broken gateway) if unset, since this standalone script has no other safety net. New test/gatewayOverride.livecheck.test.ts (gated behind GREY_MECH_LIVE_GATEWAY_CHECK=1, skipped by default): a real, live (not stubbed) network test proving the actual fix -- the broken default gateway really fails against known-good, already-resolvable content (D-57's own real pinned CID), and the override really resolves the identical content. A genuinely fresh pin-and-verify isn't provable from here without real Filebase credentials (deliberately never held by this codebase/Kov, same as every other real secret) -- this is what CAN be proven for real without them, and it directly validates the mechanism the fix depends on. vitest: 110 passed, 4 skipped (2 new, gated), 0 failed. Live gateway check run explicitly: 2 passed. tsc --noEmit clean on all three gated configs. Real, separate, unresolved question this surfaced: whether /etc/grey/mech-adapter-gnosis.env also sets MECH_ADAPTER_PIN_VERIFY_GATEWAY_URL -- if not, the live Gnosis adapter itself (not just this script) is exposed to the same broken-gateway failure the next time it needs to fetch a real request's content. Flagged for Forces/Desktop to check directly; no VPS access from here to verify. * fix(mech-adapter): createSafeDeliveryClient hardcoded Base chain, breaking Gnosis delivery (BION-DIRECTIVE-115) Real, live production bug, caught by the "First real Gnosis mech transaction watch": the live grey-mech-adapter-gnosis.service picked up BION-DIRECTIVE-113's self-test request and tried to deliver it via the Safe's execTransaction, but every attempt failed at eth_sendRawTransaction with "invalid chain id for signer: have 8453 want 100". Root cause: createSafeDeliveryClient hardcoded viem's `base` chain object for both its public and wallet clients, completely independent of the chainId actually in use -- so on Gnosis, the raw transaction it signed always embedded chainId 8453 regardless of which chain rpcUrl pointed at. This was the one client in the package the D-97/98/104/106 chain-parameterization pass never touched (serviceRegistryClient.ts and marketplaceClient.ts were fixed; this one wasn't), and safeDeliveryClient's own anvil fork test only ever forks Base, so nothing caught it until a real delivery on Gnosis actually needed it. Fix: createSafeDeliveryClient now takes an optional chainId (default 8453, Base's own real delivery path completely unaffected unless a caller explicitly passes 100 -- same "behavior-identical unless explicit opt-in" discipline the earlier chain-parameterization fixes established), and resolves its clients' chain object from CHAINS[chainId] instead of the bare `base` import. main.ts now passes the real chainId through. Added a `chainId` diagnostic property to SafeDeliveryClient's own interface so this is independently testable without a real network call or an anvil fork (same posture as ServiceRegistryClient.gnosisSafeMultisig/ MarketplaceClient.getFactoryAddress) -- that property's absence is exactly why this bug went unnoticed. New tests in chainParameterization.test.ts: Base (8453, default) and Gnosis (100) both construct with the correct chain id. vitest: 112 passed (2 new), 4 skipped, 0 failed. tsc --noEmit clean on all three gated configs. * fix(mech-adapter): self-test-request.ts Step 5 used the wrong content-fetch function (BION-DIRECTIVE-116) Step 5 (fetching the delivered response to print real proof of the whole cycle) called fetchRequestContent on RESPONSE content -- that function validates for {prompt, tool} fields specifically (real REQUEST shape, requestContent.ts's own RequestContent interface), but a real prediction_market_research response is shaped completely differently ({market, status, analysis, lastAnalysed, note}) and has neither field, so it always failed to parse and threw "not a valid request document" -- on every real run, right after a real successful delivery. Added fetchArbitraryContent: same real gateway-fallback shape (direct CID, then /metadata.json) minus the request-specific shape validation, since response content just needs to be valid JSON, of any shape. Verified live against the actual real delivered content from D-115's now-confirmed delivery (requestId 0x40eb64b8...fa7769, dataHash 0xac3f3041...ff10f1): resolves correctly via the metadata.json fallback, real body confirmed matching the expected prediction_market_research response schema. tsc --noEmit clean on all three gated configs. vitest: 112 passed, 4 skipped, 0 failed -- no regressions (this fix only touches the script, no shared library changed). --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 47ba769 commit b4a6d42

22 files changed

Lines changed: 1788 additions & 61 deletions

‎.env.example‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,34 @@ MECH_ADAPTER_POLL_INTERVAL_MS=300000
138138
# BASE_MECH_AGENT_INSTANCE_PRIVATE_KEY / MECH_ADAPTER_FILEBASE_ACCESS_KEY_ID /
139139
# MECH_ADAPTER_FILEBASE_SECRET_ACCESS_KEY / MECH_ADAPTER_FILEBASE_BUCKET
140140
# [/ MECH_ADAPTER_PIN_VERIFY_GATEWAY_URL]
141+
#
142+
# --- Chain-scoping (BION-DIRECTIVE-101 §3) — Gnosis, entirely separate process/unit ---
143+
# MECH_ADAPTER_CHAIN_ID — which chain this adapter PROCESS runs against. Defaults to 8453 (Base)
144+
# when unset; every existing deployment (Base's) has no such var and is unaffected. Only 8453 or
145+
# 100 are valid (config.ts's loadChainId() throws on anything else).
146+
# MECH_ADAPTER_CHAIN_ID=8453
147+
#
148+
# MECH_ADAPTER_RPC_URL — generic override, checked before the legacy BASE_RPC_URL, before the
149+
# chain's own default RPC. Optional on Base (BASE_RPC_URL still works as before); needed on Gnosis
150+
# unless the public default (rpc.gnosischain.com) is acceptable.
151+
# MECH_ADAPTER_RPC_URL=
152+
#
153+
# MECH_ADDRESS / MECH_MULTISIG_ADDRESS — the real, factory-created mech + its Safe multisig this
154+
# process polls/delivers for. On Base (chainId 8453), OMITTING these defaults to the hardcoded,
155+
# real, already-registered GREY_MECH_ADDRESS/GREY_MECH_MULTISIG_ADDRESS (config.ts) — every real
156+
# deployment today omits them, unaffected. On any OTHER chain there is NO default: these don't
157+
# exist until that chain's real ServiceRegistry lifecycle (create/activate/registerAgents/deploy,
158+
# BION-DIRECTIVE-100/101) actually completes — loadMechIdentity() fails closed (throws at startup)
159+
# without them, on purpose, rather than guess.
160+
# MECH_ADDRESS=
161+
# MECH_MULTISIG_ADDRESS=
162+
#
163+
# /etc/grey/mech-adapter-gnosis.env (infra/systemd/grey-mech-adapter-gnosis.service — NOT YET
164+
# INSTALLED on the VPS as of this commit; MECH_ADDRESS/MECH_MULTISIG_ADDRESS don't have real values
165+
# yet, see above). Once real: same shape as the Base file, plus the three new vars —
166+
# BASE_MECH_PAY_TO / BASE_MECH_POOL_WALLET / GREY_DATABASE_URL / MECH_ADAPTER_RPC_URL /
167+
# MECH_ADAPTER_CHAIN_ID=100 / MECH_ADAPTER_OBSERVE_ONLY (must start true) /
168+
# MECH_ADAPTER_POLL_INTERVAL_MS / BASE_MECH_AGENT_INSTANCE_PRIVATE_KEY (same key, same wallet,
169+
# reused across chains per D-77) / MECH_ADAPTER_FILEBASE_* (same credentials, reused) /
170+
# MECH_ADDRESS / MECH_MULTISIG_ADDRESS (real values, once D-100/101's registration lands)
171+
# [/ MECH_ADAPTER_PIN_VERIFY_GATEWAY_URL]

‎adapters/mech-adapter/hardhat.config.cts‎

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,16 @@ const FORK_CHAIN_CONFIG: Record<
2727
chainId: 100,
2828
defaultRpcUrl: 'https://rpc.gnosischain.com',
2929
rpcEnvVar: 'GNOSIS_FORK_RPC_URL',
30-
// Picked comfortably recent during D-97/98 research (real chain head read live via
31-
// eth_blockNumber was 47_827_394 at the time; a real request in the Gnosis marketplace
32-
// subgraph exists at block 47_827_388, so this postdates real, current marketplace activity,
33-
// not just the contract's original deployment). Bump if the RPC's retained history window
34-
// ages it out, same caveat as Base's entry above.
35-
blockNumber: 47_827_450,
30+
// BION-DIRECTIVE-113 — bumped again from D-110's 47_843_700: that block predates the real,
31+
// now-executed corrected createMech call (BION-DIRECTIVE-111/112, tx
32+
// 0x62c919b2ff77016fc42fea9123db6e7c884c1a9f008070733c3946c28fd1e747, landed at block
33+
// 47_844_995), so it couldn't be used to fork-prove anything against GNOSIS_MECH_ADDRESS's
34+
// real, live, correctly-priced state. This pin (real chain head read live via eth_blockNumber
35+
// was 47_846_148 at the time) postdates the corrected mech's creation, so the fork genuinely
36+
// sees the real GNOSIS_MECH_ADDRESS mech, already deployed and payable. Bump again if the
37+
// RPC's retained history window ages it out, or once service 3789 undergoes any further real
38+
// on-chain change this fork needs to see.
39+
blockNumber: 47_846_000,
3640
},
3741
};
3842

‎adapters/mech-adapter/package.json‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414
"typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig.test.json && tsc --noEmit -p tsconfig.scripts.json",
1515
"test": "vitest run",
1616
"test:fork": "cross-env TS_NODE_PROJECT=tsconfig.hardhat.json NODE_OPTIONS=--loader=ts-node/esm hardhat test test/fork/marketplaceRead.forkcheck.ts test/fork/serviceRegistryWrite.forkcheck.ts",
17-
"register:live": "tsx scripts/register-live.ts"
17+
"test:fork:gnosis-corrected-mech": "cross-env MECH_FORK_CHAIN=gnosis TS_NODE_PROJECT=tsconfig.hardhat.json NODE_OPTIONS=--loader=ts-node/esm hardhat test test/fork/correctedGnosisMech.forkcheck.ts",
18+
"test:fork:register-live-ordering": "cross-env MECH_FORK_CHAIN=gnosis TS_NODE_PROJECT=tsconfig.hardhat.json NODE_OPTIONS=--loader=ts-node/esm hardhat test test/fork/registerLivePreflightOrdering.forkcheck.ts",
19+
"test:fork:self-test-request": "cross-env MECH_FORK_CHAIN=gnosis TS_NODE_PROJECT=tsconfig.hardhat.json NODE_OPTIONS=--loader=ts-node/esm hardhat test test/fork/selfTestRequest.forkcheck.ts",
20+
"test:live-gateway-check": "cross-env GREY_MECH_LIVE_GATEWAY_CHECK=1 vitest run test/gatewayOverride.livecheck.test.ts",
21+
"register:live": "tsx scripts/register-live.ts",
22+
"self-test:request": "tsx scripts/self-test-request.ts"
1823
},
1924
"dependencies": {
2025
"@grey/ceremony": "workspace:*",

0 commit comments

Comments
 (0)