Skip to content

Docs describe behaviour the code does not have: checkDependencies, CREATE vs CREATE2, findDeployBlock validation, Base Sepolia #18

Description

@thedavidmeister

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

auditAudit finding

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions