Dria

Swan
NFTHardhat
21,000 USDC
View results
Submission Details
Severity: medium
Invalid

`Swan.sol`, `LLMOracleCoordinator.sol` and `LLMOracleRegistry.sol` are upgradeable contracts that use non-upgradeable contract libraries

Summary

In Solidity, code that is inside a constructor or part of a global variable declaration is not part of a deployed contract’s runtime bytecode. This code is executed only once, when the contract instance is deployed.

Swan.sol, LLMOracleCoordinator.sol and LLMOracleRegistry.sol are upgradeable contracts that use non-upgradeable contract libraries. This cause the code within a logic contract’s constructor (non-upgradeable contract libraries) will never be executed in the context of the proxy’s state. To rephrase, proxies are completely oblivious to the storage trie changes that are performed by the constructor.

For more detail can be check here

Vulnerability Details

  1. Swan.sol use ERC20 and ERC721 libraries instead of ERC20Upgradeable and ERC721Upgradeable

  2. LLMOracleCoordinator.sol use ERC20 library instead of ERC20Upgradeable

  3. LLMOracleRegistry.sol use ERC20 library instead of ERC20Upgradeable

Consider for example ERC20 from OpenZeppelin Contracts: the contract initializes the token’s name and symbol in its constructor

// @openzeppelin/contracts/token/ERC20/ERC20.sol
pragma solidity ^0.8.0;
...
contract ERC20 is Context, IERC20 {
...
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
...
}

Instead, make sure to use @openzeppelin/contracts-upgradeable, which is an official fork of OpenZeppelin Contracts that has been modified to use initializers instead of constructors. Take a look at what ERC20Upgradeable looks like in @openzeppelin/contracts-upgradeable:

// @openzeppelin/contracts-upgradeable/contracts/token/ERC20/ERC20Upgradeable.sol
pragma solidity ^0.8.0;
...
contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable {
...
string private _name;
string private _symbol;
function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {
__ERC20_init_unchained(name_, symbol_);
}
function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {
_name = name_;
_symbol = symbol_;
}
...
}

Impact

The code within a logic contract’s constructor (non-upgradeable contract libraries) will never be executed in the context of the proxy’s state

Tools Used

Manual Review

Recommended Mitigation

Consider use upgradeable contracts libraries

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Appeal created

0xdemon Submitter
about 1 year ago
0xdemon Submitter
12 months ago
0xdemon Submitter
12 months ago
inallhonesty Lead Judge
12 months ago
inallhonesty Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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