Venus Prime - ArmedGoose'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: 64/115

Findings: 2

Award: $21.61

QA:
grade-b
Analysis:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Lines of code

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

Vulnerability details

Impact

Function addMarket does not check if added market is already initialized in PrimeLiquidityProvider. If by mistake a market is added prior to being initialized in the PLP contract, then all operations involving accrueInterestAndUpdateScore e.g. used in Comptroller will revert protocol-wide. This may effectively cause part of protocol to temporarily stop working, until the token is initialized on PLP side. Below description describes which parts are at risk in that state.

Proof of Concept

Assume a market is added to Prime.sol without being first initialized at PrimeLiquidityProvider. The steps will be following:

  • New market is added using addMarket by trusted party. At first, nothing really happens and just the market and its mappings are "initialized" at Prime.sol side.

  • As comptroller has checks on each input/output to control by using prime.accrueInterestAndUpdateScore, e.g. here and in all other functions that use accrueInterestAndUpdateScore, that means each operation on the comptroller related to this market will cause following things to happen:

  • call accrueInterestAndUpdateScore in Prime, further call subroutines:

  • call _executeBoost, pass the entry conditions in first 3 lines,

  • call accrueInterest, and finally call

  • _primeLiquidityProvider.accrueTokens(underlying) Here in line 252 there is call to _ensureTokenInitialized:

    function _ensureTokenInitialized(address token_) internal view {
        uint256 lastBlockAccrued = lastAccruedBlock[token_];

        if (lastBlockAccrued == 0) {
            revert TokenNotInitialized(token_);
        }
    }

So at this point any operation on this market, will revert, until the token is not made initialized in the PLP contract.

Moreover, aside of newly-added-but-not-initialized market related operations being unoperable, any loop that come from Prime.sol and iterates over all markets, calling _executeBoost, will encounter the same issue, so until new market is added in Prime and not initialized in PLP, following functions will revert due to being depended on accrueInterest:

  • xvsUpdated -> _accrueInterestAndUpdateScore -> _executeBoost -> accrueInterest
  • burn -> _burn -> _executeBoost -> accrueInterest
  • getInterestAccrued -> accrueInterest
  • issue -> _initializeMarkets -> accrueInterest
  • claim -> _initializeMarkets -> accrueInterest
  • updateAlpha -> accrueInterest
  • updateMultipliers -> accrueInterest

Overall, since this requires trusted party mistake the likelihood is low, but the consequences are rather significant which is temporary pause of significant part of the protocol, so rating as medium.

Tools Used

Manual approach

Include initialization of market's token in the PLP contract when adding new market to Prime.sol to avoid possiblity that protocol enters such troublesome state, or check if token is already in PLP upon adding new market to Prime.

Assessed type

DoS

#0 - 0xRobocop

2023-10-06T23:41:42Z

Consider QA

#1 - c4-pre-sort

2023-10-06T23:41:47Z

0xRobocop marked the issue as low quality report

#2 - c4-judge

2023-11-02T00:59:46Z

fatherGoose1 changed the severity to QA (Quality Assurance)

#3 - fatherGoose1

2023-11-02T01:00:22Z

QA. Helpful insight, but easily fixable by initializing the token in PLP contract.

Findings Information

Labels

analysis-advanced
grade-b
sufficient quality report
edited-by-warden
A-08

Awards

17.244 USDC - $17.24

External Links

What is prime?

XVS Prime is a loyalty programme which rewards of are dependent on participating in both XVS staking and borrowing/lending in venus protocol. The proof of being a member of the Prime program can be minted both by the protocol governance to certain users, or by users themselves if they meet the criteria. Proof of membership is under the hood increased balance in the Prime.sol contract itself. The contract is called a soulbound token, but it is not implementing any official standard, instead it is a custom contract, however it does not change anything because it is functional as it is. The entry point function for minting/revoking tokens is function xvsUpdated which takes user address as a parameter and depending on user’s situation issues or burns user tokens, among other options.

Rewarding

The most important part about Prime is ability to earn rewards for being prime holder. This is the core of the whole idea. The rewards from this program are accrued per each market added to Prime.sol and initialized in PrimeLiquidityProvider.sol, they are accrued over time and are based on score calculated on Cobb-Douglas Production function described in the official documentation for the protocol.

Under the hood, for each market there are following components of the score calculation:

  • User’s individual contribution to staking, borrowing and lending and
  • Percentage of user’s score share in all total contribution score

The system works in as I called them “micro cycles” - rewarding periods - as with each update of the score components (balances, capital, xvs, burn, mint) the rewards for past micro cycle (from last accrue timestamp to now) are accrued and accounted, then new score is calculated, and then the system starts new microcycle from current timestamp (index) to another change. This means, special attention should be paid to intervals of updating, if always new rewards are not accounted to past period for example, IF new changes of components are not introduced before accounting previous system state for past interval. Currently, the protocol mainly updates the rewarding intervals using accrueInterestAndUpdateScore function, which splits itself into two main logical operations: first is accruing interest using current score, and second is updating the score, reflecting current changes, after the interest is accrued. This order is very important, otherwise there would be massive issues with rewarding if e.g. latest changes would be accounted before clearing all outstanding accrued interest.

Aside of that, the system is somewhat centralized from technical point of view (there are roles that control vital aspects of the protocol) however as specified in the documentation it is managed by a governance. The “vital aspects” are:

  • Alpha numerator and denominator being integral part of the score calculation formula
  • Adding new markets to participate in Prime program
  • Ability to issue OG (irrevocable) tokens, or burn Prime tokens

Threat modeling

Aside of potential centralization risk, which is greatly reduced by using governance, the code has been reviewed and suitable vulnerabilities (if any found) were submitted. The threat modeling shows following areas that could be interesting for the protocol:

  • Can the user manipulate the Prime tokens, have multiple tokens, or influence Prime tokens balance in other malicious way?
  • Can user manipulate the rewards amount? Can user DoS other users?
  • Is the formula and the reward calculation implemented correctly?
  • Can user manipulate the eligibility criteria?
  • Are all entries to the system properly updating Prime calculation components properly?
  • Is it possible to put protocol in an inconsistent state, where it will stop working partially or entirely?

Overall summary

Overall the code quality is good and consistent. For me it was easiest to use manual approach since there were some compilation issues with current tests.

Time spent:

40 hours

#0 - 0xRobocop

2023-10-07T05:42:23Z

I think the analysis provided points out the most critical part of the system which is the complex score system. I do not think it provides more context about it of what the team already knows. The threat modeling section could have been more specific around the score system which probably could have help the Venus team to discover a new perspective around it (maybe a question that they did not asked during design and development).

#1 - c4-pre-sort

2023-10-07T05:42:29Z

0xRobocop marked the issue as sufficient quality report

#2 - c4-judge

2023-11-03T20:21:58Z

fatherGoose1 marked the issue as grade-b

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