Summary
Several pieces of documentation in this repo describe behaviour the code does
not have. All verified against 4422e29 (v0.1.4). Grouped here because they
are one class of defect with one fix.
1. CLAUDE.md documents a function that no longer exists
CLAUDE.md still lists:
checkDependencies(...) — forks each network, verifies dependencies and Zoltu factory exist with expected codehashes
and:
deployAndBroadcast(...) — the main entry point: derives deployer from private key, calls checkDependencies then deployToNetworks
checkDependencies was folded into deployToNetworks in 503002e
("refactor(deploy): fold the dependency check into deployToNetworks"). There is
no such function in src/lib/LibRainDeploy.sol. The same section describes
deployToNetworks as "**re-**verifies dependencies", which is likewise a
leftover from the two-pass design.
Related, the "Key Design Patterns" section says:
Dependency checking: Before deploying to any network, all dependencies (contract addresses) are verified to have code on-chain.
Dependencies are now checked per network, and only on the deploy branch — an
already-deployed network skips the check entirely (deliberately; see the
deployToNetworks NatSpec).
2. CLAUDE.md describes the wrong deployment opcode
the Zoltu proxy is deployed at the same address on every chain and uses CREATE with a predictable nonce
The factory uses CREATE2 with a zero salt, not CREATE. Disassembling
ZOLTU_FACTORY_BYTECODE:
00000000: PUSH1 0x00
00000002: CALLDATASIZE
00000003: DUP2
00000004: DUP3
00000005: CALLDATACOPY
00000006: DUP1
00000007: CALLDATASIZE
00000008: DUP3
00000009: CALLVALUE
0000000a: CREATE2 <-- 0xf5, salt is the zero pushed at 0x00
0000000b: DUP1
...
Confirmed empirically — the following passes:
function testZoltuIsCreate2SaltZero() external pure {
assertEq(
address(uint160(uint256(keccak256(abi.encodePacked(
bytes1(0xff), LibRainDeploy.ZOLTU_FACTORY, bytes32(0),
keccak256(type(MockDeployable).creationCode)
))))),
0xC24016f209562fc151e5Ab7F88694ED5775feb36
);
}
This is not pedantic: under the stated CREATE-with-nonce model the address
depends on the factory's per-chain nonce, so cross-chain address equality would
require replicating deploy order on every chain. Under the actual
CREATE2-salt-0 model the address is a pure function of the creation code and
order is irrelevant. Anyone reasoning from the documented model will reason
wrongly.
The same claim appears in a test comment in
test/src/lib/LibRainDeploy.t.sol:
deployZoltu MUST deploy a contract via the Zoltu factory and return the deterministic address predicted by the factory's nonce.
3. findDeployBlock NatSpec claims a validation the code does not perform
/// ... The fork is restored to its original block
/// number before returning. The target's code hash is verified against the
/// expected value before searching. The result is validated via
/// `isStartBlock`.
findDeployBlock never calls isStartBlock. The binary search result is
returned unvalidated. (The test does the isStartBlock round-trip, which is
probably where the sentence came from.)
Either drop the sentence or make the code do it.
4. isStartBlock / findDeployBlock do not document their monotonicity requirement
The binary search is only correct if the target's code hash, once equal to
expectedCodeHash, stays equal for every subsequent block. An address that
held different code earlier (e.g. a pre-Cancun SELFDESTRUCT + CREATE2
redeploy at the same address) breaks that assumption and the search can return
a meaningless block. Since the returned block is typically used as a subgraph
start block, the assumption is worth stating in the NatSpec.
5. CLAUDE.md omits Base Sepolia in two places
- The overview lists the supported networks as "(Arbitrum, Base, Flare,
Polygon)". supportedNetworks() returns five, including base_sepolia.
- The sample
.env block lists ARBITRUM_RPC_URL, BASE_RPC_URL,
FLARE_RPC_URL, POLYGON_RPC_URL but not BASE_SEPOLIA_RPC_URL, which
foundry.toml requires under [rpc_endpoints]. Following the documented
setup gives a .env that cannot resolve one of the library's own supported
networks.
Summary
Several pieces of documentation in this repo describe behaviour the code does
not have. All verified against
4422e29(v0.1.4). Grouped here because theyare one class of defect with one fix.
1.
CLAUDE.mddocuments a function that no longer existsCLAUDE.mdstill lists:and:
checkDependencieswas folded intodeployToNetworksin503002e("refactor(deploy): fold the dependency check into deployToNetworks"). There is
no such function in
src/lib/LibRainDeploy.sol. The same section describesdeployToNetworksas "**re-**verifies dependencies", which is likewise aleftover from the two-pass design.
Related, the "Key Design Patterns" section says:
Dependencies are now checked per network, and only on the deploy branch — an
already-deployed network skips the check entirely (deliberately; see the
deployToNetworksNatSpec).2.
CLAUDE.mddescribes the wrong deployment opcodeThe factory uses CREATE2 with a zero salt, not CREATE. Disassembling
ZOLTU_FACTORY_BYTECODE:Confirmed empirically — the following passes:
This is not pedantic: under the stated CREATE-with-nonce model the address
depends on the factory's per-chain nonce, so cross-chain address equality would
require replicating deploy order on every chain. Under the actual
CREATE2-salt-0 model the address is a pure function of the creation code and
order is irrelevant. Anyone reasoning from the documented model will reason
wrongly.
The same claim appears in a test comment in
test/src/lib/LibRainDeploy.t.sol:3.
findDeployBlockNatSpec claims a validation the code does not performfindDeployBlocknever callsisStartBlock. The binary search result isreturned unvalidated. (The test does the
isStartBlockround-trip, which isprobably where the sentence came from.)
Either drop the sentence or make the code do it.
4.
isStartBlock/findDeployBlockdo not document their monotonicity requirementThe binary search is only correct if the target's code hash, once equal to
expectedCodeHash, stays equal for every subsequent block. An address thatheld different code earlier (e.g. a pre-Cancun
SELFDESTRUCT+ CREATE2redeploy at the same address) breaks that assumption and the search can return
a meaningless block. Since the returned block is typically used as a subgraph
start block, the assumption is worth stating in the NatSpec.
5.
CLAUDE.mdomits Base Sepolia in two placesPolygon)".
supportedNetworks()returns five, includingbase_sepolia..envblock listsARBITRUM_RPC_URL,BASE_RPC_URL,FLARE_RPC_URL,POLYGON_RPC_URLbut notBASE_SEPOLIA_RPC_URL, whichfoundry.tomlrequires under[rpc_endpoints]. Following the documentedsetup gives a
.envthat cannot resolve one of the library's own supportednetworks.