Platform: Code4rena
Start Date: 03/05/2022
Pot Size: $50,000 USDC
Total HM: 4
Participants: 46
Period: 5 days
Judge: gzeon
Total Solo HM: 2
Id: 117
League: ETH
Rank: 7/46
Findings: 3
Award: $507.30
🌟 Selected for report: 0
🚀 Solo Findings: 0
latestAnswer
function is deprecated, which doesn’t return an error but returns 0, and It is not able to check if the price is stale.
In the getUnderlyingPrice
function of PriceOracleImplementation.sol, it uses ChainlinkFeed(0x986b5E1e1755e3C2440e960477f25201B0a8bbD4).latestAnswer()
which will return the last value, but it doesn’t check if the value is fresh or not.
vim
Use latestRoundData
rather than latestAnswer
and check the value:
( roundId, answer, startedAt, updatedAt, answeredInRound ) = aggregator.latestRoundData(); require(answer > 0, "Invalid answer"); require(updatedAt != 0, "Invalid updatedAt"); require(answeredInRound >= roundId, "Stale price");
#0 - bunkerfinance-dev
2022-05-09T18:19:36Z
Duplicate of #1
🌟 Selected for report: BowTiedWardens
Also found by: 0x1337, 0x1f8b, 0x4non, 0xDjango, David_, Funen, GimelSec, IllIllI, Picodes, TerrierLover, WatchPug, bobi, cryptphi, csanuragjain, delfin454000, dirk_y, ellahi, fatherOfBlocks, hyh, ilan, jayjonah8, kebabsec, leastwood, oyc_109, robee, samruna, simon135, sorrynotsorry, throttle
161.1611 USDC - $161.16
We list 2 low-critical findings:
CNft
as an upgradable contract by proxyCNft
as an upgradable contract by proxyIn CNftTest.ts
, it deploys CNft
without using a proxy contract. Use a proxy contract to deploy CNft
for an upgradable contract, or it’s not necessary to use @openzeppelin/contracts-upgradeable
.
CNft.sol uses ReentrancyGuardUpgradeable
and OwnableUpgradeable
:
https://github.com/bunkerfinance/bunker-protocol/blob/752126094691e7457d08fc62a6a5006df59bd2fe/contracts/CNft.sol#L16
vim
Use proxy to deploy: https://docs.openzeppelin.com/upgrades-plugins/1.x/hardhat-upgrades
Or there’s no need to use upgradable contracts ReentrancyGuardUpgradeable
and OwnableUpgradeable
, use ReentrancyGuard
and Ownable
instead.
Floating pragma may cause unexpected compilation time behaviour and introduce unintended bugs.
Oracles/CNftPriceOracle.sol 2:pragma solidity ^0.8.0; Oracles/UniswapV2PriceOracle.sol 2:pragma solidity ^0.8.0; CNft.sol 2:pragma solidity ^0.8.0;
vim
Don't use ^
, lock pragma to ensure compiler version. e.g. pragma solidity 0.8.0;
🌟 Selected for report: BowTiedWardens
Also found by: 0v3rf10w, 0x1f8b, 0x4non, 0xDjango, 0xNazgul, 0xkatana, Cityscape, Fitraldys, Funen, GimelSec, IllIllI, MaratCerby, Picodes, TerrierLover, Tomio, delfin454000, ellahi, fatherOfBlocks, hansfriese, ilan, joestakey, oyc_109, rfa, robee, samruna, simon135, slywaters, throttle
47.5594 USDC - $47.56
The for loop has no overflow risk of i
. Use an unchecked block to save gas.
Oracles/CNftPriceOracle.sol 66: for (uint256 i = 0; i < cNfts.length; ++i) { Oracles/UniswapV2PriceOracle.sol 42: for (uint256 i = 0; i < pairs.length; ++i) { Comptroller.sol 119: for (uint i = 0; i < len; i++) { 199: for (uint i = 0; i < len; i++) { 591: for (uint i = 0; i < assets.length; i++) { 928: for (uint i = 0; i < allMarkets.length; i ++) { 1223: for (uint i = 0; i < cTokens.length; i++) { 1229: for (uint j = 0; j < holders.length; j++) { 1235: for (uint j = 0; j < holders.length; j++) { 1240: for (uint j = 0; j < holders.length; j++) { CNft.sol 50: for (uint256 i; i < length; ++i) { 62: for (uint256 i; i < length; ++i) { 72: for (uint256 i; i < length; ++i) { 98: for (uint256 i; i < length; ++i) { 122: for (uint256 i; i < length; ++i) { 145: for (uint256 i; i < length; ++i) { 151: for (uint256 i; i < length; ++i) { 176: for (uint256 i; i < vars.length; ++i) { ERC1155Enumerable.sol 51: for (uint256 i; i < ids.length; ++i) {
Use unchecked
blocks to avoid overflow checks, or use ++i
rather than i++
if you don't use unchecked blocks.
for (uint256 i = 0; i < length; ) { ... unchecked { ++i; } }