Skip to content

feat: Make weETHModule an upgradeable proxy (DEV-1149) - #228

Merged
lucas-manuel merged 11 commits into
devfrom
dev-1149-weethModule-proxy
Jan 29, 2026
Merged

lucas-manuel merged 11 commits into
devfrom
dev-1149-weethModule-proxy

Conversation

@supercontracts

@supercontracts supercontracts commented Jan 29, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

Release Notes

  • New Features

    • WEETHModule now supports upgradeable architecture, enabling future protocol enhancements.
  • Chores

    • Migrated module to proxy-based deployment pattern.
    • Updated module initialization and access control mechanisms.

✏️ Tip: You can customize this high-level summary in your review settings.

@notion-workspace

Copy link
Copy Markdown

@octane-security-app

Copy link
Copy Markdown

Summary by Octane

New Contracts

No new contracts were added.

Updated Contracts

  • WeEthModule.sol: The smart contract now supports upgradeability with UUPSUpgradeable, replacing constructor with initialize, and allows upgrades only by admin.

🔗 Commit Hash: 485c8d5

@coderabbitai

coderabbitai Bot commented Jan 29, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • 🔍 Trigger a full review

Walkthrough

The PR migrates WEETHModule from a non-upgradeable contract to an upgradeable contract using the UUPS proxy pattern. Deployment now wraps WEETHModule in an ERC1967Proxy, replacing the constructor with an initialize function, adding upgrade authorization controls, and including a storage gap for forward compatibility.

Changes

Cohort / File(s) Summary
Proxy Deployment
test/mainnet-fork/weETH.t.sol
Added ERC1967Proxy import and updated deployment to instantiate WEETHModule behind a proxy with initialization via abi.encodeCall(WEETHModule.initialize, (Ethereum.SPARK_PROXY, address(almProxy))).
Upgradeable Contract Migration
src/WEETHModule.sol
Migrated to upgradeable pattern: replaced AccessControlEnumerable with AccessControlEnumerableUpgradeable and UUPSUpgradeable; replaced constructor with no-arg constructor that disables initializers and initialize() function; added _authorizeUpgrade() gated by DEFAULT_ADMIN_ROLE; converted almProxy from immutable to mutable; added storage gap for upgrade safety.

Sequence Diagram

sequenceDiagram
    participant Test as Test Suite
    participant Proxy as ERC1967Proxy
    participant Impl as WEETHModule<br/>(Implementation)
    
    Test->>Proxy: Create proxy with implementation
    Test->>Proxy: Initialize via abi.encodeCall
    Proxy->>Impl: delegatecall initialize(admin, almProxy)
    Impl->>Impl: __AccessControlEnumerable_init()
    Impl->>Impl: __UUPSUpgradeable_init()
    Impl->>Impl: Grant DEFAULT_ADMIN_ROLE
    Impl->>Impl: Store almProxy reference
    Proxy-->>Test: Initialization complete
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • [DEV-1041] : Add weETH integration #215: Directly relates as the main PR that migrates WEETHModule to an upgradeable ERC1967 proxy pattern, modifying the same contract's inheritance, initialization approach, storage layout, and test deployment strategy.

Poem

🐰 A proxy wraps what once stood bare,
Upgradeable code floating in the air,
Authorization gates guard the way,
Storage gaps for tomorrow's day!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: making weETHModule an upgradeable proxy, starts with 'feat:' prefix as required, and includes the JIRA key (DEV-1149).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev-1149-weethModule-proxy

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • DEV-1149: Entity not found: Issue - Could not find referenced Issue.

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@src/WeEthModule.sol`:
- Around line 21-23: The WeEthModule UUPS upgradeable contract is missing the
reserved storage gap which prevents future state variable additions from
corrupting proxy storage; add a private uint256 array named __gap (e.g.,
uint256[50] private __gap) to the WeEthModule contract (which inherits
AccessControlEnumerableUpgradeable and UUPSUpgradeable) right after the existing
state variables like almProxy to reserve space for future upgrades.
- Around line 33-39: In initialize, call parent initializers by invoking
__AccessControlEnumerable_init() and __UUPSUpgradeable_init() before granting
roles, validate admin is not the zero address with require(admin != address(0),
"WeEthModule/invalid-admin"), then call _grantRole(DEFAULT_ADMIN_ROLE, admin)
and set almProxy = _almProxy; ensure __AccessControlEnumerable_init and
__UUPSUpgradeable_init are invoked at the start of the initialize function
(alongside the existing _almProxy zero check) to follow upgradeable-contract
best practices.

In `@test/mainnet-fork/weETH.t.sol`:
- Around line 25-27: Remove the unused interface IWeEthModuleLike from the file:
it is defined but never referenced, since initialization uses
abi.encodeCall(WeEthModule.initialize, ...) and does not require the interface;
delete the IWeEthModuleLike declaration to clean up unused code and leave
WeEthModule.initialize and the abi.encodeCall usage intact.

Comment thread src/WeEthModule.sol Outdated
Comment thread src/WEETHModule.sol Outdated
Comment thread test/mainnet-fork/weETH.t.sol Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jan 29, 2026
@octane-security-app

Copy link
Copy Markdown

Overview

Vulnerabilities found: 2                                                                                
Warnings found: 8                                                                                

🔗 Commit Hash: 485c8d5
🛡️ Octane Dashboard: All vulnerabilities

@lucas-manuel

Copy link
Copy Markdown
Contributor

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jan 29, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jan 29, 2026
Comment thread src/WEETHModule.sol Outdated
address public immutable almProxy;
address public almProxy;

uint256[49] private __gap;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Don't need this

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

removed

Comment thread src/WEETHModule.sol Outdated

constructor(address admin, address _almProxy) {
constructor() {
_disableInitializers();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same as buffer, add comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

added

Comment thread src/WEETHModule.sol Outdated
}

function initialize(address admin, address _almProxy) external initializer {
require(_almProxy != address(0), "WeEthModule/invalid-alm-proxy");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same as buffer, add require and test

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

added

liquidityPool = ILiquidityPoolLike(IEETHLike(eETH).liquidityPool());

weETHModule = address(new WEETHModule(Ethereum.SPARK_PROXY, address(almProxy)));
weETHModule = address(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Needs test converage for:

  • zero admin
  • zero almProxy
  • double intialization
  • initialization of implementation
  • successful initialization (initial state)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

added

Comment thread src/WEETHModule.sol Outdated
using SafeERC20 for IERC20;

address public immutable almProxy;
address public almProxy;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same changes needed as OTC

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

done

Comment thread src/WEETHModule.sol
Comment thread src/WEETHModule.sol Outdated
Comment thread src/WEETHModule.sol Outdated
Comment thread src/WEETHModule.sol
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jan 29, 2026
deluca-mike
deluca-mike previously approved these changes Jan 29, 2026
Comment thread test/mainnet-fork/weETH.t.sol Outdated
Comment thread src/WEETHModule.sol Outdated
Comment thread src/WEETHModule.sol Outdated
@lucas-manuel
lucas-manuel merged commit 79432f3 into dev Jan 29, 2026
4 checks passed
@lucas-manuel
lucas-manuel deleted the dev-1149-weethModule-proxy branch January 29, 2026 19:32
@github-actions

Copy link
Copy Markdown

Coverage after merging dev-1149-weethModule-proxy into dev will be

99.29%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
deploy
   ControllerDeploy.sol100%100%100%100%
   ForeignControllerInit.sol100%100%100%100%
   MainnetControllerInit.sol97.37%93.33%100%100%152, 90
src
   ALMProxy.sol100%100%100%100%
   ALMProxyFreezable.sol100%100%100%100%
   ForeignController.sol96.10%89.66%95.65%98.04%130–131, 131, 131, 556
   MainnetController.sol99.18%100%98.36%99.24%596–597
   OTCBuffer.sol92.31%100%83.33%93.75%55
   RateLimitHelpers.sol100%100%100%100%
   RateLimits.sol100%100%100%100%
   WEETHModule.sol93.18%90%85.71%96.30%65, 72
src/libraries
   AaveLib.sol100%100%100%100%
   ApproveLib.sol100%100%100%100%
   CCTPLib.sol100%100%100%100%
   CurveLib.sol100%100%100%100%
   ERC4626Lib.sol97.06%90%100%100%117
   LayerZeroLib.sol100%100%100%100%
   PSMLib.sol100%100%100%100%
   UniswapV4Lib.sol99.32%95.65%100%100%282
   WEETHLib.sol100%100%100%100%

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants