Platform: Code4rena
Start Date: 21/12/2021
Pot Size: $30,000 USDC
Total HM: 20
Participants: 20
Period: 5 days
Judge: Jack the Pug
Total Solo HM: 13
Id: 70
League: ETH
Rank: 16/20
Findings: 2
Award: $109.45
🌟 Selected for report: 2
🚀 Solo Findings: 0
26.2062 USDC - $26.21
Jujic
There is no upper limit on vaderPairs[]
, it increments each time when a new pair is added. Eventually, as the count of pair increases, gas cost of smart contract calls will raise and that there is no implemented function to reduce the array size.
For every call functions which computed the Vaden price of a given par is listed in vaderPairs
array, the gas consumption can be more expensive each time that a new collateral address is appended to the array, until reaching an "Out of Gas" error or a "Block Gas Limit" in the worst scenario.
The same situation with usdvPairs
array.
As a result, this situation can lead to the blocking of the pricing mechanism and loss reimbursement in the protocol.
Remix
Add additional check for max array length or add remove function
#0 - SamSteinGG
2021-12-27T10:45:14Z
There can be no hard limit as block gas limits and gas cost fluctuate.
#1 - jack-the-pug
2022-03-12T05:04:07Z
Downgraded to low
as the adding of pairs is onlyOwner
, and it's unlikely to happen in practice.
🌟 Selected for report: pauliax
Also found by: Dravee, Jujic, Meta0xNull, robee
7.5338 USDC - $7.53
Jujic
Shortening revert strings to fit in 32 bytes will decrease deployment time gas and will decrease runtime gas when the revert condition has been met.
function _onlyUSDV() private view { require( address(usdv) == msg.sender, "Vader::_onlyUSDV: Insufficient Privileges" ); }
Remix
Shorten the revert strings to fit in 32 bytes.
#0 - 0xstormtrooper
2021-12-23T01:46:30Z
Vader is already live
#1 - jack-the-pug
2022-03-12T14:44:23Z
Dup #188
15.5017 USDC - $15.50
Jujic
State variable vadger
is read two times respectively in mint()
function. Caching it in local variable at the beginning of the function and using local variables can save gas.
vader.transferFrom(msg.sender, address(this), vAmount); vader.burn(vAmount);
Remix
Cache vader
state variable in local variable at the beginning of the function and use those local variable instead.
#0 - jack-the-pug
2022-03-12T14:39:03Z
Dup #15
15.5017 USDC - $15.50
Jujic
Using the unchecked keyword to avoid redundant arithmetic underflow/overflow checks to save gas when an underflow/overflow cannot happen.
cycleTimestamp = block.timestamp + 24 hours;
Remix
Consider using 'unchecked' where it is safe to do so.
unchecked { cycleTimestamp = block.timestamp + 24 hours; }
#0 - jack-the-pug
2022-03-13T12:26:38Z
Dup #130
🌟 Selected for report: Jujic
25.8362 USDC - $25.84
Jujic
modifier onlyUSDV()
calls internal function _onlyUSDV()
. This function is not called anywhere else. So I do not see a reason why all the logic can't be moved to the modifier to save some gas by reducing the extra call.
Remix
Remove function _onlyUSDV()
, place its logic directly in the onlyUSDV()
modifier.
#0 - 0xstormtrooper
2021-12-23T01:45:52Z
Internal functions inside modifier reduces the size of contract. Vader is already live so this suggestion won't be applied
🌟 Selected for report: defsec
Also found by: Jujic, TomFrenchBlockchain, danb, hyh
18.8684 USDC - $18.87
Jujic
The method .latestRoundData() on an oracle returns the latest updated price from the oracle, but this is not the current price of an asset. To get an accurate current price you need to query it by calling the oracle and waiting for a callback to fulfill the request.
Inaccurate price data could quickly lead to a large loss of funds. Suppose the price of an asset changes downward 5% but your oracle is not updated.
Remix
https://github.com/code-423n4/2021-08-notional-findings/issues/18
Recommend not fetching the latest price (having to call the oracle to update the price instead), and then waiting for the callback.
#0 - jack-the-pug
2022-03-12T05:05:14Z
Dup of #111