veToken Finance contest - cccz's results

Lock more veAsset permanently.

General Information

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

veToken Finance

Findings Distribution

Researcher Performance

Rank: 37/71

Findings: 2

Award: $199.53

🌟 Selected for report: 0

πŸš€ Solo Findings: 0

Findings Information

🌟 Selected for report: xiaoming90

Also found by: 0xNazgul, FSchmoede, Funen, Kumpa, VAD37, berndartmueller, cccz, kirk-baird

Labels

bug
duplicate
2 (Med Risk)

Awards

99.6119 USDT - $99.61

External Links

Lines of code

https://github.com/code-423n4/2022-05-vetoken/blob/2d7cd1f6780a9bcc8387dea8fecfbd758462c152/contracts/Booster.sol#L575-L595

Vulnerability details

Impact

The setFeeInfo function of the Booster contract is used to set the lockFeesIncentive and stakerLockFeesIncentive variables. In the earmarkFees function, the feeToken in the contract will be transferred to lockFees and stakerLockRewards according to the proportion. If lockFeesIncentive + stakerLockFeesIncentive > FEE_DENOMINATOR, the number of tokens to be transferred by the earmarkFees function will be greater than the balance, causing the earmarkFees call to fail.

Proof of Concept

https://github.com/code-423n4/2022-05-vetoken/blob/2d7cd1f6780a9bcc8387dea8fecfbd758462c152/contracts/Booster.sol#L193-L197 https://github.com/code-423n4/2022-05-vetoken/blob/2d7cd1f6780a9bcc8387dea8fecfbd758462c152/contracts/Booster.sol#L575-L595

Tools Used

None

function setFeeInfo(uint256 _lockFeesIncentive, uint256 _stakerLockFeesIncentive) external { require(msg.sender == feeManager, "!auth"); + require(_lockFeesIncentive + _stakerLockFeesIncentive <= FEE_DENOMINATOR) lockFeesIncentive = _lockFeesIncentive; stakerLockFeesIncentive = _stakerLockFeesIncentive;

#0 - jetbrain10

2022-06-15T15:17:14Z

same as issues #215

#1 - GalloDaSballo

2022-07-24T23:47:30Z

Dup of #215

Lines of code

https://github.com/code-423n4/2022-05-vetoken/blob/2d7cd1f6780a9bcc8387dea8fecfbd758462c152/contracts/BaseRewardPool.sol#L343-L345

Vulnerability details

Impact

In the getAPY function, rewardRate * BLOCKS_PER_YEAR is used to calculate APY, but rewardRate is the reward per second, and BLOCKS_PER_YEAR is the number of blocks in the year, which will result in a lower APY.

Proof of Concept

https://github.com/code-423n4/2022-05-vetoken/blob/2d7cd1f6780a9bcc8387dea8fecfbd758462c152/contracts/BaseRewardPool.sol#L343-L345

Tools Used

None

- uint256 constant BLOCKS_PER_DAY = 6450; - uint256 constant BLOCKS_PER_YEAR = BLOCKS_PER_DAY * 365; + uint256 constant SECONDS_PER_DAY = 86400; + uint256 constant SECONDS_PER_YEAR = SECONDS_PER_DAY * 365; function getAPY() external view returns (uint256) { - return rewardRate.mul(BLOCKS_PER_YEAR).mul(1e18).div(totalSupply()); + return rewardRate.mul(SECONDS_PER_YEAR).mul(1e18).div(totalSupply()); }

#0 - jetbrain10

2022-06-15T16:44:11Z

will remove this function

#1 - GalloDaSballo

2022-07-24T23:50:14Z

Finding is valid, the math is incorrect.

Notice that even the corrected math would not be APY, but APR (technically vAPR as it's based on totalSupply which can change at any moment)

Question is whether this is a valid Medium or QA.

Because the function is never used in the codebase, not even in tests, I'll downgrade to QA.

I may change my mind

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax Β© 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter