Verifying 1.4 contract upgrade

Hi All,

As I’ve done other times, I wanted to take a look and publish it for folks that aren’t gonna dig in themselves, or folks that want to follow along.

I used the team’s verification tool, after a quick skim into its functionality. Happy checkmarks across the board. I then made specific changes to source to confirm that those specific changes were found by the tool. Note: by default, the env example uses Hoodi network/rocketstorage so set those to mainnet/0x1d8f8f00cfa6758d7bE78336684788Fb0ee0Fa46 and make sure your RPC endpoint matches your chosen chain.

The 3 audits were Cantina (56ea8976a5ccafb553b0eb613bd62fd19a8d5aa8), Bailsec (02621fa4f88af44b7e0475840b222b9aaba4a6dd), Sigma Prime (the specific range from Comparing 6f07f2a..269782f · rocket-pool/rocketpool · GitHub, which starts from the last Sigma prime audit for Houston hotfix).

Post-audit drift, the phantom menace

The tagged v1.4 is fb7d9c428dc3dddc3fbd3e634e3cb365655df89e. The commit used by the verification tool is 5049193cb94c6e153c3ea5784fc670b95b828bf2. The commits from the audits don’t

Let’s take a stab at where these all fit.

Ok… looking further, the final sigma prime audit was on a commit from 7/11/2025 (the first was from 9/9/2024). The Cantina commit was from 7/23/2025. The Bailsec commit was from 7/31/2025. It’s far outside my bandwidth to look at this much.

Follow-up rounds, a new hope

Bailsec then had follow-up resolutions :tada:. The first was on 11/11/2025 and noted explicitly that there were many changes it did not cover. The second was from 12/16/2025 and covered those things. The third was from 1/16/2026, though it explicitly excludes 2 contracts.

That makes it somewhat tractable to get eyes on “from the last thing auditors saw to the thing in the verification tool”.

  • Step 1: look at Bailsec’s resolution3 commit vs the commit from the verification tool (skip RocketDAOProtocolSettingsProposals and RocketUpgradeOneDotFour)
  • Step 2: for RocketDAOProtocolSettingsProposals and RocketUpgradeOneDotFour, look at Bailsec’s resolution2 commit vs the commit from the verification tool

I will note that Bailsec did recommend more work. I’ll copy their note here and leave judgement to the reader:

Bailsec has conducted a follow-up audit based on the changes which are highlighted in the “Resolution 2/Follow-Up” column. The specified commit was considered as finalized by other audit providers and thus a high confidence of deployment-correctness was expected.

However, during our follow-up review we found multiple new issues which allowed for stealing of funds and DoS of the protocol which decreases the confidence in a vulnerability-free code, even after these have been fixed. This comes naturally due to code complexity and exponentiality of state transitions in the Megapool architecture.

While we have applied all our resources to this task, we can not say with high-confidence that there are no critical issues left. We recommend another full protocol audit by a third-party before deployment and a robust bug bounty program.

We highly recommend keeping the post-audit changes to a minimum and only fixing issues
which are of a high severity. It must be highlighted that any potential change (even if
minimal) can and will introduce new edge-cases.

Step 1

I’m not gonna mention comments and whitespace. I also won’t mention javascript semicolons or trailing commas in a list as these are usually nonfunctional differences.

  • RPIP-75 variable changes for number of express tickets
  • A bypass to guardrails around minipool-staked RPL unstaking, for use when slashing RPL
  • Deploy
    • Tweak to ensure contracts are finished deploying in the deploy script before tyring to verify them
    • :question: Added storageHelper. Storage helper is not used in production, rather it’s used to help perform manual edits to storage. I’m unclear on why no uses of it got flagged in delta.. is it cuz it’s replacing other functions with the same name like setUint? If so, why are we bothering?
  • Test
    • Updated numbers for RPIP-75
    • New tests around RPL slashing
    • Disable new minipools to make context match better
    • Update to etherscan api version and related
    • Added storageHelper.
    • Mocking for express tickets

Step 2

RocketDAOProtocolSettingsProposals.sol

  • version increment
  • quorum changes matching RPIP-64 (and guardrail change to support that)

RocketUpgradeOneDotFour.sol

  • add one more slot for contracts, which is used for RocketDAOProtocolSettingsProposals.sol
  • update express queue parameters per RPIP-75
  • delete removed parameters for min/max minipool stake
  • enable new node deposits (new validators) as part of upgrade execution
  • set quorum changes per RPIP-64 (I’m unclear on if both this and the change in RocketDAOProtocolSettingsProposals.sol is needed? might be this one is the active one and the other is informative so the starting value is accurate)

Conclusion

We were able to get a full chain from a latest auditor look to the deployment tag and the verified source on etherscan. There is more uncertainty than we’ve had historically, per Bailsec for the work from 7/31 to 1/16 (see their note). There is also a bit more ground covered between the last auditor touchpoint on 1/16 and the latest – this mostly looks good to me (I’m no auditor ofc), with the note that I’m not grokking the storageHelper and am asking Kane to help explain that.

8 Likes

Hijacking this for a random thing I discovered in Cantina’s report:

In chapter 3.2.1 they advise against hardcoding 12 second block times since EIP-7782 might change this. They mention that this has been fixed in commit 85a1c01c but that commit is “Replace all integer casts with SafeCast” and does not change hardcoded block times.

I have found the needed commit to be fadbcd8. So it is implemented, but an audit that has wrong references to fixes is suboptimal. If I didn’t know Rocket Pool, looked into the audit and saw this “fake” audit correction commit I would assume the audit and the protocol to be a scam.

Thank you for the comprehensive review.

We kept these to an absolute minimum with only variable tweaks being included, except this one:

  • A bypass to guardrails around minipool-staked RPL unstaking, for use when slashing RPL

Although this item was reviewed by Sigma Prime in their fix check process last week.

1 Like

Thank you for pointing that out - we will work with Cantina to update it.

1 Like

Thanks for pointing this out. Actually, this was brought up in my final comments to Cantina to fix in the report review process but it seems like we mistakenly uploaded the report 1 version behind this being fixed.

We’ve replaced the report on our website with this final version which features this correction plus a few other mostly insignificant corrections.

For transparency, the changes in this final report version from the previously published version are:

3.2.1 - Include all commits related to the fix
3.3.2 - Remove my comment which contained a typo :sweat_smile:
3.3.4 - Reduce severity from Medium (Now renumbered as 3.4.1)

3 Likes