Platform: Code4rena
Start Date: 18/10/2023
Pot Size: $36,500 USDC
Total HM: 17
Participants: 77
Period: 7 days
Judge: MiloTruck
Total Solo HM: 5
Id: 297
League: ETH
Rank: 34/77
Findings: 2
Award: $120.08
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0xmystery
Also found by: 0x6d6164616e, 0xWaitress, 0xsurena, Tendency, ZanyBonzy, cryptothemex, hals, lsaudit, ni8mare, niki, phoenixV110, spark, tnquanghuy0512, twcctop
26.0735 USDC - $26.07
Judge has assessed an item in Issue #221 as 2 risk. The relevant finding follows:
[L-02] Handling missing for case where ERC20 token has decimal > 18 in CamelotRelayer & UniV3Relayer oracles https://github.com/open-dollar/od-contracts/blob/v1.5.5-audit/src/contracts/oracles/UniV3Relayer.sol#L64 https://github.com/open-dollar/od-contracts/blob/v1.5.5-audit/src/contracts/oracles/CamelotRelayer.sol#L58
Description In the constructor token decimals of an ERC20 is assumed to be <= 18 which can be wrong for some tokens. There should be a handling to avoid unexpected execution failures.
Existing multiplier = 18 - IERC20Metadata(_quoteToken).decimals(); Suggestion uint256 quoteTokenDecimals = IERC20Metadata(_quoteToken).decimals();
if(quoteTokenDecimals > 18) { revert CustomError(); } multiplier = 18 - quoteTokenDecimals;
#0 - c4-judge
2023-11-03T17:04:31Z
MiloTruck marked the issue as duplicate of #323
#1 - c4-judge
2023-11-03T17:04:35Z
MiloTruck marked the issue as satisfactory
🌟 Selected for report: MrPotatoMagic
Also found by: 0xMosh, 0xPsuedoPandit, 0xhacksmithh, 8olidity, Al-Qa-qa, Baki, Bughunter101, Krace, Stormreckson, T1MOH, Tendency, eeshenggoh, fibonacci, hals, immeas, kutugu, lsaudit, m4k2, mrudenko, okolicodes, phoenixV110, spark, twicek, xAriextz
94.0139 USDC - $94.01
https://github.com/open-dollar/od-contracts/blob/v1.5.5-audit/src/contracts/oracles/CamelotRelayer.sol#L48-#L55 https://github.com/open-dollar/od-contracts/blob/v1.5.5-audit/src/contracts/oracles/UniV3Relayer.sol#L54-#L61
In the constructor _token0 and _token1 is set to baseToken and quoteToken global variables but the validation comment says both token0 and token1 are validated is untrue. The check can be refactored as suggested below.
if (_token0 == _baseToken) { baseToken = _token0; quoteToken = _token1; } else { baseToken = _token1; quoteToken = _token0; }
if (_token0 == _baseToken) { if(_token1 == _quoteToken) { baseToken = _token0; quoteToken = _token1; } else { revert CustomError; } } else if (_token1 == _baseToken){ if(_token0 == _quoteToken) { baseToken = _token1; quoteToken = _token0; } else { revert CustomError; } } else { revert CustomError; }
https://github.com/open-dollar/od-contracts/blob/v1.5.5-audit/src/contracts/oracles/UniV3Relayer.sol#L64 https://github.com/open-dollar/od-contracts/blob/v1.5.5-audit/src/contracts/oracles/CamelotRelayer.sol#L58
In the constructor token decimals of an ERC20 is assumed to be <= 18 which can be wrong for some tokens. There should be a handling to avoid unexpected execution failures.
multiplier = 18 - IERC20Metadata(_quoteToken).decimals();
uint256 quoteTokenDecimals = IERC20Metadata(_quoteToken).decimals(); if(quoteTokenDecimals > 18) { revert CustomError(); } multiplier = 18 - quoteTokenDecimals;
https://github.com/open-dollar/od-contracts/blob/v1.5.5-audit/src/contracts/oracles/CamelotRelayer.sol#L59 https://github.com/open-dollar/od-contracts/blob/v1.5.5-audit/src/contracts/oracles/UniV3Relayer.sol#L65
_quotePeriod can be sent as 0 by mistake and there is no method available to update it.
add a non zero check in the constructor and add a method to update the quotePeriod if necessary.
Any user can send any arbitrary number to addSAFE() method and it will be added to _usrSafes mapping of the user.
function addSAFE(uint256 _safe) external { SAFEData memory _sData = _safeData[_safe]; _usrSafes[msg.sender].add(_safe); _usrSafesPerCollat[msg.sender][_sData.collateralType].add(_safe); }
Add a check if the safe exists and if the msg.sender is the owner of the safe or not. Only then allow it to add to the mapping.
function addSAFE(uint256 _safe) external { SAFEData memory _sData = _safeData[_safe]; if(_sData.owner == msg.sender) { _usrSafes[msg.sender].add(_safe); _usrSafesPerCollat[msg.sender][_sData.collateralType].add(_safe); } }
Check ODProxy(_userRegistry[_user]).OWNER() != _user will always be false as the owner is always set _user when the proxy is deployed and it is not modifier anywhere in the code.
function _isNotProxy(address _user) internal view returns (bool) { return _userRegistry[_user] == address(0) || ODProxy(_userRegistry[_user]).OWNER() != _user; }
Redundant check ODProxy(_userRegistry[_user]).OWNER() can be removed.
https://github.com/open-dollar/od-contracts/blob/v1.5.5-audit/src/contracts/proxies/Vault721.sol#L34
There is no address(0) check while setting up the governor in constructor(). There isn't any method to update the governor.
constructor(address _governor) ERC721('OpenDollar Vault', 'ODV') { governor = _governor; }
Add a check if the _governor == address(0) the revert() the transaction.
https://github.com/open-dollar/od-contracts/blob/v1.5.5-audit/src/contracts/oracles/CamelotRelayer.sol#L36 https://github.com/open-dollar/od-contracts/blob/v1.5.5-audit/src/contracts/oracles/UniV3Relayer.sol#L35
For multiplier uint256 is used while it's value will be <=18.
uint256 public multiplier;
uint8 can be used for multiplier varaible.
https://github.com/open-dollar/od-contracts/blob/v1.5.5-audit/src/contracts/AccountingEngine.sol#L37-#L39 https://github.com/open-dollar/od-contracts/blob/v1.5.5-audit/src/contracts/AccountingEngine.sol#L61-L#63
The above mentioned methods should be put after the constructor definition.
#0 - c4-pre-sort
2023-10-27T01:00:13Z
raymondfam marked the issue as sufficient quality report
#1 - c4-judge
2023-11-03T16:42:59Z
MiloTruck marked the issue as grade-a