Platform: Code4rena
Start Date: 26/05/2022
Pot Size: $75,000 USDT
Total HM: 31
Participants: 71
Period: 7 days
Judge: GalloDaSballo
Total Solo HM: 18
Id: 126
League: ETH
Rank: 19/71
Findings: 2
Award: $1,017.13
🌟 Selected for report: 0
🚀 Solo Findings: 0
https://github.com/code-423n4/2022-05-vetoken/blob/2d7cd1f6780a9bcc8387dea8fecfbd758462c152/contracts/Booster.sol#L313 https://github.com/code-423n4/2022-05-vetoken/blob/2d7cd1f6780a9bcc8387dea8fecfbd758462c152/contracts/Booster.sol#L316
An issue in withdrawAll
function, permits the pool shutdown and not retrieve the tokens.
The issue is reproduced the following way:
poolManager
calls shutdownPool
any the _pid valuewithdrawAll
function try an errorfunction shutdownPool(uint256 _pid) external returns (bool) { ... //withdraw from gauge + try IStaker(staker).withdrawAll(pool.lptoken, pool.gauge) {} catch { + return false; + } - try IStaker(staker).withdrawAll(pool.lptoken, pool.gauge) {} catch {} pool.shutdown = true; gaugeMap[pool.gauge] = false; ... return true; }
VSCode
#0 - jetbrain10
2022-06-15T16:04:11Z
same as issue #35
#1 - GalloDaSballo
2022-07-25T00:52:46Z
Dup of #35
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, 0x29A, 0xKitsune, 0xNazgul, 0xf15ers, 0xkatana, Cityscape, Dravee, ElKu, FSchmoede, Funen, GalloDaSballo, Hawkeye, Kaiziron, MiloTruck, Randyyy, RoiEvenHaim, Ruhum, SecureZeroX, SmartSek, TerrierLover, TomJ, Tomio, WatchPug, Waze, _Adam, asutorufos, c3phas, catchup, cogitoergosumsw, delfin454000, ellahi, fatherOfBlocks, gzeon, hansfriese, horsefacts, jonatascm, minhquanym, oyc_109, pauliax, reassor, robee, sach1r0, saian, sashik_eth, simon135, z3s
79.9372 USDT - $79.94
updateveAssetWeight
in VeTokenMinter contractReducing one call to totalWeight
variable will reduce gas used
... ///@dev weight is 10**25 precision function updateveAssetWeight(address veAssetOperator, uint256 newWeight) external onlyOwner { require(operators.contains(veAssetOperator), "not an veAsset operator"); + totalWeight += newWight - veAssetWeights[veAssetOperator]; - totalWeight -= veAssetWeights[veAssetOperator]; veAssetWeights[veAssetOperator] = newWeight; - totalWeight += newWeight; } ...
VSCode
For gas optimization declare constants variables outside of constructor
+ uint256 public totalCliffs = 1000; + uint256 public reductionPerCliff = maxSupply.div(totalCliffs);; ... constructor(address veTokenAddress) { veToken = ERC20(veTokenAddress); - totalCliffs = 1000; - reductionPerCliff = maxSupply.div(totalCliffs); } ...
VSCode
If you divide first then multiply you may lose precision, to not lose precision you need to multiply first and then divide
function initialLock() external { ... if (veVeAsset == 0) { uint256 unlockAt = block.timestamp + maxTime; //@audit Possible miss calculation unlockInWeeks = unlockAt + uint256 unlockInWeeks = (unlockAt * WEEK) / WEEK; - uint256 unlockInWeeks = (unlockAt / WEEK) * WEEK; ... } ... } ... function _lockVeAsset() internal { ... uint256 unlockAt = block.timestamp + maxTime; //@audit Possible miss calculation unlockInWeeks = unlockAt + uint256 unlockInWeeks = (unlockAt * WEEK) / WEEK; - uint256 unlockInWeeks = (unlockAt / WEEK) * WEEK; ... }
VSCode
!= 0
 INSTEAD OF > 0
For gas optimization use ≠0
instead of > 0
... uint256 x; + require(x != 0, "x!=0"); - require(x > 0, "x>0"); ...
VSCode
for
For gas optimization in for loop you have 2 options:
i++
to ++i
... uint256[] array = [...] + uint256 length = array.length; + for (uint i = 0; i < length;){ ... + uncheck{++i;} + } - for (uint256 i = 0; i < array.length; i++) {...}
VSCode
= 0
To optimize you don't need to declare default initial values to variables, eg.
bool isFalse = false
uint256 x = 0
... //BaseRewardPool.sol + uint256 public periodFinish; + uint256 public rewardRate; - uint256 public periodFinish = 0; - uint256 public rewardRate = 0; ... + uint256 public queuedRewards; + uint256 public currentRewards; + uint256 public historicalRewards; - uint256 public queuedRewards = 0; - uint256 public currentRewards = 0; - uint256 public historicalRewards = 0; ...
... //VeAssetDepositor.sol + uint256 public incentiveVeAsset; - uint256 public incentiveVeAsset = 0; ...
... //VoterProxy.sol + uint256 _balance; - uint256 _balance = 0; ...
VSCode
delete
instead of setting to defaultTo reduce gas cost of a function you should use delete
instead of setting to default, check the following code
... //BaseRewardPool.sol //Change to delete + delete rewards[_account]; - rewards[_account] = 0; ... //Change to delete + delete queuedRewards; - queuedRewards = 0;; ...
VSCode
immutable
The variables operator
,rewardManager
, pid
, stakingToken
and rewardToken
are fixed, you can declare them as immutable for a gas optimization
... + IERC20 public immutable rewardToken; + IERC20 public immutable stakingToken; + address public immutable operator; + address public immutable rewardManager; + uint256 public immutable pid; - IERC20 public rewardToken; - IERC20 public stakingToken; - address public operator; - address public rewardManager; - uint256 public pid; ...
VSCode
modifiers
for require
used multiple timesImpact
More than 2 similar requires can be replaced by a modifier
Create these modifier and replace in functions inside VoterProxy.sol
+ modifier isOwner() { + require(msg.sender == owner, "!auth"); + } ... + modifier isOperator() { + require(msg.sender == operator, "!auth"); + } ... + modifier isDepositor() { + require(msg.sender == depositor, "!auth"); + }
VSCode
#0 - GalloDaSballo
2022-07-14T02:13:07Z
5 immutables = 10500 + the rest is less than 1k
11500 roughly saved