fix(deploy): check dependencies and deploy on one fork per network#13
Conversation
deployAndBroadcast ran two phases that each forked every network: checkDependencies forked each network to validate the Zoltu factory and dependencies, then deployToNetworks forked each network again at a newer head, re-read the same dependencies, and broadcast the deploy. That second fork's re-read on a newer snapshot let a transient RPC inconsistency report an already-deployed dependency as having no code, falsely reverting MissingDependency and aborting a valid deploy. checkDependencies now returns the fork it created and selected for each network, and deployToNetworks reuses that fork via vm.selectFork and deploys. Validating once on the fork the deploy runs on removes the redundant second read, so there is no longer a divergent snapshot for a transient glitch to surface on. The deploy-time re-check and the dependency codehash record/compare machinery (meaningful only across two forks) are removed, and deployAndBroadcast no longer needs the depCodeHashes mapping parameter. Adds a fork-reuse regression test and a two-network per-index fork-selection test; removes the tests that exercised the deleted deploy-time re-check and codehash recording. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 3 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
Walkthrough
ChangesDeployment flow simplification
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The single-contract static check (rainix-sol-single-contract) requires one contract per .sol file. Move MockDeployable and MockReverter out of LibRainDeploy.t.sol into their own files and import them. bytecode_hash is "none", so the mocks' creation code — and the deterministic Zoltu addresses the tests assert — are unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
deployAndBroadcast ran a separate checkDependencies pass over every network before deployToNetworks deployed to any of them. With the fork-reuse fix that pre-flight had become a second function that protected nothing: the Zoltu deploy is idempotent (an already-deployed contract is skipped) and each network is independent, so a failure on one network leaves the others intact and the script can simply be re-run. There is nothing for an all-network pre-flight to guard. deployToNetworks now forks each network once, verifies the Zoltu factory and every dependency have code on that fork, then broadcasts the deploy — all on a single fork per network, so each dependency is read exactly once. This removes the redundant second fork (the original transient-glitch bug) at the root and drops checkDependencies, the forkIds plumbing, and the two-pass structure entirely. The per-network dependency check still runs before that network's deploy, so nothing deploys onto a network missing a prerequisite. deployToNetworks regains the dependencies parameter and loses forkIds; deployAndBroadcast is otherwise unchanged. The dependency and Zoltu-factory checks now run through deployToNetworks (the persistent-etch test pattern survives its internal createSelectFork) and are mutation-validated; the fork-reuse and checkDependencies tests are removed and a two-network deploy test is added. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
test/src/lib/LibRainDeploy.t.sol (1)
356-380: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winAdd a regression where skip wins over missing dependencies.
This skip-path test still uses an empty
dependenciesarray, so it will not catch the ordering bug above. Make one dependency undeployed here and keep asserting success onceexpectedAddressalready has code.Minimal test tweak
- address[] memory dependencies = new address[](0); + address[] memory dependencies = new address[](1); + dependencies[0] = address(0xdead);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/src/lib/LibRainDeploy.t.sol` around lines 356 - 380, The regression test in testDeployToNetworksSkipsWhenAlreadyDeployed still uses an empty dependencies array, so it does not exercise the skip-over-missing-dependencies path. Update this test to include at least one undeployed dependency in the dependencies list while keeping the predeployed expectedAddress setup and the assert that externalDeployToNetworks returns the existing address. Use the existing test helpers and identifiers like externalDeployToNetworks, externalDeployZoltu, and MockDeployable to keep the scenario focused on the skip logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/lib/LibRainDeploy.sol`:
- Around line 221-240: The deployment loop in LibRainDeploy currently validates
ZOLTU_FACTORY and other dependencies before checking whether a network is
already deployed, so idempotent reruns can still revert on MissingDependency or
DependencyChanged. Move the already-deployed skip logic to the start of the
per-network loop in the deployment routine that iterates over networks, before
any dependency validation or logging that assumes deployment is needed. Make
sure the skip path using expectedAddress runs first so previously deployed
networks are bypassed entirely.
---
Outside diff comments:
In `@test/src/lib/LibRainDeploy.t.sol`:
- Around line 356-380: The regression test in
testDeployToNetworksSkipsWhenAlreadyDeployed still uses an empty dependencies
array, so it does not exercise the skip-over-missing-dependencies path. Update
this test to include at least one undeployed dependency in the dependencies list
while keeping the predeployed expectedAddress setup and the assert that
externalDeployToNetworks returns the existing address. Use the existing test
helpers and identifiers like externalDeployToNetworks, externalDeployZoltu, and
MockDeployable to keep the scenario focused on the skip logic.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: a36bf56e-a7f9-4d4c-bb95-8a84fa2a840c
📒 Files selected for processing (4)
src/lib/LibRainDeploy.soltest/src/lib/LibRainDeploy.t.soltest/src/lib/MockDeployable.soltest/src/lib/MockReverter.sol
The merged deployToNetworks discarded the fork id returned by vm.createSelectFork, which slither flags as an unused return. Bind and reference it, matching the idiom used elsewhere for this call. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
deployToNetworks validated the Zoltu factory and dependencies before the already-deployed skip path, so a network that no longer needs deploying could still revert MissingDependency / DependencyChanged on a rerun, re-introducing the transient-read failure this change exists to remove for the no-op case. Reorder so the expectedAddress-has-code skip is taken first; dependencies are only validated on the deploy path. The deployed contract codehash is still verified on both paths. Adds testDeployToNetworksSkipsAlreadyDeployedWithMissingDependency, which deploys the target then reruns with a missing dependency and asserts the network is skipped without reverting (fails on the old order). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Reviewed 9156d28 Final merged-design fork-reuse fix: |
Summary
deployAndBroadcastvalidated dependencies and deployed in two passes that each forked every network —checkDependencies(fork, validate) thendeployToNetworks(fork again at a newer head, re-read, deploy). That redundant second read on a fresh fork let a rare transient RPC inconsistency report an already-deployed dependency as having no code, falsely revertingMissingDependencyand aborting an otherwise-valid deploy.This folds the two passes into one:
deployToNetworksforks each network once, verifies the Zoltu factory and every dependency have code on that fork, then broadcasts the deploy — so each dependency is read exactly once and the second fork is gone.The separate all-network pre-flight isn't needed, because the Zoltu deploy is idempotent: an already-deployed contract is skipped, each network is independent, and a failure on one network leaves the others intact and is safely re-runnable. The per-network dependency check still runs before that network's deploy, so nothing deploys onto a network that is missing a prerequisite.
Changes
checkDependencies.deployToNetworks(vm, networks, deployer, creationCode, contractPath, expectedAddress, expectedCodeHash, dependencies)now forks each network, checks the Zoltu factory + dependencies inline, then deploys.deployAndBroadcastjust callsdeployToNetworks— noforkIds, nodepCodeHashes.deployToNetworksand are mutation-validated (disabling each check fails its test, restoring it passes); added a two-network deploy test; removed the fork-reuse andcheckDependenciestests; the two mocks live in their own files for the one-contract-per-file static check.This is an audited library and the change is structural — please re-review.
deployAndBroadcast's signature changed vs the released v0.1.3: thedepCodeHashesstorage-mapping parameter is gone (the codehash record/compare machinery only had meaning across two forks). Consumers must drop that argument — e.g.st0x.deploy'sDeploy.sol, which I'll update on the dependency bump.Testing
forge build+forge testgreen for the deploy/dependency suite (17 tests). The three inline checks are mutation-validated (each one disabled → its test fails; restored → all pass), andtestDeployZoltustill pins the deterministic0xC24016…address. The archive-historyfindDeployBlock/isStartBlocktests are untouched and run under CI's archive RPC.🤖 Generated with Claude Code
Summary by CodeRabbit