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: 1/71
Findings: 8
Award: $8,875.64
π Selected for report: 4
π Solo Findings: 3
π Selected for report: cryptphi
Also found by: csanuragjain
https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VE3DRewardPool.sol#L134
It was observed that addExtraReward does not check for duplicate values which can lead to duplicate reward tokens being added to extraRewards. This can lead to higher reward payment than expected. Need to be fixed for BaseRewardPool.sol as well
rewardManager calls the addExtraReward function and provides address A as reward contract
rewardManager calls the addExtraReward function and provides address B as reward contract
rewardManager calls the addExtraReward function and by mistake again provide address A as reward contract
Now extraRewards has 3 entries A,B,A
User X calls stake method for amount 1000
This executes below code
for(uint i=0; i < extraRewards.length; i++){ IRewards(extraRewards[i]).stake(msg.sender, _amount); }
Do not allow duplicate values in addExtraReward. For this Set can be used
#0 - solvetony
2022-06-15T15:11:28Z
Duplicate of #89
#1 - GalloDaSballo
2022-07-21T01:46:46Z
Dup of #16
π Selected for report: csanuragjain
2082.6377 USDT - $2,082.64
https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VE3DRewardPool.sol#L141
rewardManager can at anytime delete the extra Rewards. This impacts the extra rewards earned by existing staker. The existing staker will have no way to claim these extra rewards. Since these extra rewards have been staked for all users making a deposit BaseRewardPool.sol#L215 so basically the extra reward gets locked with no one having access to this fund. Need to be fixed for BaseRewardPool.sol as well
If rewardManager wants to clear extra rewards then all existing stakes on extra rewards must be withdrawn and claimed so that user extra rewards are not lost
#0 - solvetony
2022-06-15T15:10:23Z
Not an issue of the user staked fund, but we need to add call at pool factory for clearExtraRewards()
.
#1 - GalloDaSballo
2022-07-21T01:46:08Z
The warden has shown how, due to admin privilege, extra rewards could stay stuck in the contract.
Because this is contingent on a malicious admin, I believe Medium Severity to be more appropriate.
Notice that the rewards would be lost forever as there doesn't seem to be any sweep
function which instead would allow the admin to take the reward tokens
My recommendation is to remove the function to clearExtraRewards
as it doesn't seem to help but it can indeed cause issues
π Selected for report: csanuragjain
Also found by: kirk-baird, unforgiven
562.3122 USDT - $562.31
https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/Booster.sol#L256
It was observed that addPool function is not checking for duplicate lpToken which allows 2 or more pools to have exact same lpToken. This can cause issue with deposits.
In case of duplicate lpToken, the first pool calling depositAll will take away all lpToken and deposit them under there own pid. This leaves no balance for 2nd pool
Add a global variable keeping track of all lpToken added for pool. In case of duplicate lpToken addPool function should fail.
#0 - jetbrain10
2022-06-15T15:24:57Z
there is already a validation not allow to add duplicated gauges, pool manager contract, add pool function , but we have to add also a validation for lp token like gauges
#1 - GalloDaSballo
2022-07-21T01:54:48Z
The warden has shown how, due to a lack of validation, the assumption that each lpToken is used only on one pool can be broken. This will cause accounting issues.
For those reasons, I agree with Medium Severity
π Selected for report: kirk-baird
Also found by: Dravee, IllIllI, Koustre, Ruhum, VAD37, csanuragjain, gzeon, unforgiven, xiaoming90
https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VE3DRewardPool.sol#L102 https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VE3DLocker.sol#L145
The current implementation of addReward seems to allow any number of reward token to be added. There should be a limit on the number of rewards allowed
Add below check in addReward function:
require(rewardTokens.length<MAX_ALLOWED, "Max reward crossed")
#0 - solvetony
2022-06-15T15:34:04Z
Duplicate of #136
#1 - GalloDaSballo
2022-07-21T01:52:58Z
Dup of #136
π Selected for report: unforgiven
Also found by: csanuragjain
937.187 USDT - $937.19
https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VE3DRewardPool.sol
Sweep function is missing which could lead to reward token being stuck in contract. Need to be fixed for BaseRewardPool.sol as well
Assume new rewards were added to the contract and first user staked after 3 days.
This means the reward for the first 3 days will remain in contract and will not be given to anyone.
Currently Admin has no way to claim this 3 days rewards (will not even come within queued rewards). Ideally Admin must have a way to clean out this pending reward once duration is over
Kindly consider adding below:
function sweepAmount(int amount) external returns (bool) { if(block.timestamp<periodFinish){ return; } rewardToken.safeTransfer(adminAddress, amount); return true; }
#0 - jetbrain10
2022-06-15T15:27:12Z
yes, it is nice to have and we will add it. This part is forked from convex and we didn;t change it
#1 - GalloDaSballo
2022-07-24T23:57:51Z
Dup of #168
π Selected for report: csanuragjain
2082.6377 USDT - $2,082.64
https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/Booster.sol#L129
Once Fee Manager has been set initially by owner, then owner has no power to change it. Owner should be allowed to change fees manager in case if he feels current fee manager is behaving maliciously
function setFeeManager(address _feeM) external { require(msg.sender == feeManager, "!auth"); feeManager = _feeM; emit FeeManagerUpdated(_feeM); }
Change the setFeeManager function like below. Same can be done with other important functionality involving setArbitrator and setVoteDelegate
require(msg.sender == owner, "!auth");
#0 - GalloDaSballo
2022-07-25T00:10:07Z
I agree with the finding, the feeManager can also potentially funnel funds away so it's best to allow governance to replace them if need be.
Due to the finding being tied to admin privilege, I agree with Medium Severity
π Selected for report: csanuragjain
2082.6377 USDT - $2,082.64
https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VE3DRewardPool.sol#L102
If _rewardToken is set as _stakingToken by mistake then user funds would get lost (staking token will get sent as reward token). Need to be fixed for BaseRewardPool.sol as well
Add below check in constructor
require(_stakingToken!=_rewardToken, "Incorrect reward token");
#0 - jetbrain10
2022-06-15T15:27:59Z
it set by owner, so there is no issue, but it is nice to have and it is a quick fix
#1 - GalloDaSballo
2022-07-27T00:25:42Z
The warden has shown how, due to a misconfiguration, the deposit token stakingToken
Β could be transferred away to early withdrawers.
For end users the basic due diligence would be to ensure that the stakingToken
is not added as reward.
Because the finding is contingent on a malicious admin / misconfiguration, I believe Medium Severity to be appropriate
π Selected for report: IllIllI
Also found by: 0x1f8b, 0x29A, 0xDjango, 0xNazgul, 0xf15ers, BouSalman, Chom, Deivitto, Dravee, ElKu, FSchmoede, Funen, GimelSec, Hawkeye, MiloTruck, Picodes, SecureZeroX, SmartSek, TerrierLover, WatchPug, _Adam, asutorufos, berndartmueller, c3phas, catchup, cccz, cogitoergosumsw, cryptphi, csanuragjain, delfin454000, dipp, ellahi, gzeon, hansfriese, horsefacts, hyh, kirk-baird, minhquanym, oyc_109, pauliax, reassor, robee, sashik_eth, shenwilly, simon135, sorrynotsorry, sseefried, unforgiven, xiaoming90, z3s
110.3392 USDT - $110.34
Function setOwner: The function does not perform zero address check which means owner can be updated incorrectly.
Also it is recommended to change owner in 2 step process which will ensure that new owner is indeed correct
require(_owner!=address(0), "Incorrect address");
Function voteGaugeWeight: Add below check to prevent incorrect weight updation
require(_tokenVote.length==_weight.length,"Incorrect length");
Function updateveAssetWeight: newWeight cannot be zero. If need to be 0 then better to remove operator
require(newWeight!=0, "Incorrect weight");
#0 - jetbrain10
2022-06-15T21:08:07Z
high quality.
#1 - GalloDaSballo
2022-07-06T23:59:23Z
1L, 1R, 1 NC