πŸ“œC4 REPORT

Velocore and Velodrome Finance use the same codebase, and the security documentation for Velodrome Finance is provided below.

HOW VELODROME IS ADDRESSING ISSUES IN THE C4 CONTESTS

The Code4rena contest results were released on August 8, 2022 and are available here.

Below details how the Velodrome team addressed these issues prior to their mainnet deploy on Optimism.

HIGH RISK (6)

[H-01] Users can get unlimited votes

[H-02] VotingEscrow's merge and withdraw aren't available for approved users

  • Still exists in our mainnet deploy, VoterEscrow.sol:L510.

  • However does not result in major disruptions to user needs, also will not impact our future product plans.

[H-03] User rewards stop accruing after any _writeCheckpoint calling action

  • Got rid of tracking user votes with a prevVoteStatus boolean, Gauge.sol.

[H-04] Bribe Rewards Struck In Contract If Deposited During First Epoch

  • Got rid of the deliverBribes() method, also did not experience issue in prod. ExternalBribe.sol.

[H-05] Voting overwrites checkpoint.voted in last checkpoint, so users can just vote right before claiming rewards

  • Got rid of tracking user votes with a prevVoteStatus boolean, Gauge.sol.

[H-06] Attacker can block LayerZero channel

MEDIUM RISK (17)

[M-01] Gauge set can be front run if bribe and gauge constructors aren't run atomically

[M-02] VeloGovernor: proposalNumerator and team are updated by team, not governance

  • β€œIssue” is expected behavior.

[M-03] Alter velo receptions computation

  • See judge’s comments, attack could only be pulled by deployer and wasn’t.

[M-04] Malicious user can populate rewards array with tokens of their interest reaching limits of MAX_REWARD_TOKENS

  • Judge’s comment is accurate, does allow team to change real reward tokens (but so far non-issue).

[M-05] Bribe.sol is not meant to handle fee-on-transfer tokens

[M-06] Voting tokens may be lost when given to non-EOA accounts

  • Confirmed, see judge’s comment.

[M-07] RedemptionSender should estimate fees to prevent failed transactions

[M-08] Temporary DOS by calling notifyRewardAmount() in Bribe/Gauge with malicious tokens

[M-09] Owner's delegates should be decreased in _burn()

[M-10] Rewards aren't updated before user's balance change in Gauge's withdrawToken

[M-11] Griefing Attack By Extending The Reward Duration

  • Addressed in mainnet deploy by reverting to original implementation, Gauge.sol:L546.

[M-12] Rewards can be locked in Bribe contract because distributing them depends on base token reward amount and Gauge.deliverBribes() is not always called by Voter.distribute()

  • Addressed in mainnet deploy by decoupling bribe delivery from gauge reward distribution, Voter.sol:L369.

[M-13] Bribe Rewards Not Collected In Current Period Will Be Lost Forever

  • Addressed in mainnet by reverting to an implementation more similar to Solidly’s, which does not couple gauge and bribe rewards. ExternalBribe.sol.

[M-14] Wrong reward distribution in Bribe because deliverReward() won't set tokenRewardsPerEpoch[token][epochStart] to 0

  • Will be addressed with an upcoming fix (will be linked here once contracts are live). In the interim, relevant parties (i.e. protocols who wish to bribe) should get in touch with our team.

[M-15] Wrong calculation for the new rewardRate[token] can cause some of the late users can not get their rewards

  • Addressed in mainnet deploy as we reverted to a duration of 7 days instead of 5, Gauge.sol#L535.

[M-16] Wrong DOMAIN_TYPEHASH definition

  • Not addressed in mainnet deploy, but see judge’s comment.

[M-17] WeVE (FTM) may be lost forever if redemption process is failed

  • Error won’t happen as long as contracts were initialized correctly (which they were in prod).

Last updated