Tadle

Tadle
DeFi
30,000 USDC
View results
Submission Details
Severity: low
Invalid

Owner can re-initialize wrappedNativeToken TokenManager due to lack of input validation.

Summary

The lack of input validation in TokenManager.sol#L43-L45 could allow the wrappedNativeToken to be re-initialized with a contract containing arbitrary code.

Vulnerability Details

The purpose of the initialize function in the context of upgradeable contracts is to serve as a constructor, which should only be called once to set up the initial state of the contract. However, the current implementation allows the initialize function to be called multiple times by the owner, potentially reinitializing the wrappedNativeToken to a contract with arbitrary code.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "../../Base.t.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IWrappedNativeToken} from "../../../src/interfaces/IWrappedNativeToken.sol";
contract MaliciousWrappedNativeToken is IWrappedNativeToken {
function deposit() external payable override {
while(true) {}
}
function withdraw(uint256 amount) external override {
while(true) {}
}
}
contract L01 is Base {
function test_initialize_can_be_reinitialized() external prank(guardian) {
// assert that wrapped native token is already initialized
assertEq(tokenManager.wrappedNativeToken() != address(0), true);
// deploy a new wrapped native token with malicious code
MaliciousWrappedNativeToken token = new MaliciousWrappedNativeToken();
// re-initialize token manager with the new wrapped native token
tokenManager.initialize(address(token));
assertEq(tokenManager.wrappedNativeToken(), address(token));
}
}

Impact

If the owner's private key is compromised, an attacker could deploy a malicious token contract that is compatible on an interface level with WETH9 but contains harmful code. This malicious contract could execute arbitrary and potentially harmful logic when functions, such as, WETH::deposit() and WETH::withdraw()are called.

Tools Used

Manual Review, Foundry

Recommendations

Consider checking if the wrappedNativeToken is already initialized.

function initialize(address _wrappedNativeToken) external onlyOwner {
+ if (wrappedNativeToken != address(0x0)) {
+ revert AlreadyInitialized();
+ }
wrappedNativeToken = _wrappedNativeToken;
}
Updates

Lead Judging Commences

0xnevi Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Known issue
Assigned finding tags:

[invalid] finding-Rescuable-initialize-owner

Invalid, can only be initialized by admin, which are trusted per contest READ.ME. So this would take a malicious admin to reinitialize contracts.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.