Venus Prime - PwnStars's results

Earn, borrow & lend on the #1 Decentralized Money Market on the BNB chain.

General Information

Platform: Code4rena

Start Date: 28/09/2023

Pot Size: $36,500 USDC

Total HM: 5

Participants: 115

Period: 6 days

Judge: 0xDjango

Total Solo HM: 1

Id: 290

League: ETH

Venus Protocol

Findings Distribution

Researcher Performance

Rank: 16/115

Findings: 3

Award: $235.12

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

198.4834 USDC - $198.48

Labels

bug
3 (High Risk)
satisfactory
upgraded by judge
duplicate-555

External Links

Lines of code

https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L818-L822 https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L397-L405

Vulnerability details

Impact

The management of pending score updates within the Prime Program can lead to certain users not accruing their deserved interests in newly added markets. This is because their scores may not be updated as intended. Meanwhile, an attacker could obtain more rewards than they're entitled to due to these temporarily inaccurate scores.

Proof of Concept

  1. Owner invokes addMarket, which internally calls _startScoreUpdateRound.
  2. Assuming there are 4 minted Prime Tokens, pendingScoreUpdates is set to 4.
   function _startScoreUpdateRound() internal {
       nextScoreUpdateRoundId++;
       totalScoreUpdatesRequired = totalIrrevocable + totalRevocable;
       pendingScoreUpdates = totalScoreUpdatesRequired;
   }
  1. Bob claims new tokens using the claim function. This mints a new Prime Token, increasing the count to 5.
  2. Bob then calls updateScores providing 3 previously minted token addresses plus their own one
  3. The pendingScoreUpdates counter decrements in each iteration. As a result, it will be set to 0 after processing the Bob’s and the 3 other addresses.
  4. There's still 1 user with a minted Prime Token that hasn't had their scores updated. Due to the check if (pendingScoreUpdates == 0) revert NoScoreUpdatesRequired(); no further score updates are allowed for this user. Bob will receive more rewards than expected, because the omitted user has score 0, so the available rewards won't be distributed to that user.

Tools Used

Manual review

Increment the pendingScoreUpdates whenever any new Prime Token is claimed.

Assessed type

Timing

#0 - c4-pre-sort

2023-10-06T01:15:17Z

0xRobocop marked the issue as duplicate of #555

#1 - c4-judge

2023-11-01T19:59:13Z

fatherGoose1 marked the issue as satisfactory

#2 - c4-judge

2023-11-05T00:52:22Z

fatherGoose1 changed the severity to 3 (High Risk)

Awards

32.2731 USDC - $32.27

Labels

bug
2 (Med Risk)
satisfactory
duplicate-556

External Links

Lines of code

https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L200-L230

Vulnerability details

Impact

It has been confirmed by the sponsor that the updateScores function will be called for every user by the owner, e.g. if the new market will be added.

An attacker, upon observing the owner's transaction containing an array of user addresses intended for score updates, can front-run this transaction. By selecting a single address from the owner's list and invoking the updateScores function with a higher gas price, the attacker ensures that this specific user's score is updated prior to the owner's transaction being mined. When the owner's transaction processes and encounters the already updated address, the check if (isScoreUpdated[nextScoreUpdateRoundId][user]) continue; will trigger.

Because the continue statement is invoked and the loop counter doesn't increment until the end, the function can run out of gas and revert. This allows an attacker to repeatedly grief the owner, leading to financial losses from wasted gas.

Proof of Concept

  1. Owner initiates the updateScores call, providing an array of all users addresses to update their scores.
  2. An attacker observes this transaction, selects one address from the array and calls updateScores for this specific address, ensuring their transaction has a higher gas price.
  3. The attacker's transaction updates the score for the chosen address before.
  4. The owner's transaction starts processing, but when it reaches the already updated address, the check if (isScoreUpdated[nextScoreUpdateRoundId][user]) continue; will skip the address, resulting in transaction revert due to out of gas error.

Tools Used

Manual review

Increment the i counter directly in the loop header:

for (uint256 i = 0; i < users.length; i++)

Assessed type

Loop

#0 - c4-pre-sort

2023-10-04T22:18:55Z

0xRobocop marked the issue as duplicate of #556

#1 - c4-judge

2023-11-01T20:29:21Z

fatherGoose1 marked the issue as satisfactory

1. Sweep Token Will Emit Incorrect Event With Fee-On-Transfer Tokens

Description:

The sweep token function here https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/PrimeLiquidityProvider.sol#L216 when given a fee-on-trasfer token (considering there is some amount of that token in the contract) will emit the incorrect event as the amount in the argument of the event would be less than the amount given as parameter.

2. getEffectivedistributionSpeed Might Give Incorrect Result

Description:

The function getEffectivedistributionSpeed here https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/PrimeLiquidityProvider.sol#L232 might give incorrect result as before calculating uint256 accrued it does not call accrueTokens , since it is a view function is would be incorrect to change state this way but it can be changed to a normal external function.

3. While Issuing a Prime Token _mint Might Revert

Description:

The appropriate role can call issue() function https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L331 to issue a Prime token to an array of users , but if one of the user already has a prime token the whole call will revert due to the checks in the _mint function that if the user already has a prime token then revert. Ensure that before minting the user does not have a prime token.

4 . _accrueInterestAndUpdateScore Should Be Used

We accrue interest and update score of the users across all markets in this code block https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L211-L217 , but instead of this a simple call to _accrueInterestAndUpdateScore would be sufficient since it does the same job and would make the code more readable and streamlined.

5 . isScoreUpdated Might Not Be Updated For A Round Id

Description:

updateAlpha , updateMultiplers , addMarket when called updates a round Id through _startScoreUpdate round at L818 and score updates for these rounds take place in the function updateScores() at L200 . If for a round before updateScores() is called for a user the next round gets started ( through updateAlpha , updateMultiplers , addMarket ) then score won’t be updated for that round for the users and isScoreUpdated will always be false for that round.

6 . Capital Calculation Might Revert In Future Upgrades

Description:

Capital is calculated here https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L661 , currently vToken will be 8 decimals but other are possible in future , if in future the decimal is more than 18 , capital calculation will always revert and no scores calculated.

7 . Incorrect Comment

Description:

The comment here https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/PrimeLiquidityProvider.sol#L23 is incorrect , it should be “ the last block where tokens were accrued” instead of “The rate at which token is distributed to the Prime contract”

#0 - c4-pre-sort

2023-10-07T01:26:23Z

0xRobocop marked the issue as low quality report

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