Venus Prime - J4X'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: 34/115

Findings: 2

Award: $163.77

QA:
grade-b
Analysis:
grade-a

🌟 Selected for report: 0

🚀 Solo Findings: 0

Low

[L-01] Revert Risk in User Score Update Process

Prime: Line 200

**Issue Description: The smart contract utilizes score update rounds when certain actions occur, such as adding a new market, setting a new alpha value, or updating multipliers. The process of an update round looks like this.

  1. One of the 3 action gets taken which leads to a call to _startScoreUpdateRound()
  2. nextScoreUpdateRoundId gets increased by one and pendingScoreUpdates gets set to the amount of tokens we have.
  3. Now as there could be X amount of users the function updateScores() gets called multiple times to update each users score.
  4. For each user it's checked if this user has already been updated in the current round, if he has the token and if there are still users that need to be updated (which can be checked by decreasing pendingScoreUpdates each time a user gets updated)

However, a potential issue arises when the script is executed twice in a short timeframe. In such cases, the first execution's calls to updateScores() may not have completed when the second execution begins, potentially causing a transaction revert due to an incomplete update process.

Proof of Concept (POC):

  • Protocol has 3 users: A, B, C
  • updateScores() can update a maximum of 2 users before running out of gas
  • nextScoreUpdateRoundId = 0
  • pendingScoreUpdates = 0

Actions:

  1. A new market is added, triggering _startScoreUpdateRound()
    • nextScoreUpdateRoundId = 1
    • pendingScoreUpdates = 3
  2. Script1 calls updateUsers() for Users A and B
    • nextScoreUpdateRoundId = 1
    • pendingScoreUpdates = 1
    • isScoreUpdated[1][A, B] = true
  3. Multipliers are changed, triggering another _startScoreUpdateRound()
    • nextScoreUpdateRoundId = 2
    • pendingScoreUpdates = 3
  4. Script1 calls updateUsers() for User C
    • nextScoreUpdateRoundId = 2
    • pendingScoreUpdates = 2
    • isScoreUpdated[1][C] = true
  5. Script2 calls updateUsers() for Users A and B
    • nextScoreUpdateRoundId = 2
    • pendingScoreUpdates = 0
    • isScoreUpdated[2][A, B] = true
  6. Script2 calls updateUsers() for User C
    • nextScoreUpdateRoundId = 2
    • pendingScoreUpdates = 0
    • Revert occurs due to the failed check (pendingScoreUpdates == 0)

Recommended Mitigation Steps: To address this issue, a simple mitigation can be implemented. The contract should check if pendingScoreUpdates is not zero before allowing a new call to _startScoreUpdateRound(). This check can be added at the beginning of the _startScoreUpdateRound() function:

if(pendingScoreUpdates != 0) revert;

Additionally, a custom error named updatingRoundNotFinished could be introduced to provide better clarity on the revert reason.


[L-02] Unintended accrueTokens() Behavior on Arbitrum

PrimeLiquidityProvider: Line 249

Issue Description: The smart contract relies on block.number to perform certain operations, including the accrueTokens() function. However, on the Arbitrum network, block.number is updated only once per minute, resulting in the function accruing tokens approximately every 4 blocks instead of every block.

Recommended Mitigation Steps: If accruing tokens once per minute aligns with the protocol's management requirements, it's advisable to retain the current implementation and update the documentation to reflect this behavior. However, if the protocol should accrue tokens on every block, consider using the arbBlockNumber() function from the ArbSys to obtain the accurate block number.


[L-03] Incorrect return in claimTimeRemaining()

Prime: Line 479

Issue Description: If a user has never staked, (stakedAt[user] == 0) the function returns the STAKING_PERIOD which is incorrect as this user has not staked and will not be able to retrieve anything when the staking period has passed.

Recommended Mitigation Steps: I would recommend returning type(uint256).max as this will probably make it more clear to a user that he has not staked enough.


[L-04] Lack of Validation for Markets in calculateAPR()

Prime: Line 496

Issue Description: The calculateAPR() function, used to predict a user's APR on a provided market, does not validate whether the supplied address represents a valid market. Consequently, if an incorrect address is provided, the function may return arbitrary and inaccurate values.

Recommended Mitigation Steps: To enhance the robustness of the calculateAPR() function, consider adding a validation check to ensure that the provided address corresponds to a valid prime market. If the address does not exist as a prime market, return 0 to prevent misleading data. A validation check could be implemented as follows:

if (!markets[market].exists)
{
	return (0,0);
}

[L-05] Incorrect return from getEffectiveDistributionSpeed()

PrimeLiquidityProvider: Line 232

Issue Description: In case of the accrueTokens() function already having been called shortly before and leading to IERC20Upgradeable(token_).balanceOf(address(PLP)) == tokenAmountAccrued[token_]the getEffectiveDistributionSpeed() function incorrectly returns 0 which is not the distribution speed for the provided market. This not only results in an inaccurate calculation within Prime's _incomeDistributionYearly() function but also provides an incorrect return value to external callers of the view function.

Recommended Mitigation Steps: To address this issue, it is advisable to modify the getEffectiveDistributionSpeed() function to always return tokenDistributionSpeeds[token_], as follows:

function getEffectiveDistributionSpeed(address token_) external view returns (uint256) {
	return tokenDistributionSpeeds[token_];
}

Non-Critical (NC) Findings

[NC-01] Missing Functions in IPrime Interface

IPrime

Issue Description: The IPrime interface is lacking the inclusion of several external/public functions that are present in the Prime contract.

Recommended Mitigation Steps: If the intention is to include all externally callable functions within the IPrime interface, it should be updated to include the missing functions listed below. However, if the interface is intended to expose functions only to users, the interface can exclude some functions.

Functions missing in IPrime:

  • initialize()
  • getPendingInterests()
  • updateScores()
  • updateAlpha()
  • updateMultipliers()
  • addMarket()
  • setLimit()
  • issue()
  • claim()
  • burn()
  • togglePause()
  • 2x claimInterest()
  • updateAssetsState()
  • getAllMarkets()
  • claimTimeRemaining()
  • calculateAPR()
  • estimateAPR()
  • getInterestAccrued()

If only functions intended for the users should be included the interface is missing:

  • getPendingInterests()
  • updateScores()
  • claim()
  • 2x claimInterest()
  • getAllMarkets()
  • claimTimeRemaining()
  • calculateAPR()
  • estimateAPR()
  • getInterestAccrued()

[NC-02] isEligible Naming Non-compliance

Prime: Line 904

Issue Description: The internal function isEligible does not adhere to Solidity style guidelines for internal functions, as its name lacks a leading underscore.

Recommended Mitigation Steps: To align with best practices, rename the function to _isEligible.


[NC-03] Incorrect Documentation in Audit Description

Issue Description: The provided audit sponsor description incorrectly states that "all currently unreleased funds issued can be sent from both PrimeLiquidityProvider and ProtocolShareReserve to the Prime contract by anyone." This statement is inaccurate, as the funds of the PLP are released only when a user claims interest and the Prime token balance is insufficient. Furthermore, the releaseFunds() function of PLP can only be called by the Prime token itself.

Recommended Mitigation Steps: Revise the description/documentation to accurately reflect the process and restrictions associated with the release of funds.


[NC-04] Incorrect Documentation of the Variable totalScoreUpdatesRequired

Readme.md Line 236

Issue Description: The documentation inaccurately states that the variable responsible for tracking pending upgrades is named totalScoreUpdatesRequired, while the actual variable name is pendingScoreUpdates.

Recommended Mitigation Steps: Update the documentation to use the correct variable name, replacing totalScoreUpdatesRequired with pendingScoreUpdates.


[NC-05] Indistinct Access Control Definition in Headers

PrimeLiquidityProvider Line 116 PrimeLiquidityProvider Line 175 PrimeLiquidityProvider Line 214

Issue Description: In the PrimeLiquidityProvider contract, multiple functions are ambiguously defined with access control annotations, specifically stating either @custom:access Only Governance or @custom:access Only owner. Consistency in access control definitions is needed.

Recommended Mitigation Steps: Choose a standardized convention for function headers, either Only Governance or Only owner, and apply it consistently to all affected functions.


[NC-06] Missing Errors in Multiple Function Headers in PrimeLiquidityProvider

PrimeLiquidityProvider Line 332 PrimeLiquidityProvider Line 344

Issue Description: Several functions in the PrimeLiquidityProvider contract throw errors, but these errors are not declared in the function headers. This lack of error declaration can lead to confusion.

Recommended Mitigation Steps: For each affected function, include the relevant error declarations in the function headers to improve clarity and documentation.

_ensureTokenInitialized()

The function throws the TokenNotInitialized error but that is not declared in the header

Add this line to the header:

* @custom:error Throw TokenNotInitialized if the address does not own a  token

_ensureZeroAddress()

The function throws the InvalidArguments error but that is not declared in the header

Add this line to the header:

* @custom:error Throw InvalidArguments if the address is 0

[NC-07] Missing Errors in Multiple Function Headers in Prime

Issue Description: Several functions in the Prime contract throw errors, but these errors are not declared in the function headers. This omission may result in a lack of clarity for developers interacting with the contract.

Recommended Mitigation Steps: To enhance clarity and documentation, include the relevant error declarations in the headers of the affected functions.

constructor()

The function throws the InvalidAddress and InvalidBlocksPerYear errors but that is not declared in the header.

Add these lines to the header:

* @custom:error Throw InvalidAddress if the wbnb address is 0
* @custom:error Throw InvalidAddress if the vbnb address is 0
* @custom:error Throw InvalidBlocksPerYear if the blocks per year are 0

initialize()

The function throws the InvalidAddress error but that is not declared in the header.

Add these lines to the header:

* @custom:error Throw InvalidAddress if the xvsVault address is 0
* @custom:error Throw InvalidAddress if the xvsVaultRewardToken address is 0
* @custom:error Throw InvalidAddress if the protocolShareReserve address is 0
* @custom:error Throw InvalidAddress if the comptroller address is 0
* @custom:error Throw InvalidAddress if the oracle address is 0
* @custom:error Throw InvalidAddress if the primeLiquidityProvider address is 0

updateScores()

The function throws the NoScoreUpdatesRequired and UserHasNoPrimeToken errors but that is not declared in the header.

Add these lines to the header:

* @custom:error Throw NoScoreUpdatesRequired if the pendingScoreUpdates is 0
* @custom:error Throw NoScoreUpdatesRequired if the nextScoreUpdateRoundId is 0
* @custom:error Throw UserHasNoPrimeToken if the user doesn't have a prime token

updateMultipliers()

The function throws the MarketNotSupported error but that is not declared in the header.

Add this line to the header:

* @custom:error Throw MarketNotSupported if the market does not exist

addMarket()

The function throws the MarketAlreadyExists and InvalidVToken errors but that is not declared in the header.

Add these lines to the header:

* @custom:error Throw MarketAlreadyExists if the market is already in the prime program.
* @custom:error Throw InvalidVToken if the market does not exist. 

setLimit()

The function throws the InvalidLimit error but that is not declared in the header.

Add this line to the header:

* @custom:error Throw InvalidLimit if one of the new total values is smaller than the current value

claim()

The function throws the IneligibleToClaim and WaitMoreTime errors but that is not declared in the header.

Add these lines to the header:

* @custom:error Throw IneligibleToClaim if the user has not staked enough XVS
* @custom:error Throw WaitMoreTime if the time since the user has staked is less than the staking period. 

updateAssetsState()

The function throws the InvalidCaller, InvalidComptrollerand MarketNotSupported errors but that is not declared in the header.

Add these lines to the header:

* @custom:error Throw InvalidCaller if the function is called by someone else than the protocolShareReserve
* @custom:error Throw InvalidComptroller if the address passed as _comptroller parameter is not the comptroller
* @custom:error Throw MarketNotSupported if the vToken address is 0. 

accrueInterest()

The function throws the MarketNotSupported error but that is not declared in the header.

Add this line to the header:

* @custom:error Throw MarketNotSupported if the market is not a prime market

_mint()

The function throws the IneligibleToClaim and WaitMoreTime errors but that is not declared in the header.

Add these lines to the header:

* @custom:error Throw IneligibleToClaim if the user does not have a prime token
* @custom:error Throw InvalidLimit if all tokens of that category have already been minted

_burn()

The function throws the UserHasNoPrimeToken error but that is not declared in the header.

Add this line to the header:

* @custom:error Throw UserHasNoPrimeToken if the user has no prime token

_upgrade()

The function throws the InvalidLimit error but that is not declared in the header.

Add this line to the header:

* @custom:error Throw InvalidLimit if all tokens of that category have already been minted

_checkAlphaArguments()

The function throws the InvalidAlphaArguments error but that is not declared in the header.

Add this line to the header:

* @custom:error Throw InvalidAlphaArguments if the denominator is 0 or smaller than the numerator

[NC-08] Missing Access Restrictions in Multiple Function Headers in Prime

Issue Description: Several functions in the Prime contract are access-restricted by the AccessManager, but this access control is not mentioned in their function headers. Properly documenting access control is essential for understanding contract behavior. The affected functions are:

  • updateAlpha()
  • updateMultipliers()
  • addMarket()
  • setLimit()
  • issue()
  • burn()
  • togglePause()

Recommended Mitigation Steps: Add the following access control declaration to the headers of all affected functions:

* @custom:access Controlled by ACM

[NC-09] Bad Indexing Practices

Prime Line 63 Prime Line 74 Prime Line 82

Issue Description: In the events MintLimitsUpdated, AlphaUpdated, and MultiplierUpdated, the new values are indexed incorrectly while the old ones are indexed. Proper indexing is essential for making contract events more informative for users monitoring the contract.

Recommended Mitigation Steps: Adjust the indexing to focus on the new values rather than the old ones for the mentioned events to provide clearer event data.


[NC-10] Missing Indexing in InterestClaimed

Prime Line 91

Issue Description: The InterestClaimed event lacks indexing for the amount parameter, which can hinder users seeking specific event data.

Recommended Mitigation Steps: Add indexing to the amount parameter in the InterestClaimed event to improve event data accessibility.


[NC-11] Missing Indexing in mint

Prime Line 51

Issue Description: The mint event does not index the isIrrevocable parameter, potentially limiting the usefulness of the event data.

Recommended Mitigation Steps: Index the isIrrevocable parameter in the mint event to enhance the event's informative value.


[NC-12] Functions That Can Be Declared as pure

Prime Line 809 Prime Line 854 Prime Line 904

Issue Description: The functions _checkAlphaArguments, _xvsBalanceForScore, and isEligible do not read or modify any state variables within the contract. Therefore, they can be declared as pure for improved clarity.

Recommended Mitigation Steps: Declare the functions as pure to signify their lack of state-changing behavior and improve contract readability.


[NC-13] claimTimeRemaining() Misleading Name

Prime Line 478

Issue Description: The function claimTimeRemaining() has a misleading name, as it does not return the time remaining for users to claim their tokens but rather the time it takes until users can claim their tokens.

Recommended Mitigation Steps: Rename the function to timeUntilClaimRemaining() to accurately convey its functionality.


[NC-14] Inaccurate Naming of Error MarketAlreadyExists

Prime Line 28

The error MarketAlreadyExistsis badly named as it is used when checking for if the market is already marked as a prime market, not if the market exists.

Issue Description: The error MarketAlreadyExists is misleading, as it is used to check if a market is already marked as a prime market, not if the market exists.

Recommended Mitigation Steps: Rename the error to MarketIsAlreadyPrimeMarket to align with its actual usage.


[NC-15] Inconsistent Naming of vToken Address in Function Parameters

Issue Description: In the contract functions, there is inconsistent naming of the vToken address parameter, sometimes referred to as vToken and other times as market. Consistency in parameter naming enhances code readability.

In the following functions the address is called vToken:

  • addMarket()
  • claimInterest()
  • accrueInterest()
  • getInterestAccrued()
  • _claimInterest()
  • _executeBoost()
  • _interestAccrued()
  • _getUnderlying()
  • _incomePerBlock()
  • _incomeDistributionYearly()) While in these functions the address is called market
  • updateMultipliers()
  • accrueInterestAndUpdateScore()
  • calculateAPR()
  • _calculateScore()
  • _updateScore()

Recommended Mitigation Steps: Standardize the parameter naming to either vToken or market across all functions to improve code consistency and clarity.


[NC-16] Invalid Description for lastAccruedBlock

PrimeLiquidityProvider: Line 23

Issue Description: The description in the header for the variable lastAccruedBlock inaccurately states that it represents the rate at which tokens are distributed to the Prime contract. In reality, it signifies the block at which the token was initialized or the last block at which accrueTokens() was called.

Recommended Mitigation Steps: Revise the description to accurately convey that lastAccruedBlock represents the block at which token initialization or accrual occurred.

/// @notice The last block at which the tokens interest was accrued (or the token was initialized) mapping(address => uint256) public lastAccruedBlock;

#0 - 0xRobocop

2023-10-07T15:49:50Z

L-02 Dup of #132

#1 - c4-pre-sort

2023-10-07T15:49:56Z

0xRobocop marked the issue as sufficient quality report

Findings Information

Labels

analysis-advanced
grade-a
sufficient quality report
A-07

Awards

159.397 USDC - $159.40

External Links

Introduction

This analysis focuses on the Venus Prime audit hosted on Code4rena.

| Spec | Value | | ----------- | ----------- | | Name | Venus Prime | | Duration | 6 days | | nSLOC | 1039 |

The primary objectives of this audit are to identify potential vulnerabilities, propose mitigation strategies, and optimize gas usage within the codebase.

Methodology

The audit process was divided into three distinct phases:

Recon

In the Recon phase, I conducted a preliminary review of the codebase to gain a broad understanding of its structure and functionality. This initial pass allowed me to familiarize myself with the code before diving deeper. Additionally, I examined the provided documentation and gathered supplementary information from online sources and the audit's Discord channel.

Analysis

The Analysis phase constituted the primary focus of the audit, where I conducted an in-depth examination of the codebase. My approach involved meticulously documenting suspicious code sections, identifying minor bugs, and envisioning potential attack vectors. I explored how various attack scenarios could manifest within the code and delved into the relevant functions. Throughout this phase, I maintained communication with the protocol team to verify findings and clarify any ambiguities.

Reporting

After compiling initial notes during the Analysis phase, I refined and expanded upon these findings. I also developed test cases to complement the identified issues and integrated them into the final report. Furthermore, I generated Quality Assurance (QA) and Gas reports, alongside this comprehensive analysis.

Overview

Venus Prime comprises a system where users stake a specified amount of XVS tokens in the XVS-Vault, the native token of the Venus protocol. In return, users receive a unique token, subject to specific conditions. Notably, to obtain a token, users must stake 1000 XVS tokens for a 90-day period.

Two distinct types of tokens exist within the system: "normal" revocable tokens and irrevocable tokens. The former may be revoked (burned) if a user's stake falls below 1000 XVS, whereas the latter remains immune to such revocation. Notably, these tokens do not adhere to the ERC standard and instead employ custom implementations. Furthermore, tokens are non-transferable, and each address may possess only one token at any given time.

The codebase also incorporates the PrimeLiquidityProvider, responsible for managing liquidity within the Prime contract. It receives tokens (interest) generated by the protocol and distributes them to the Prime contract when required.

In addition to the primary contracts mentioned above, several smaller libraries and contracts contribute to the system's functionality:

  • PrimeStorage: An outsourced storage contract inherited by the Prime token.
  • Scores: A library responsible for calculating user scores.
  • FixedMath0x/FixedMath: Mathematical libraries facilitating complex mathematical operations.

The system interacts with several other contracts within the Venus protocol, with significant relevance attributed to the protocolShareReserve and xvsVault.

Detailed Analysis

Prime

The Prime token contract is the centerpiece of the system, encompassing token minting, burning, interest claiming, and APR calculation. The contract handles interest accrual and equitable distribution to users. Additionally, it maintains a record of markets designated as prime markets, each associated with an upper limit set during deployment.

Recommendations:

  1. Token Naming: Consider renaming the irrevocable tokens to better align with their actual functionality, as their potential revocation contradicts their current name. As mentioned by the host, the irrevocable tokens might be revoked by the community, when a user does not use the protocol for long. Suggested alternatives include "plus tokens" or "special tokens." If retaining the name "irrevocable," remove the functionality for others to burn these tokens, preserving the trust associated with irrevocable tokens.
  2. Market Management: Implement a mechanism allowing Governance to remove corrupted or problematic markets from the prime program. This flexibility enhances the protocol's adaptability to evolving scenarios.

PrimeLiquidityProvider

The PrimeLiquidityProvider offers a second source of liquidity for the Prime contract when it runs out of tokens and must provide users with their accrued interest.

Recommendations:

  1. Access Control: Simplify the codebase by replacing the Ownable functionalities with AccessControlManager (ACM) functionalities, ensuring consistency and reliability across the protocol.

Storage, Scores & Math

  • PrimeStorage serves as the storage setup for the Prime contract, enhancing clarity and simplifying storage examination.
  • Scores is a library responsible for calculating user scores, particularly valuable for score calculation clarity.
  • Math libraries offer secure mathematical operations, including exponentiation and logarithmic calculations.

Potential attack vectors

  1. Insufficient XVS Staking: Users may acquire tokens without staking the required amount of XVS.
  2. Premature Token Acquisition: Users may acquire tokens before the designated 90-day staking period.
  3. Unrevoked Revocable Tokens: Revocable tokens may not be revoked automatically after a user unstakes their XVS, potentially leading to unintended token behavior.
  4. Token Upgrade to Irrevocable: Users might exploit vulnerabilities to upgrade their revocable tokens to irrevocable tokens, potentially undermining the token's intended functionality.
  5. Claiming Excessive Interest: Users may exploit vulnerabilities to claim more interest than allowed.
  6. Manipulating Claimable Interest: Malicious users may decrease the claimable interest of others.
  7. Claiming Interest Without Tokens: Attackers may attempt to claim interest without owning a token.
  8. Protocol Locking/Frozen State: The protocol may become locked, frozen, or face repeated out-of-gas scenarios.
  9. Malicious Governance: Compromised Governance keys may lead to malicious actions or token draining.

Centralization Risk

The security of the Prime functionality significantly relies on the security of Governance and the AccessControlManager (ACM). If the ACM is compromised, malicious actors could exploit functions with potentially harmful consequences. For example, an attacker could burn other users' prime tokens, issue arbitrary prime tokens, pause the protocol, or conduct Denial-of-Service (DOS) attacks.

Recommendations on Centralization Risk: Mitigate this risk by safeguarding the ACM against any compromise or unauthorized access. Ensuring the ACM's integrity is paramount to prevent the exploitation of functions that could disrupt the protocol.

Code Quality

The codebase exhibits a high level of code quality. It is well-documented and adheres to best practices, encompassing custom errors/events, interfaces, and parameter checks. Variables and functions mostly comply with Solidity Style Guide standards. Moreover, the code maintains simplicity and organization, utilizing separate contracts for distinct functionalities.

Test Suite

The test suite consists of two files, one for the Prime token and another for the PrimeLiquidityProvider. It leverages the Hardhat framework and incorporates libraries such as smock, hardhat-network-helpers, chai, ethers, and typechain. Proxy and initialization occur in a single transaction, reducing front-running risk.

Recommendations on Test Suite: Some of the functions are not tested fully. Examples are:

  • Prime.updateMultipliers() is not tested at all
  • Prime.setLimit() is only used in the setup but never tested
  • Prime.getPendingInterests() return values are never tested
  • Prime.togglePause() is never tested (pausing functionality is essential and should definitely be tested)
  • Prime.claimTimeRemaining() is not tested for edge cases (user has not deposited enough/anything)
  • PrimeLiquidityProvider.getEffectiveDistributionSpeed() is not tested
  • PrimeLiquidityProvider.sweepToken() is not tested for access by someone else than the owner It is recommended to add additional tests for these functions to verify their correct functionality.

The access control manager always returns true if someone wants to access a function, so there is no testing to verify that a function reverts in the case of the caller not being allowed to access it. It is recommended to add testcases in which the ACM returns false for certain addresses.

Additionally the test suite is lacking tests in which multiple functionalities get combined to check for cross reactions, especially for the prime contract. It is recommended to add more cross functionality tests, as well as bigger testcases simulating multiple users staking/unstaking XVS as well as retrieving funds.

Comments, Documentation

The codebase features helpful comments that aid in understanding its functionality, making it accessible to new developers. NatSpec is employed to provide standardized descriptions, adhering to the Solidity Style Guide. However, adherence to NatSpec standards could be improved in some areas, as inconsistencies occasionally arise.

Recommendations on Comments and Documentation: Offer additional explanations for functions responsible for updating Scores and accruing interest, as these are critical but may not be entirely clear from existing comments. Enhanced clarity in these areas would benefit future developers working on the code.

Conclusions

The audit spanned a full six days and comprised three phases:

  • Days 1-2: Documentation review, initial code inspection, and gaining an understanding of the system's functionalities.
  • Days 3-5: In-depth code analysis, vulnerability identification, and bug hunting.
  • Day 6: Reporting findings, including bug reports and this comprehensive analysis.

Total time spent: 40 hours.

Time spent:

40 hours

#0 - c4-pre-sort

2023-10-07T05:29:32Z

0xRobocop marked the issue as sufficient quality report

#1 - c4-judge

2023-11-03T20:22:38Z

fatherGoose1 marked the issue as grade-a

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