Every live-state check in this repo starts from the pinned token tables, so a
vault that was deployed but never pinned is invisible to all of them.
What is verified today
StoxCrossChainParityTest forks Base, Ethereum and HyperEVM and runs
LibTokenInvariants.assertAll(tokens, safe, clone) per chain. For every row in
that chain's table it asserts the receipt vault's owner() is the chain's
token-owner Safe, its authorizer() is the chain's pinned V4 clone, its
receipt() is the pinned receipt with receipt.manager() pointing back, both
legs' name/symbol against LibProdTokenConfig, decimals against Base,
wrapped.asset(), and beacon lineage. assertChainLegs fails outright on a
half-hydrated table rather than skipping it, so the tables cannot go silently
partial either.
That is a strong check on the rows that are in the table.
The gap
The table is the query set, and the table is hand-transcribed from a broadcast
run's console output into LibTokenInvariants. If a run deployed a vault whose
tuple never made it into the table, nothing reads that vault — so nothing
asserts who owns it, what it is wired to, or that it exists at all. A dropped
row during transcription is exactly the failure a hand step produces, and it is
the one failure the entire parity suite cannot see, by construction.
The tables were populated this way for both target chains:
- Ethereum:
20260706-deploy-tokens-ethereum (manual-broadcast run 29921218929)
plus the RKLB gap-fill (run 29924926246)
- HyperEVM: run 30114307165, all 29 tokens in one broadcast
Neither script read back what it deployed at the time (fixed going forward in
#291 by assertHandoffLanded), and no check since has been able to ask whether
the set is complete.
Why it is not merely unobserved
20260807-deploy-missing-tokens defines "missing" as an underlying present in
productionTokensBase() and absent from the target chain's table. An unpinned
stray vault is absent from the table, so a re-dispatch would deploy a second
vault for that ticker, wire it, and hand it to the Safe as production. The
NoMissingTokens guard is computed from the pins, so it structurally cannot
protect against a gap in the pins. (The previous index-join model had the same
blind spot by a different route.)
Proposed check
A fork test that enumerates from chain rather than from the repo: pull every
Deployment(address,address,address) emitted by
LibProdDeployV4.STOX_UNIFIED_DEPLOYER_0_1_1 on each chain and assert the
emitted set equals the pinned table exactly — no extras, no missing.
vm.eth_getLogs(fromBlock, toBlock, target, topics) is available in
forge-std 1.16.1 (dependencies/forge-std-1.16.1/src/Vm.sol:650) and is
currently used nowhere in this repo, so this is a test rather than new tooling.
Notes for whoever picks it up:
fromBlock must be bounded to the unified deployer's deploy block; public
RPCs reject unbounded ranges.
- Base is in scope too. Its table has the same property, and Base is the source
of truth the other chains are copied from, so a gap there propagates.
- Set equality in both directions is the point. "Every pinned row was emitted"
is already implied by the parity suite; "every emitted deployment is pinned"
is the new information.
- A deployment that is legitimately not production (a test or aborted run
against the same deployer) would surface here as an extra. If any exist, they
need an explicit allowlist with a reason, not a loosened assertion.
Follow-up from the review of #291.
Every live-state check in this repo starts from the pinned token tables, so a
vault that was deployed but never pinned is invisible to all of them.
What is verified today
StoxCrossChainParityTestforks Base, Ethereum and HyperEVM and runsLibTokenInvariants.assertAll(tokens, safe, clone)per chain. For every row inthat chain's table it asserts the receipt vault's
owner()is the chain'stoken-owner Safe, its
authorizer()is the chain's pinned V4 clone, itsreceipt()is the pinned receipt withreceipt.manager()pointing back, bothlegs'
name/symbolagainstLibProdTokenConfig,decimalsagainst Base,wrapped.asset(), and beacon lineage.assertChainLegsfails outright on ahalf-hydrated table rather than skipping it, so the tables cannot go silently
partial either.
That is a strong check on the rows that are in the table.
The gap
The table is the query set, and the table is hand-transcribed from a broadcast
run's console output into
LibTokenInvariants. If a run deployed a vault whosetuple never made it into the table, nothing reads that vault — so nothing
asserts who owns it, what it is wired to, or that it exists at all. A dropped
row during transcription is exactly the failure a hand step produces, and it is
the one failure the entire parity suite cannot see, by construction.
The tables were populated this way for both target chains:
20260706-deploy-tokens-ethereum(manual-broadcast run 29921218929)plus the RKLB gap-fill (run 29924926246)
Neither script read back what it deployed at the time (fixed going forward in
#291 by
assertHandoffLanded), and no check since has been able to ask whetherthe set is complete.
Why it is not merely unobserved
20260807-deploy-missing-tokensdefines "missing" as anunderlyingpresent inproductionTokensBase()and absent from the target chain's table. An unpinnedstray vault is absent from the table, so a re-dispatch would deploy a second
vault for that ticker, wire it, and hand it to the Safe as production. The
NoMissingTokensguard is computed from the pins, so it structurally cannotprotect against a gap in the pins. (The previous index-join model had the same
blind spot by a different route.)
Proposed check
A fork test that enumerates from chain rather than from the repo: pull every
Deployment(address,address,address)emitted byLibProdDeployV4.STOX_UNIFIED_DEPLOYER_0_1_1on each chain and assert theemitted set equals the pinned table exactly — no extras, no missing.
vm.eth_getLogs(fromBlock, toBlock, target, topics)is available inforge-std 1.16.1 (
dependencies/forge-std-1.16.1/src/Vm.sol:650) and iscurrently used nowhere in this repo, so this is a test rather than new tooling.
Notes for whoever picks it up:
fromBlockmust be bounded to the unified deployer's deploy block; publicRPCs reject unbounded ranges.
of truth the other chains are copied from, so a gap there propagates.
is already implied by the parity suite; "every emitted deployment is pinned"
is the new information.
against the same deployer) would surface here as an extra. If any exist, they
need an explicit allowlist with a reason, not a loosened assertion.
Follow-up from the review of #291.