Skip to content

OSU-1514: introduce contract semver checks#394

Open
0xferit wants to merge 16 commits intodevelopfrom
feature/osu-1514-add-date-based-version-tagging-ddmmyy-to-contracts-with-ci
Open

OSU-1514: introduce contract semver checks#394
0xferit wants to merge 16 commits intodevelopfrom
feature/osu-1514-add-date-based-version-tagging-ddmmyy-to-contracts-with-ci

Conversation

@0xferit
Copy link
Contributor

@0xferit 0xferit commented Feb 27, 2026

Automates contract semver checks: analysis now targets only contracts that declare API_VERSION, and CI uses safe.directory for merge-base to avoid dubious-ownership failures.

@0xferit 0xferit requested a review from a team as a code owner February 27, 2026 14:09
@linear
Copy link

linear bot commented Feb 27, 2026

@0xferit 0xferit force-pushed the feature/osu-1514-add-date-based-version-tagging-ddmmyy-to-contracts-with-ci branch from 3dd4d90 to e34b3f4 Compare February 27, 2026 14:10
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3dd4d9036e

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@github-actions
Copy link

github-actions bot commented Feb 27, 2026

Code Coverage Report for src/ files

File % Lines % Statements % Branches % Funcs
src/core/BaseStrategy.sol ✅ 100.00% (54/54) ✅ 100.00% (39/39) ✅ 100.00% (2/2) ✅ 100.00% (19/19)
src/core/MultistrategyLockedVault.sol ✅ 100.00% (117/117) ✅ 100.00% (121/121) ✅ 100.00% (22/22) ✅ 100.00% (18/18)
src/core/MultistrategyVault.sol ✅ 100.00% (593/593) ✅ 100.00% (617/617) ✅ 98.49% (196/199) ✅ 100.00% (88/88)
src/core/PaymentSplitter.sol ✅ 100.00% (55/55) ✅ 100.00% (52/52) ✅ 100.00% (18/18) ✅ 100.00% (16/16)
src/core/Privileged.sol ✅ 100.00% (13/13) ✅ 100.00% (12/12) ✅ 100.00% (0/0) ✅ 100.00% (4/4)
src/core/TokenizedStrategy.sol ✅ 99.35% (308/310) ✅ 99.64% (275/276) ✅ 95.60% (87/91) ✅ 98.81% (83/84)
src/core/libs/DebtManagementLib.sol ✅ 100.00% (76/76) ✅ 100.00% (80/80) ✅ 100.00% (20/20) ✅ 100.00% (2/2)
src/core/libs/ERC20SafeApproveLib.sol ✅ 100.00% (4/4) ✅ 100.00% (5/5) ✅ 100.00% (1/1) ✅ 100.00% (1/1)
src/factories/AaveV3StrategyFactory.sol ✅ 100.00% (13/13) ✅ 100.00% (19/19) ✅ 100.00% (2/2) ✅ 100.00% (2/2)
src/factories/AddressSetFactory.sol ✅ 100.00% (15/15) ✅ 100.00% (15/15) ✅ 100.00% (0/0) ✅ 100.00% (4/4)
src/factories/BaseERC4626StrategyFactory.sol ✅ 100.00% (15/15) ✅ 100.00% (19/19) ✅ 100.00% (0/0) ✅ 100.00% (3/3)
src/factories/BaseStrategyFactory.sol ✅ 100.00% (14/14) ✅ 100.00% (14/14) ✅ 100.00% (1/1) ✅ 100.00% (4/4)
src/factories/ERC4626StrategyFactory.sol ✅ 100.00% (2/2) ✅ 100.00% (1/1) ✅ 100.00% (0/0) ✅ 100.00% (1/1)
src/factories/LidoStrategyFactory.sol ✅ 100.00% (12/12) ✅ 100.00% (17/17) ✅ 100.00% (2/2) ✅ 100.00% (2/2)
src/factories/MorphoCompounderStrategyFactory.sol ✅ 100.00% (13/13) ✅ 100.00% (19/19) ✅ 100.00% (2/2) ✅ 100.00% (2/2)
src/factories/MultistrategyVaultFactory.sol ✅ 100.00% (74/74) ✅ 100.00% (64/64) ✅ 100.00% (31/31) ✅ 100.00% (18/18)
src/factories/PaymentSplitterFactory.sol ✅ 100.00% (58/58) ✅ 100.00% (69/69) ✅ 100.00% (22/22) ✅ 100.00% (10/10)
src/factories/RegenEarningPowerCalculatorFactory.sol ✅ 100.00% (14/14) ✅ 100.00% (14/14) ✅ 100.00% (0/0) ✅ 100.00% (4/4)
src/factories/RegenStakerFactory.sol ✅ 100.00% (32/32) ✅ 100.00% (29/29) ✅ 100.00% (2/2) ✅ 100.00% (10/10)
src/factories/SkyCompounderStrategyFactory.sol ✅ 100.00% (12/12) ✅ 100.00% (17/17) ✅ 100.00% (2/2) ✅ 100.00% (2/2)
src/factories/SparkStrategyFactory.sol ✅ 100.00% (2/2) ✅ 100.00% (1/1) ✅ 100.00% (0/0) ✅ 100.00% (1/1)
src/factories/yieldDonating/YearnV3StrategyFactory.sol ✅ 100.00% (12/12) ✅ 100.00% (16/16) ✅ 100.00% (0/0) ✅ 100.00% (2/2)
src/factories/yieldSkimming/RocketPoolStrategyFactory.sol ✅ 100.00% (12/12) ✅ 100.00% (17/17) ✅ 100.00% (2/2) ✅ 100.00% (2/2)
src/guards/KeeperBotGuard.sol ✅ 100.00% (32/32) ✅ 100.00% (30/30) ✅ 100.00% (8/8) ✅ 100.00% (6/6)
src/mechanisms/AllocationMechanismFactory.sol ✅ 100.00% (50/50) ✅ 100.00% (53/53) ✅ 100.00% (4/4) ✅ 100.00% (10/10)
src/mechanisms/BaseAllocationMechanism.sol ✅ 97.01% (65/67) ✅ 97.18% (69/71) ✅ 100.00% (7/7) ✅ 95.83% (23/24)
src/mechanisms/TokenizedAllocationMechanism.sol ✅ 99.76% (422/423) ✅ 99.57% (466/468) ✅ 95.38% (124/130) ✅ 100.00% (81/81)
src/mechanisms/mechanism/OctantQFMechanism.sol ✅ 100.00% (37/37) ✅ 100.00% (37/37) ✅ 100.00% (14/14) ✅ 100.00% (7/7)
src/mechanisms/mechanism/QuadraticVotingMechanism.sol ✅ 100.00% (69/69) ✅ 100.00% (87/87) ✅ 100.00% (17/17) ✅ 100.00% (17/17)
src/mechanisms/voting-strategy/ProperQF.sol ✅ 100.00% (85/85) ✅ 100.00% (104/104) ✅ 100.00% (13/13) ✅ 100.00% (15/15)
src/regen/RegenEarningPowerCalculator.sol ✅ 100.00% (35/35) ✅ 100.00% (31/31) ✅ 100.00% (6/6) ✅ 100.00% (8/8)
src/regen/RegenStaker.sol ✅ 100.00% (16/16) ✅ 100.00% (14/14) ✅ 100.00% (1/1) ✅ 100.00% (5/5)
src/regen/RegenStakerBase.sol ✅ 99.59% (241/242) ✅ 99.59% (242/243) ✅ 97.33% (73/75) ✅ 100.00% (34/34)
src/regen/RegenStakerWithoutDelegateSurrogateVotes.sol ✅ 100.00% (20/20) ✅ 100.00% (17/17) ✅ 100.00% (4/4) ✅ 100.00% (5/5)
src/strategies/periphery/BaseHealthCheck.sol ✅ 100.00% (32/32) ✅ 100.00% (24/24) ✅ 100.00% (14/14) ✅ 100.00% (9/9)
src/strategies/periphery/BaseYieldSkimmingHealthCheck.sol ✅ 100.00% (41/41) ✅ 100.00% (39/39) ✅ 100.00% (18/18) ✅ 100.00% (10/10)
src/strategies/periphery/UniswapV3Swapper.sol ✅ 100.00% (23/23) ✅ 100.00% (30/30) ✅ 100.00% (7/7) ✅ 100.00% (4/4)
src/strategies/yieldDonating/AaveV3Strategy.sol ✅ 100.00% (39/39) ✅ 100.00% (48/48) ✅ 100.00% (9/9) ✅ 100.00% (7/7)
src/strategies/yieldDonating/ERC4626Strategy.sol ✅ 100.00% (26/26) ✅ 100.00% (30/30) ✅ 100.00% (2/2) ✅ 100.00% (7/7)
src/strategies/yieldDonating/MorphoCompounderStrategy.sol ✅ 100.00% (26/26) ✅ 100.00% (30/30) ✅ 100.00% (2/2) ✅ 100.00% (7/7)
src/strategies/yieldDonating/PrivilegedYieldDonatingTokenizedStrategy.sol ✅ 100.00% (16/16) ✅ 100.00% (14/14) ✅ 100.00% (4/4) ✅ 100.00% (6/6)
src/strategies/yieldDonating/SkyCompounderStrategy.sol ✅ 100.00% (88/88) ✅ 100.00% (77/77) ✅ 100.00% (24/24) ✅ 100.00% (19/19)
src/strategies/yieldDonating/SparkStrategy.sol ✅ 100.00% (8/8) ✅ 100.00% (9/9) ✅ 100.00% (6/6) ✅ 100.00% (1/1)
src/strategies/yieldDonating/YearnV3Strategy.sol ✅ 100.00% (26/26) ✅ 100.00% (30/30) ✅ 100.00% (2/2) ✅ 100.00% (7/7)
src/strategies/yieldDonating/YieldDonatingTokenizedStrategy.sol ✅ 100.00% (23/23) ✅ 100.00% (26/26) ✅ 100.00% (5/5) ✅ 100.00% (2/2)
src/strategies/yieldSkimming/BaseYieldSkimmingStrategy.sol ✅ 100.00% (8/8) ✅ 100.00% (5/5) ✅ 100.00% (0/0) ✅ 100.00% (5/5)
src/strategies/yieldSkimming/LidoStrategy.sol ✅ 100.00% (4/4) ✅ 100.00% (3/3) ✅ 100.00% (0/0) ✅ 100.00% (2/2)
src/strategies/yieldSkimming/PrivilegedYieldSkimmingTokenizedStrategy.sol ✅ 100.00% (16/16) ✅ 100.00% (14/14) ✅ 100.00% (4/4) ✅ 100.00% (6/6)
src/strategies/yieldSkimming/RocketPoolStrategy.sol ✅ 100.00% (4/4) ✅ 100.00% (3/3) ✅ 100.00% (0/0) ✅ 100.00% (2/2)
src/strategies/yieldSkimming/YieldSkimmingTokenizedStrategy.sol ✅ 99.61% (254/255) ✅ 99.39% (326/328) ✅ 96.43% (81/84) ✅ 100.00% (28/28)
src/utils/AddressSet.sol ✅ 100.00% (34/34) ✅ 100.00% (34/34) ✅ 100.00% (12/12) ✅ 100.00% (7/7)
src/zodiac-core/LinearAllowanceExecutor.sol ✅ 100.00% (24/24) ✅ 100.00% (24/24) ✅ 100.00% (7/7) ✅ 100.00% (7/7)
src/zodiac-core/modules/LinearAllowanceSingletonForGnosisSafe.sol ✅ 100.00% (91/91) ✅ 100.00% (100/100) ✅ 95.24% (20/21) ✅ 100.00% (16/16)

@0xferit 0xferit force-pushed the feature/osu-1514-add-date-based-version-tagging-ddmmyy-to-contracts-with-ci branch from b07cc94 to ee7ec9b Compare February 27, 2026 14:15
@0xferit 0xferit force-pushed the feature/osu-1514-add-date-based-version-tagging-ddmmyy-to-contracts-with-ci branch from ee7ec9b to b135ee5 Compare February 27, 2026 14:19
@0xferit
Copy link
Contributor Author

0xferit commented Feb 27, 2026

@copilot review

@0xferit 0xferit marked this pull request as draft February 27, 2026 15:45
@0xferit
Copy link
Contributor Author

0xferit commented Mar 2, 2026

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e37564491e

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@0xferit
Copy link
Contributor Author

0xferit commented Mar 2, 2026

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2a1b170352

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@0xferit
Copy link
Contributor Author

0xferit commented Mar 2, 2026

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e68d9ad86b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@0xferit
Copy link
Contributor Author

0xferit commented Mar 2, 2026

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1b5e7c0588

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@0xferit
Copy link
Contributor Author

0xferit commented Mar 2, 2026

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a5698da10b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".


function extractContractNames(sourceCode) {
const names = [];
const regex = /\b(?:abstract\s+)?contract\s+([A-Za-z_][A-Za-z0-9_]*)\b/g;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ignore comments while extracting contract declarations

This regex scans raw source text and matches comment phrases like contract address or contract for, producing fake names that are then passed to forge inspect in findInspectableContractsInSource; each false candidate spawns extra inspect subprocesses and can significantly inflate check time on heavily documented contracts. Parsing declarations without comments (or using a Solidity-aware parser) avoids this CI performance regression.

Useful? React with 👍 / 👎.

@0xferit
Copy link
Contributor Author

0xferit commented Mar 2, 2026

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a13521155a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +659 to +661
if (oldPath.endsWith(".sol") && newPath.endsWith(".sol")) {
changedFiles.add(newPath);
renamedNewToOld[newPath] = oldPath;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Record old renamed Solidity paths for discovery

When a Solidity file is renamed (R status), this branch only adds newPath to changedFiles, so later discovery never scans the old path. In the common refactor case where a file rename also renames the contract symbol, the old contract ID is never analyzed as removed, and analyzeContract can misclassify the change as a newly added contract instead of a breaking removal/rename. That underestimates required version bumps and can let incompatible changes pass the semver gate.

Useful? React with 👍 / 👎.

@0xferit 0xferit marked this pull request as ready for review March 4, 2026 11:41
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a13521155a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +839 to +842
if (/\bAPI_VERSION\b\s*=\s*"(\d+\.\d+\.\d+)"/.test(source)) {
hasVersion = true;
}
inspectable.push(...findInspectableContractsInSource(worktreeDir, sourcePath, source));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restrict API_VERSION enforcement to versioned contracts

This discovery path treats a file as versioned when any API_VERSION constant is present, but then adds every inspectable contract from that file to analysis. In a multi-contract file where only one contract is versioned, helper contracts without API_VERSION will still be checked and then fail under-bump with missing declared API_VERSION, which blocks valid PRs that only touch those helpers. Discovery should only enqueue contracts whose own declaration contains API_VERSION.

Useful? React with 👍 / 👎.

@0xferit 0xferit requested review from qGolem and skimaharvey March 4, 2026 11:58
Copy link
Contributor

@skimaharvey skimaharvey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving — this is a solid foundation for enforcing semver discipline on versioned contracts. A few points worth considering:

1. CI cost — two full forge build per run
The check creates two git worktrees and runs forge soldeer install + forge clean + forge build --skip test --skip script in each. On a growing codebase that's going to get expensive fast. Worth keeping an eye on wall-clock time once this lands on real PRs, and considering build artifact caching or only building the contracts in scope down the road.

2. Lock file machinery is wired up but never invoked
~100 lines of lock file validation (lock-entry-present, lock-format-valid, lock-not-downgraded, lock-vs-declared, lock-updated) are implemented but the CI workflow never passes --lock-file, so none of it runs. If this is intentional prep for a future phase, a comment or TODO explaining that would help — otherwise it reads as dead code.

3. Failure output is raw JSON
When the check fails, developers get a JSON blob in the CI logs. Writing a human-readable summary to $GITHUB_STEP_SUMMARY (even just the failures array formatted as a markdown table) would make version-bump violations much faster to act on without having to dig through structured output.

4. Bytecode-only diffs require a patch bump
After metadata stripping, any bytecode change (gas optimizations, internal refactors, compiler upgrades) forces a patch bump to API_VERSION. This is strict — these changes have zero impact on integrators. Might lead to version inflation or developers reflexively over-bumping. Worth a deliberate call on whether patch-level bytecode diffs should be advisory rather than enforced.

5. Storage comparison blind spot on mappings/dynamic arrays
forge inspect <contract> storage only reports fixed-layout variables. Mappings and dynamic arrays use hashed slots and don't appear in the layout output. So a change like mapping(address => uint) to mapping(bytes32 => uint) (breaking for storage integrity behind a proxy) would be invisible to the storage layer check. Not something the script can easily fix — it's a Forge limitation — but worth documenting as a known gap so reviewers know storage checks aren't exhaustive.

6. compareStorage early-returns on first issue
The function returns on the first breaking change it finds. If a contract has multiple storage problems, developers only see one per CI cycle, leading to a fix-one-rerun-fix-another loop. Collecting all issues before returning would save round-trips.

@0xferit
Copy link
Contributor Author

0xferit commented Mar 6, 2026

Approving — this is a solid foundation for enforcing semver discipline on versioned contracts. A few points worth considering:

1. CI cost — two full forge build per run The check creates two git worktrees and runs forge soldeer install + forge clean + forge build --skip test --skip script in each. On a growing codebase that's going to get expensive fast. Worth keeping an eye on wall-clock time once this lands on real PRs, and considering build artifact caching or only building the contracts in scope down the road.

2. Lock file machinery is wired up but never invoked ~100 lines of lock file validation (lock-entry-present, lock-format-valid, lock-not-downgraded, lock-vs-declared, lock-updated) are implemented but the CI workflow never passes --lock-file, so none of it runs. If this is intentional prep for a future phase, a comment or TODO explaining that would help — otherwise it reads as dead code.

3. Failure output is raw JSON When the check fails, developers get a JSON blob in the CI logs. Writing a human-readable summary to $GITHUB_STEP_SUMMARY (even just the failures array formatted as a markdown table) would make version-bump violations much faster to act on without having to dig through structured output.

4. Bytecode-only diffs require a patch bump After metadata stripping, any bytecode change (gas optimizations, internal refactors, compiler upgrades) forces a patch bump to API_VERSION. This is strict — these changes have zero impact on integrators. Might lead to version inflation or developers reflexively over-bumping. Worth a deliberate call on whether patch-level bytecode diffs should be advisory rather than enforced.

5. Storage comparison blind spot on mappings/dynamic arrays forge inspect <contract> storage only reports fixed-layout variables. Mappings and dynamic arrays use hashed slots and don't appear in the layout output. So a change like mapping(address => uint) to mapping(bytes32 => uint) (breaking for storage integrity behind a proxy) would be invisible to the storage layer check. Not something the script can easily fix — it's a Forge limitation — but worth documenting as a known gap so reviewers know storage checks aren't exhaustive.

6. compareStorage early-returns on first issue The function returns on the first breaking change it finds. If a contract has multiple storage problems, developers only see one per CI cycle, leading to a fix-one-rerun-fix-another loop. Collecting all issues before returning would save round-trips.

Approving — this is a solid foundation for enforcing semver discipline on versioned contracts. A few points worth considering:

1. CI cost — two full forge build per run The check creates two git worktrees and runs forge soldeer install + forge clean + forge build --skip test --skip script in each. On a growing codebase that's going to get expensive fast. Worth keeping an eye on wall-clock time once this lands on real PRs, and considering build artifact caching or only building the contracts in scope down the road.

2. Lock file machinery is wired up but never invoked ~100 lines of lock file validation (lock-entry-present, lock-format-valid, lock-not-downgraded, lock-vs-declared, lock-updated) are implemented but the CI workflow never passes --lock-file, so none of it runs. If this is intentional prep for a future phase, a comment or TODO explaining that would help — otherwise it reads as dead code.

3. Failure output is raw JSON When the check fails, developers get a JSON blob in the CI logs. Writing a human-readable summary to $GITHUB_STEP_SUMMARY (even just the failures array formatted as a markdown table) would make version-bump violations much faster to act on without having to dig through structured output.

4. Bytecode-only diffs require a patch bump After metadata stripping, any bytecode change (gas optimizations, internal refactors, compiler upgrades) forces a patch bump to API_VERSION. This is strict — these changes have zero impact on integrators. Might lead to version inflation or developers reflexively over-bumping. Worth a deliberate call on whether patch-level bytecode diffs should be advisory rather than enforced.

5. Storage comparison blind spot on mappings/dynamic arrays forge inspect <contract> storage only reports fixed-layout variables. Mappings and dynamic arrays use hashed slots and don't appear in the layout output. So a change like mapping(address => uint) to mapping(bytes32 => uint) (breaking for storage integrity behind a proxy) would be invisible to the storage layer check. Not something the script can easily fix — it's a Forge limitation — but worth documenting as a known gap so reviewers know storage checks aren't exhaustive.

6. compareStorage early-returns on first issue The function returns on the first breaking change it finds. If a contract has multiple storage problems, developers only see one per CI cycle, leading to a fix-one-rerun-fix-another loop. Collecting all issues before returning would save round-trips.

Thanks. Let's harden before merging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants