Platform: Code4rena
Start Date: 27/05/2022
Pot Size: $75,000 USDC
Total HM: 20
Participants: 58
Period: 7 days
Judge: GalloDaSballo
Total Solo HM: 15
Id: 131
League: ETH
Rank: 7/58
Findings: 3
Award: $3,532.99
🌟 Selected for report: 1
🚀 Solo Findings: 1
🌟 Selected for report: csanuragjain
2732.5332 USDC - $2,732.53
https://github.com/code-423n4/2022-05-backd/blob/main/protocol/contracts/RewardHandler.sol#L50
burnFees will fail if none of the pool tokens have underlying token as native ETH token. This is shown below. Since burnFees fails so no fees is deposited in BKDLocker
require(burningEth_ || msg.value == 0, Error.INVALID_VALUE);
ETH should not be sent if none of pool underlying token is ETH. Change it to something like below:
bool ethFound=false; for (uint256 i; i < pools.length; i = i.uncheckedInc()) { ILiquidityPool pool = ILiquidityPool(pools[i]); address underlying = pool.getUnderlying(); if (underlying != address(0)) { _approve(underlying, address(feeBurner)); } else { ethFound=true; } tokens[i] = underlying; } if(ethFound){ feeBurner.burnToTarget{value: ethBalance}(tokens, targetLpToken); } else { feeBurner.burnToTarget(tokens, targetLpToken); }
#0 - GalloDaSballo
2022-06-19T19:30:32Z
The warden has shown how, due to a flaw in the logic, if ETH is present in the contract and no pool is denominated in ETH, then the contract will revert.
This can be done as a DOS attack or for griefing.
However, remediation would simply require adding a pool denominated in ETH, to ensure that the logic goes through
For this reason, I believe Medium Severity to be more appropriate
🌟 Selected for report: hansfriese
Also found by: csanuragjain, unforgiven
737.784 USDC - $737.78
https://github.com/code-423n4/2022-05-backd/blob/main/protocol/contracts/BkdLocker.sol#L70
If Governor mistakenly adds duplicate reward token then user will get more funds
_replacedRewardTokens.remove(newRewardToken);
_replacedRewardTokens.set(rewardToken, block.timestamp);
Now new rewardToken is also set as X
Finally this becomes like below
_replacedRewardTokens=[X] rewardToken=X
Add a check to see that new reward token is not equal to existing reward token
require(newRewardToken!=rewardToken, "Migration not required");
#0 - pauljpritz-zz
2022-06-02T12:18:47Z
I don't think this is a valid bug. When the rewardToken
is replaced, the feeIntegral
for that reward token stops increasing. Therefore, even if the same reward token is present twice, it will have separate fee integrals and will therefore be treated entirely seperately. Also, there is no use of balanceOf()
to compute the feeIntegral
, therefore the two records won't be confused.
#1 - GalloDaSballo
2022-06-22T17:02:54Z
@pauljpritz I believe that
RewardTokenData storage curRewardTokenData = rewardTokenData[rewardToken];
RewardTokenData storage prevRewardTokenData = rewardTokenData[token];
When prev and new token are same, will point to the same area in storage, causing a double count.
If rewards where identified by a code, then I'd have to agree, but because they use the address, then the data for old and new would be in the same storage slot.
For that reason, I believe the finding to be valid, and a Dup of #86
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, 0x29A, 0xKitsune, 0xNazgul, 0xf15ers, 0xkatana, Chom, Dravee, Fitraldys, Funen, Kaiziron, MiloTruck, Picodes, Randyyy, RoiEvenHaim, SecureZeroX, Sm4rty, SmartSek, StyxRave, Tadashi, Tomio, Waze, asutorufos, berndartmueller, c3phas, catchup, csanuragjain, defsec, delfin454000, djxploit, fatherOfBlocks, gzeon, hake, hansfriese, oyc_109, robee, sach1r0, sashik_eth, scaraven, simon135
62.6774 USDC - $62.68
Function _setConfig: No need to set deadlines[key] = 0; as this was already done in _executeDeadline function
Function _mint: Check that amount is not equal to zero
amount!=0
Note: do same for mintNonInflationTokens
Function claimRewards: Since amount is uint type so amount cannot be <0. Change it to
if (amount == 0) return 0;
Note: Same need to be fixed for other Gauge like AMMGauge
Function claimFees: If claimable is zero, no need to go further
require(claimable!=0);
#0 - GalloDaSballo
2022-06-17T23:56:59Z
Saves 100 gas
Saves gas in the "bad path", I'd rather revert then
Saves 3 gas, although maybe the optimizer may convert to a is_zero
Saves gas in the "bad path"
Total Gas Saved 103