Sparrow dom/foundry updates - #2957
Open
sparrowDom wants to merge 5 commits into
Open
Conversation
Three contracts used non-standard gap names (______gap, _____gap, ___gap) that scripts/check-storage-layout.js did not recognise as gaps, so a legitimate gap shrink in them would have been reported as a removed variable. Initializable is inherited widely, so most upgradeable layouts were affected. Renaming is storage-neutral -- verified with forge inspect before/after across OUSD, OETHVault, VaultCore, WOETH, OETHHarvesterSimple and OUSDResolutionUpgrade: slot, offset, type and the types dictionary are identical, only labels change. OZ assertStorageUpgradeSafe does flag a rename, so the committed layout snapshots are relabelled in the same change; without that the next deploy of anything inheriting Initializable would fail the upgrade gate. OUSD keeps its legacy _gap: it declares both _gap and __gap in the same contract, so they cannot share a name.
The package is an optional peer dependency so CI and external contributors can install without GitHub Packages auth, but tasks/lib/network.ts imported it at module scope. That pulled it into hardhat.config.js's load path via tasks.js -> utils/morpho.js -> utils/resolvers.js, so any `npx hardhat` command failed with "Cannot find module" in a fresh checkout -- and the abi.yml release workflow, which installs without auth and then runs `hardhat deploy`, would fail on the next v* tag. Move the import inside rpcUrlFor(), the only place it is used, so importing the module no longer requires the package. Verified: with the package removed, `hardhat --help` still registers every task and `hardhat compile` succeeds; with it present, chain and RPC resolution are unchanged and the action catalog still dumps 43 actions. Add `pnpm install:talos` for the case where it is genuinely needed (running actions, KMS signer). It sources a token from the gh CLI, checks the token can actually read the package -- `gh auth login` does not request read:packages -- installs via a throwaway npm config, then restores package.json and pnpm-lock.yaml so the package is never committed as a dependency, which would break CI.
…t tasks and talos task code can remain unchanged
Replaces the Hardhat-based upgrade gate, which is broken on this branch (cache/validations.json is stale and VaultCore is now abstract). The baseline moves into the deployment descriptor, so it is written by the same step that records the address and the write side cannot silently stop. The check runs inside _recordDeployment, which is mandatory, and takes the contract name as type(X).name so a rename cannot point it at the wrong baseline. A revert there still aborts before broadcast — forge runs the whole script against the fork before submitting — verified against anvil: no transactions, no block mined, ledger untouched. Comparison is @openzeppelin/upgrades-core, which already implements the __gap shrink arithmetic. Two policies are ours: a rename is ignored only when the new label derives from the old (assets -> _deprecated_assets), since two same-typed variables trading labels also reports as two renames; and enum member data, absent from solc layouts, is ignored — an enum is one byte regardless of variant count, so no slot moves. Gap labels are normalised to __gap in memory because OZ's isGap() matches only __gap/__gap_*, while contracts deployed before the rename still carry ______gap on chain. Stored layouts stay faithful to their source. Scope is mainnet and Base. foundry.toml gains extra_output = ["storageLayout"] (extra_output_files alone emitted nothing, which also broke forge inspect). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GueER8JLB5U4MBLEbFERAK
…y trees
Descriptors become the single record of a deployed contract:
{address, abi, storageLayout}. 103 layouts were read from each deployed
implementation's verified source on chain via cast storage (71 mainnet,
32 Base); the remaining 61 came from the legacy Hardhat snapshots, used only
where the chain fetch could not run — contracts compiled with solc 0.5.x that
the current toolchain cannot rebuild, and stateless contracts whose layout is
empty anyway. 16 descriptors get no layout: 12 proxies, which declare no
storage, and 4 deprecated contracts whose source has left the repo.
Layouts are stored faithfully, exactly as their source produced them, so a bug
in the in-memory gap normalisation never costs a re-fetch. Note this means
some baselines legitimately carry ______gap, which is what is deployed.
Deletes storageLayout/ (216 files) — baselines now live in descriptors, and
the name-keyed snapshots had already rotted into fossils for VaultCore and
VaultAdmin, both abstract and undeployable since #2714. Re-supporting a chain
means re-fetching its layouts; see CLAUDE.md.
Deletes deployments/*/solcInputs/ (217 files, ~139 MB) — only hardhat-deploy's
verification path read them, and verification does not run through Hardhat.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GueER8JLB5U4MBLEbFERAK
sparrowDom
requested review from
clement-ux,
naddison36 and
shahthepro
as code owners
August 1, 2026 16:32
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Foundry does the deploying now, but the Talos crons and the Hardhat task CLI still resolve contracts from
deployments/<network>/<Name>.json, and Foundry writes only addresses, tobuild/deployments-<chainId>.json— so a redeploy silently left those descriptors pointing at the previous contract. After each broadcast a script now rewrites them in place, keyed offcontractNamefromrun-latest.json, which turns out to be the descriptor filename verbatim. Nothing downstream changes.The descriptor also becomes the storage-layout baseline, replacing the Hardhat upgrade gate — which is broken on this branch anyway, since
cache/validations.jsonis stale andVaultCoreis now abstract._recordDeploymenttakestype(X).nameand compares the new layout against what is deployed, aborting the run before anything broadcasts. Comparison is@openzeppelin/upgrades-core, which already implements the__gapshrink arithmetic; we add only two policies — a rename passes only when the new label derives from the old (assets→_deprecated_assets), since two same-typed variables trading labels also reports as two renames, and enum members, which solc omits from layouts, are ignored. Baselines were seeded from each deployed implementation's verified source on chain, which letsstorageLayout/and the orphanedsolcInputs/go (~139 MB). The gate commit and the seeding commit have to land together.Also here:
@oplabs/talos-clientis imported lazily sohardhat deployin the ABI publish workflow no longer needs GitHub Packages auth, and storage gaps are unified on__gap.Code Change Checklist
To be completed before internal review begins:
Internal review:
Deploy checklist
Two reviewers complete the following checklist: