Skip to content

Latest commit

 

History

History
657 lines (408 loc) · 71.2 KB

hunter_w3b-Analysis.md

File metadata and controls

657 lines (408 loc) · 71.2 KB

Analysis - Revert Lend Contest

Revert Lend Protocol

Description overview of Revert Lend Contest

Overview:

Revert Lend is a decentralized lending protocol that allows liquidity providers on Uniswap v3 to collateralize their liquidity provider (LP) positions and borrow loans.

Key Features:

  • Collateralize LP Positions: LPs can use their Uniswap v3 LP positions, represented as NFTs, as collateral to obtain loans.
  • Maintain Control: LPs retain control over their LP positions while they are collateralized, allowing them to manage and optimize their positions as needed.
  • Dynamic Interest Rates: The protocol uses a dynamic interest rate model that adjusts based on demand for loans.

How it Works:

Supplying Assets:

  • Lenders deposit assets into a lending pool and receive rTokens representing their share of the pool.
  • As borrowers repay loans with interest, the value of rTokens increases.

Borrowing Assets:

  • LPs can borrow tokens from the lending pool by collateralizing their LP positions.
  • The collateral value of the LP position is determined by the collateral factors of the assets in the pair.
  • Loans carry variable interest rates and do not require specific terms negotiation.

Collateralized Positions:

  • Collateralized LP positions are locked in the protocol until the loan is repaid.
  • LPs maintain control over their positions and can adjust price ranges or reallocate liquidity.
  • Liquidation mode is activated when the debt exceeds the borrowing capacity, allowing other accounts to clear the debt and earn a premium.

Use Cases:

  • Capital Availability: LPs can use loans to invest in other assets or protocols.
  • Leveraging Positions: LPs can reinvest loaned assets back into their LP positions, creating leverage.
  • Self-Repaying Loans: AMM positions generate yield that can be used to repay the debt, similar to self-repaying loans in other DeFi protocols.

System Overview

Scope

  • src

    1. V3Vault.sol: This contract is a Revert Lend Vault for token lending and borrowing using Uniswap V3 LP positions as collateral. It is an implementation of the ERC4626 Vault Standard and is itself an ERC20 token representing shares of the total lending pool. The V3Vault contract manages one ERC20 asset for lending and borrowing, but collateral positions can be composed of any two tokens configured with a collateralFactor greater than 0.

      • key features:

        • Lending: Users can deposit assets into the vault and earn interest. The interest rate is determined by the InterestRateModel contract and can vary based on the utilization of the asset.
        • Borrowing: Users can borrow assets from the vault by providing collateral. The amount they can borrow is determined by the collateralFactor and the value of their collateral.
        • Liquidation: If the value of a user's collateral falls below a certain threshold, their position can be liquidated.
        • Fees: The vault charges fees for borrowing and liquidation. These fees are used to cover the costs of the protocol and to incentivize liquidators.
        • Collateral Management: The contract uses Uniswap V3 LP positions as collateral. These positions can be added, removed, and transformed using the NonfungiblePositionManager contract.
      • Core Logic: The core logic of this contract revolves around the creation, management, and liquidation of loans that are collateralized with Uniswap V3 LP tokens. The contract allows users to deposit Uniswap V3 LP tokens as collateral and borrow a single ERC20 token (referred to as the "asset") against that collateral. The loans are represented as ERC721 tokens, with each token representing a unique loan position.

    2. V3Oracle.sol: The V3Oracle contract serve as an oracle for valuing Uniswap v3 LP positions in a specified token. It utilizes both Chainlink and Uniswap v3 TWAP to derive accurate price estimates.

    • Key Features:

      • Token Configuration: Allows the configuration of oracles for different tokens, including Chainlink feeds, TWAP pools, and modes of operation.
      • Value Calculation: Provides a method to calculate the value of a Uniswap v3 LP position in a specified token, considering both current prices and uncollected fees.
      • Price Verification: Verifies the price derived from the primary oracle against a secondary oracle to ensure accuracy.
      • Emergency Fallback: Includes an emergency fallback mode that allows the emergency admin to take special actions without a timelock.
    • Implementation Details:

      • Token Configuration:
        • The contract maintains a mapping of tokens to their respective configurations, including Chainlink feeds, TWAP pools, and modes of operation.
        • The setTokenConfig function allows the owner to set or update these configurations.
      • Value Calculation:
        • The getValue function calculates the value of a Uniswap v3 LP position in a specified token.
        • It uses the _getReferenceTokenPriceX96 function to obtain the price of the reference token (typically USDC or another stablecoin) using both Chainlink and TWAP.
        • The price of the token in which the value is requested is then calculated using the reference token price and the TWAP price of the token pair.
      • Price Verification:
        • The _getReferenceTokenPriceX96 function uses both Chainlink and TWAP to derive the reference token price.
        • If the mode is set to CHAINLINK_TWAP_VERIFY or TWAP_CHAINLINK_VERIFY, it verifies the price against the secondary oracle.
      • Emergency:
        • The emergencyAdmin address can be set by the owner.
        • The emergency admin has the authority to call special emergency actions without a timelock, such as updating oracle configurations or disabling the oracle.
    • Additional Features:

      • Max Pool Price Difference: Allows the owner to set a maximum allowable difference between the pool price and the derived oracle pool price.
      • Breakdown of Position: Provides a method to obtain a breakdown of a Uniswap v3 position, including tokens, fee tier, liquidity, and current amounts.
    1. InterestRateModel.sol: The InterestRateModel contract calculate interest rates for both borrowing and supplying assets in a lending protocol.
    • Key Features:

      • Interest Rate Calculation: Provides methods to calculate both borrow and supply interest rates based on the current cash and debt levels in the protocol.
      • Utilization Rate: Calculates the utilization rate, which represents the ratio of debt to available cash.
    • Functionality:

      • Interest Rate Calculation:
        • The getRatesPerSecondX96 function calculates the borrow and supply interest rates per second, multiplied by Q96.
        • It first calculates the utilization rate using the getUtilizationRateX96 function.
        • Based on the utilization rate, it applies the appropriate interest rate formula, considering the base rate, multiplier, and jump multiplier.
      • Utilization Rate:
        • The getUtilizationRateX96 function calculates the utilization rate by dividing the current debt by the sum of current cash and debt.
  • automators

    1. AutoExit.sol: The AutoExit.sol contract is automate the execution of limit orders or stop-loss orders for Uniswap v3 positions. It allows a designated operator to execute these orders when certain conditions are met, such as reaching a specific tick value.

      • Key Features:

        • Automated Order Execution: Provides a mechanism for automatically executing limit orders or stop-loss orders for Uniswap v3 positions.
        • Configuration: Allows users to configure the conditions under which orders should be executed, including the trigger tick values and slippage tolerance.
        • Reward System: Includes a reward system that compensates the operator for executing orders.
      • Functionality:

        • Order Configuration:

          • Users can configure orders for specific Uniswap v3 positions using the configToken function.
          • The configuration includes parameters such as the trigger tick values, whether to swap or remove liquidity, and the maximum reward percentage for the operator.
        • Order Execution:

          • The execute function is used to execute orders.
          • It first checks if the operator is authorized and if the order is configured correctly.
          • It then collects fees and liquidity from the position and executes the order either as a swap or a liquidity removal.
          • The operator receives a reward for executing the order.
        • Reward System:

          • The reward system allows the operator to receive a percentage of the fees or liquidity collected from the position.
          • The maximum reward percentage is configurable for each order.
      • Additional Features:

        • Token Transfers: Handles the transfer of tokens to the user after the order is executed.
        • Liquidity Removal: Supports the removal of full liquidity from the position, including collected fees.
    2. Automator.sol: The Automator contract is a base contract for automating the execution of orders for Uniswap v3 positions. It provides a framework for managing operators, vaults, and withdrawal addresses, as well as configuring TWAP parameters for order validation.

      • Key Features:

        • Operator and Vault Management: Allows the owner to activate or deactivate operators and vaults, which are responsible for executing and withdrawing funds from positions, respectively.
        • Withdrawal: Includes methods for withdrawing token balances and ETH balances to a specified address.
        • Order Validation: Implements a mechanism to validate if a swap can be executed based on oracle parameters, such as TWAP and maximum price difference.
      • Functionality:

        • Operator and Vault Management:
          • The setOperator and setVault functions allow the owner to control which addresses can execute orders and withdraw funds.
        • Withdrawal:
          • The withdrawBalances function allows the withdrawer to withdraw token balances, and the withdrawETH function allows the withdrawer to withdraw ETH balances.
        • Order Validation:
          • The _validateSwap function checks if a swap can be executed based on the current pool price and oracle parameters. It calculates the minimum amount out and reverts if the price difference exceeds the maximum allowed.
          • The _hasMaxTWAPTickDifference function checks if the current tick is within a specified range of the TWAP tick, which is calculated from the pool's history.
          • The _getTWAPTick function attempts to retrieve the TWAP tick from the pool's history.
      • Additional Features:

        • Liquidity Removal and Fee Collection: Includes a helper function, _decreaseFullLiquidityAndCollect, to remove full liquidity from a position and collect any accrued fees.
        • Token Transfers: Implements a _transferToken function to transfer tokens or unwrap WETH and send ETH.
  • transformers

    1. AutoCompound.sol: The AutoCompound contract allows operators to execute auto-compounding operations, which involve collecting fees, swapping tokens, and reinvesting the proceeds back into the position.

      • Key Features:

        • Auto-Compounding: Implements a mechanism for operators to auto-compound positions, increasing their liquidity and earning fees.
        • Swap Execution: Includes logic for executing swaps based on TWAP oracle parameters to ensure price protection.
        • Reward Management: Allows the owner to adjust the reward percentage for auto-compounding.
      • Implementation Details:

      • Auto-Compounding:

        • The execute function is the entry point for auto-compounding. It collects fees, performs a swap if necessary, and reinvests the proceeds back into the position.
        • The ExecuteParams struct defines the parameters for auto-compounding, including the token ID, swap direction, and swap amount.
        • The ExecuteState struct is used to track the state of the auto-compounding process.
      • Swap Execution:

        • The _poolSwap function is used to execute swaps based on TWAP oracle parameters.
        • The _validateSwap function from the Automator contract is used to ensure that the swap can be executed within the specified price range.
      • Reward Management:

        • The totalRewardX64 variable represents the total reward percentage for auto-compounding.
        • The setReward function allows the owner to adjust the reward percentage.
      • Additional Features:

        • Leftover Token Withdrawal: Allows the owner of a position to withdraw any leftover tokens that are not part of the auto-compounding process.
        • Balance Management: Tracks token balances for each position and updates them based on auto-compounding operations.
    2. AutoRange.sol: Allows operators to execute range adjustments, which involve creating a new position with a different range while maintaining the same liquidity and fees.

      • Key Features:

        • Range Adjustment: Implements a mechanism for operators to adjust the range of configured positions.
        • Swap Execution: Includes logic for executing swaps based on TWAP oracle parameters to ensure price protection.
        • Position Configuration: Allows operators to configure positions with specific range parameters and reward settings.
      • Functionality:

        • Range Adjustment:
          • The execute function is the entry point for range adjustment. It collects fees, performs a swap if necessary, and creates a new position with the adjusted range.
          • The ExecuteParams struct defines the parameters for range adjustment, including the token ID, swap direction, swap amount, and reward percentage.
          • The ExecuteState struct is used to track the state of the range adjustment process.
        • Swap Execution:
          • The _routerSwap function is used to execute swaps based on TWAP oracle parameters.
          • The _validateSwap function from the Automator contract is used to ensure that the swap can be executed within the specified price range.
        • Position Configuration:
          • The PositionConfig struct defines the configuration parameters for positions.
          • The configToken function allows operators to configure positions with specific range parameters and reward settings.
    3. LeverageTransformer.sol: This contract to add functionality for leveraging and deleveraging Uniswap v3 positions directly within a single transaction. It allows operators to execute leverage operations, which involve borrowing tokens to increase position size, and deleverage operations, which involve reducing position size and repaying borrowed tokens.

      • Key Features:

        • Leverage Up: Implements a mechanism for operators to leverage up positions by borrowing tokens and using them to increase liquidity.
        • Leverage Down: Implements a mechanism for operators to deleverage positions by reducing liquidity and repaying borrowed tokens.
        • Swap Execution: Includes logic for executing swaps based on TWAP oracle parameters to ensure price protection.
      • Functionality:

        • Leverage Up:
          • The leverageUp function is the entry point for leverage up operations. It borrows tokens from the vault, swaps them to the desired tokens, and adds liquidity to the position.
          • The LeverageUpParams struct defines the parameters for leverage up operations, including the token ID, borrow amount, swap parameters, and recipient for leftover tokens.
        • Leverage Down:
          • The leverageDown function is the entry point for leverage down operations. It removes liquidity from the position, collects fees, swaps tokens to the desired token, and repays the borrowed tokens to the vault.
          • The LeverageDownParams struct defines the parameters for leverage down operations, including the token ID, liquidity to remove, fee collection parameters, swap parameters, and recipient for leftover tokens.
        • Swap Execution:
          • The _routerSwap function from the Swapper contract is used to execute swaps based on TWAP oracle parameters.
          • The _validateSwap function from the Swapper contract is used to ensure that the swap can be executed within the specified price range.
    4. V3Utils.sol: This contract V3Utils is a utility contract for Uniswap V3 positions. It's a stateless and ownerless contract, designed to facilitate various operations on Uniswap V3 positions, such as swapping, adding or removing liquidity, and collecting fees. It does not hold any ERC20 or NFTs.

      • Key Features:

        • Swap and Mint: This feature allows users to swap tokens and mint new NFTs representing Uniswap V3 positions. It supports both ERC20 and Ether swaps, and can handle multiple swaps in one transaction.

        • Increase Liquidity: Users can increase liquidity in their existing Uniswap V3 positions. The contract supports both ERC20 and Ether deposits, and can handle multiple deposits in one transaction.

        • Collect Fees: Users can collect fees accrued from their Uniswap V3 positions. The contract ensures that the collected fees match the expected amount.

        • Permit2 Integration: The contract uses the Permit2 contract for handling permissions. This allows users to grant permissions to the contract to perform actions on their behalf.

      • Core Logic: The contract revolves around the execute function and the various swap functions. The execute function performs a set of instructions on a provided NFT, while the swap functions handle swapping tokens and adding liquidity. The contract also includes various helper functions for handling permissions, preparing token transfers, and checking token balances.

      • Additional Features:

        The contract includes various additional features, such as support for Ether swaps and deposits, handling of fee-on-transfer tokens, and unwrapping of WETH. The contract also emits various events, such as CompoundFees, ChangeRange, WithdrawAndCollectAndSwap, and SwapAndMint, to log its actions.

  • utils

    1. FlashloanLiquidator.sol: This contract, FlashloanLiquidator, is a helper contract that allows atomic liquidation and needed swaps by using Uniswap V3 Flashloan.

      • Key Features:

        • Flashloan Liquidation: This feature allows users to liquidate loans using Uniswap V3 Flashloans. The contract supports both ERC20 and Ether loans, and can handle multiple swaps in one transaction.

        • Swapper Integration: The contract uses the Swapper contract for handling token swaps. This allows users to swap tokens as part of the liquidation process.

      • Core Logic: The contract core logic is liquidate function and the uniswapV3FlashCallback function. The liquidate function initiates the liquidation process by requesting a flashloan from Uniswap V3. The uniswapV3FlashCallback function is then called by Uniswap V3 to perform the actual liquidation and swaps. The contract also includes various helper functions for handling permissions, preparing token transfers, and checking token balances.

    2. Swapper.sol: This abstract contract that provides base functionality to do swaps with different routing protocols.

      • Key Features:

        • Swap Functionality: This feature allows users to swap tokens using different routing protocols. The contract supports both ERC20 and Ether swaps, and can handle multiple swaps in one transaction.

        • Router Integration: The contract uses different routing protocols, such as 0x Exchange Proxy and Uniswap Universal Router, for handling token swaps. This allows users to swap tokens using the most efficient route.

      • Additional Features: The contract includes various additional features, such as support for Ether swaps, handling of fee-on-transfer tokens, and unwrapping of WETH. The contract also emits various events, such as Swap, to log its actions.

Invariants Generated

  1. V3Vault.sol

    1. Collateral factors for tokens must be less than or equal to MAX_COLLATERAL_FACTOR_X32.

    2. Reserve factor must be less than Q32.

    3. Liquidation penalty must be between MIN_LIQUIDATION_PENALTY_X32 and MAX_LIQUIDATION_PENALTY_X32.

    4. Reserve protection factor must be greater than or equal to MIN_RESERVE_PROTECTION_FACTOR_X32.

    5. Daily increase limits must be less than the respective MAX_DAILY_LIMIT constants.

    6. Interest rates returned from the rate model must be non-negative.

    7. Total debt shares can never exceed the theoretical backing from collateral.

    8. Collateral value used for any single token cannot exceed its configured limit factor.

    9. Withdrawals cannot exceed a user's balance, pending approvals, or total availability.

    10. Repays and borrows cannot cause a loan's debt to become negative.

    11. Liquidation penalties must leave sufficient value for the liquidator.

    12. Reserve amounts withdrawn respect the protection factor threshold.

    13. Owned token counts are consistent with the mapping indexes.

  2. V3Oracle.sol

    1. feedConfigs mapping should only contain valid configurations:

      • TokenConfig.feed should be a valid Chainlink aggregator address.
      • TokenConfig.maxFeedAge should be a reasonable value to ensure the Chainlink price is not stale.
      • TokenConfig.pool should be a valid Uniswap V3 pool address with the correct token pair.
      • TokenConfig.twapSeconds should be a reasonable value for the TWAP calculation.
      • TokenConfig.mode should be a valid mode (not NOT_SET).
      • TokenConfig.maxDifference should be greater than or equal to MIN_PRICE_DIFFERENCE.
    2. The maxPoolPriceDifference should always be greater than or equal to MIN_PRICE_DIFFERENCE.

    3. The emergencyAdmin address should be a valid Ethereum address when set.

    4. The referenceToken and chainlinkReferenceToken should be valid ERC20 token addresses.

    5. For any token configured with Mode.CHAINLINK_TWAP_VERIFY or Mode.TWAP_CHAINLINK_VERIFY, the price difference between the Chainlink oracle and the TWAP oracle should not exceed TokenConfig.maxDifference.

    6. The getValue function should revert if:

      • The position tokenId is invalid or doesn't exist.
      • Any of the involved tokens (token0, token1, or the requested token) are not configured in the feedConfigs mapping.
      • The derived pool price difference exceeds the maxPoolPriceDifference.
    7. The getPositionBreakdown function should return the correct token0, token1, fee tier, liquidity, current amounts, and uncollected fees for a valid position tokenId.

    8. The _getReferenceTokenPriceX96 function should return the correct price for the given token based on the configured mode, and the Chainlink and TWAP oracles should be used as specified by the mode.

    9. The _getTWAPPriceX96 function should correctly calculate the TWAP price for the token based on the configured pool and TWAP period.

    10. The _getChainlinkPriceX96 function should correctly retrieve the latest Chainlink price for the token and revert if the price is stale or invalid.

  3. Automator.sol

    1. operators[address] and vaults[address] should only be true for valid addresses controlled by the owner.
    2. TWAPSeconds should always be greater than or equal to MIN_TWAP_SECONDS (60).
    3. maxTWAPTickDifference should always be less than or equal to MAX_TWAP_TICK_DIFFERENCE (200).
    4. The tokenId passed to _validateOwner should be owned by either msg.sender or the vault address.
    5. The amountOutMin returned by _validateSwap should be less than or equal to the actual amount out calculated by the swap.
    6. The currentTick returned by _validateSwap should match the current tick of the Uniswap V3 pool.
    7. The sqrtPriceX96 and priceX96 returned by _validateSwap should match the current price in the Uniswap V3 pool.
    8. The twapTick returned by _getTWAPTick should be within the maxTWAPTickDifference range of the currentTick.
    9. The sum of feeAmount0 and feeAmount1 returned by _decreaseFullLiquidityAndCollect should be less than or equal to the sum of amount0 and amount1.
    10. The amount0 and amount1 returned by _decreaseFullLiquidityAndCollect should match the amounts actually collected from the Uniswap V3 pool.
    11. The ETH balance of the contract should only change as a result of weth.withdraw or to.call in _transferToken.
  4. AutoCompound.sol

    • Invariant 1: The total reward is always less than or equal to 2%.

      • The totalRewardX64 variable is initialized to MAX_REWARD_X64, which is 2% of Q64.
      • The setReward function can only decrease the totalRewardX64 variable, not increase it.
    • Invariant 2: The amount of fees charged for each compound is always less than or equal to the amount of reward added to the protocol balance.

      • The amount of fees charged is calculated as rewardX64 * compounded0 / Q64 and rewardX64 * compounded1 / Q64, where rewardX64 is the total reward, compounded0 is the amount of token 0 added to the position, and compounded1 is the amount of token 1 added to the position.
      • The amount of reward added to the protocol balance is calculated as rewardX64 * maxAddAmount0 / Q64 and rewardX64 * maxAddAmount1 / Q64, where maxAddAmount0 is the maximum amount of token 0 that can be added to the position, and maxAddAmount1 is the maximum amount of token 1 that can be added to the position.
      • Since compounded0 and compounded1 are always less than or equal to maxAddAmount0 and maxAddAmount1, respectively, the amount of fees charged is always less than or equal to the amount of reward added to the protocol balance.

Approach Taken-in Evaluating Revert Lend Protocol

Accordingly, I analyzed and audited the subject in the following steps;

  1. Core Protocol Contract Overview:

    I focused on thoroughly understanding the codebase and providing recommendations to improve its functionality. The main goal was to take a close look at the important contracts and how they work together in the Revert Lend.

    I start with the following contracts, which play crucial roles in the Revert Lend:

              V3Vault.sol
              V3Oracle.sol
              AutoExit.sol
              Automator.sol
              AutoCompound.sol
              AutoRange.sol
              LeverageTransformer.sol
    

    I started my analysis by examining the intricate structure and functionalities of the Revert Lend protocol. The V3Vault contract, the core component of the protocol, manages the lending and borrowing of assets using Uniswap V3 LP positions as collateral. It implements the ERC4626 Vault Standard and is itself an ERC20 token representing shares of the total lending pool. The V3Oracle contract serves as an oracle for valuing Uniswap v3 LP positions in a specified token, utilizing both Chainlink and Uniswap v3 TWAP to derive accurate price estimates. The InterestRateModel contract calculates interest rates for both borrowing and supplying assets in the protocol.

  2. Documentation Review:

    Then went to Review these documentations for a more detailed and technical explanation of the Revert Lend.

  3. Compiling code and running provided tests:

  4. Manuel Code Review In this phase, I initially conducted a line-by-line analysis, following that, I engaged in a comparison mode.

    • Line by Line Analysis: Pay close attention to the contract's intended functionality and compare it with its actual behavior on a line-by-line basis.

    • Comparison Mode: Compare the implementation of each function with established standards or existing implementations, focusing on the function names to identify any deviations.

Codebase Quality

Overall, I consider the quality of the Revert Lend protocol codebase to be Good. The code appears to be mature and well-developed. We have noticed the implementation of various standards adhere to appropriately. Details are explained below:

Codebase Quality Categories Comments
Architecture & Design The protocol features a modular design, segregating functionality into distinct contracts (e.g., V3Vault, V3Oracle, Automator, LeverageTransformer, V3Utils) for clarity and ease of maintenance.
Error Handling & Input Validation Functions check for conditions and validate inputs to prevent invalid operations, though the depth of validation (e.g., for edge cases transactions) would benefit from closer examination.
Code Maintainability and Reliability The contracts are written with emphasis on sustainability and simplicity. The functions are single-purpose with little branching and low cyclomatic complexity. The protocol includes a novel mechanism for collecting fees that offers an incentive for this work to be done by outside actors,thereby removing the associated complexity.
Code Comments The contracts are accompanied by comprehensive comments, facilitating an understanding of the functional logic and critical operations within the code. Functions are described purposefully, and complex sections are elucidated with comments to guide readers through the logic. Despite this, certain areas, particularly those involving intricate mechanics or tokenomics, could benefit from even more detailed commentary to ensure clarity and ease of understanding for developers new to the project or those auditing the code.
Testing The contracts exhibit a commendable level of test coverage 80% but with aim to 100% for indicative of a robust testing regime. This coverage ensures that a wide array of functionalities and edge cases are tested, contributing to the reliability and security of the code. However, to further enhance the testing framework, the incorporation of fuzz testing and invariant testing is recommended. These testing methodologies can uncover deeper, systemic issues by simulating extreme conditions and verifying the invariants of the contract logic, thereby fortifying the codebase against unforeseen vulnerabilities.
Code Structure and Formatting The codebase benefits from a consistent structure and formatting, adhering to the stylistic conventions and best practices of Solidity programming. Logical grouping of functions and adherence to naming conventions contribute significantly to the readability and navigability of the code. While the current structure supports clarity, further modularization and separation of concerns could be achieved by breaking down complex contracts into smaller, more focused components. This approach would not only simplify individual contract logic but also facilitate easier updates and maintenance.
Strengths The key strengths of the Revert Lend protocol are that it provides a robust, configurable and risk-managed framework for collateralized lending and borrowing using Uniswap positions, through features like dynamic interest rates, reserve management, configurable tokens, transformations, and daily/emergency controls.
Documentation The NatSpec is mostly complete for all external functions,and there are helpful inline comments throughout. However, there currently is no external documentation for users or integrators.The external documentation for users or integrators should be created to provide a comprehensive understanding of the contract's functionality, purpose, and interaction methods. This documentation should include detailed explanations of the contract's features, how to use and integrate its functions, as well as any relevant use cases and examples. Providing clear and thorough external documentation will ensure that users and integrators have a complete understanding of the contract and can effectively utilize its capabilities.

Architecture

System Workflow

  1. The V3Vault contract manages token lending/borrowing using Uniswap V3 LP positions as collateral. It implements the IERC4626 Vault standard and itself is an ERC20 token representing shares of the total lending pool.

  2. Users can deposit tokens into the vault in exchange for vault shares, which represents their portion of the total lending pool. This increases the total assets available for lending.

  3. Borrowers can use LP positions (Uniswap V3 NFTs) as collateral to borrow the vault's underlying asset token. The amount that can be borrowed is determined by the collateral value of the position.

  4. Interest accrues on borrowed assets and lent assets separately. The interest rate model contract calculates utilization-based interest rates taking into account the amount of assets supplied vs borrowed.

  5. LP position collateral values and borrower debt values fluctuate with market prices via the oracle. If a position's collateral drops below a threshold, it becomes liquidatable.

  6. In the event of liquidation, the liquidator can pay off the debt and receive part of the position's collateral value. Any shortfall is socialized across vault share holders.

  7. Users can withdraw lent assets or redeem vault shares in exchange for the underlying asset tokens at the current exchange rates.

  8. The Vault holds underlying asset tokens and manages total supply, debt levels, collateral configurations etc. Other helper contracts like the oracle, interest model and liquidator help facilitate the core functionality.

File Name Core Functionality Technical Characteristics Importance and Management
V3Vault.sol The core functionality for V3Vault contract includes creating new collateralized positions, borrowing assets, repaying borrowed tokens, liquidating positions, and managing reserves and interest rates The technical characteristics involve using various libraries and interfaces such as Uniswap V3, OpenZeppelin, and ERC721. The V3Vault's importance lies in providing a lending and borrowing solution while utilizing Uniswap V3 LP positions as collateral. The management of the contract is done through various admin functions, including setting limits, configuring transformer contracts, and updating token configurations.
V3Oracle.sol Provides oracle prices for Uniswap v3 LP positions in a specified token. Uses both Chainlink and Uniswap v3 TWAP for price calculation and offers emergency fallback mode for price verification. Critical for accurately calculating the value of Uniswap v3 LP positions in V3Vault.Configurable token configurations to specify feed sources and verification modes, customizable max pool price difference to prevent price manipulation attacks, emergency admin can take special actions without timelock.
InterestRateModel.sol Calculates borrow and supply interest rates based on the utilization rate. Interest rates are multiplied by Q96 for precision.Utilization rate is calculated as debt divided by the sum of cash and debt.Interest rates are adjusted based on a kink point in the utilization rate. Crucial for determining the interest paid by borrowers and earned by suppliers in the Vault.Interest rate values (base rate, multiplier, jump multiplier, kink) can be updated by the owner.
AutoExit.sol Automates the execution of limit orders or stop-loss orders for Uniswap V3 positions. Uses a revert-controlled bot (operator) to execute optimized swaps using external swap routers.Positions are configured with trigger ticks, swap parameters, and reward percentages. Allows users to set automated exit strategies for their Uniswap V3 positions, reducing the risk of losses or missed opportunities. Positions can be configured and executed by the operator account.Position configurations include trigger ticks, swap parameters, and reward percentages.
Automator.sol Automates the execution of token withdrawals, NFT liquidity decreases, and token collections for Uniswap V3 positions. Uses a revert-controlled bot (operator) to execute optimized swaps using external swap routers.Positions are configured with trigger ticks, swap parameters, and reward percentages. Validates swap prices using a TWAP and maximum tick difference. Allows users to automate the management of their Uniswap V3 positions, reducing the risk of losses or missed opportunities.Operators can be activated/deactivated by the owner. Vaults can be activated/deactivated by the owner. The withdrawer address can be set by the owner. TWAP configuration can be set by the owner.
AutoCompound.sol Automates the compounding of Uniswap V3 positions by adjusting token balances and swapping tokens to maintain a target reward percentage. Positions are configured with trigger ticks, swap parameters, and reward percentages. Validates swap prices using a TWAP and maximum tick difference. Allows for the withdrawal of leftover token balances and accumulated protocol fees. Allows users to optimize their Uniswap V3 positions by automatically adjusting token balances and swapping tokens to maintain a target reward percentage. Reduces the risk of losses or missed opportunities by automating the compounding process. Operators can be activated/deactivated by the owner. Vaults can be activated/deactivated by the owner. The withdrawer address can be set by the owner. The total reward percentage can be lowered by the owner.
AutoRange.sol Automates the adjustment of Uniswap V3 positions by changing the range of the position (lower and upper ticks). Positions are configured with trigger ticks, swap parameters, and reward percentages.Validates swap prices using a TWAP and maximum tick difference. Allows for the configuration of positions with a minimum reward percentage. Supports both direct and vault-mediated execution. Allows users to optimize their Uniswap V3 positions by automatically adjusting the range to capture price movements.Reduces the risk of losses or missed opportunities by automating the adjustment process.
LeverageTransformer.sol Facilitates leverage and deleverage operations on Uniswap V3 positions directly within a single transaction. Supports both borrowing and repaying of assets. Allows for swapping of borrowed assets to increase liquidity. Provides flexibility in setting swap parameters and minimum amounts. Integrates with Vaults for seamless execution. Only the Vault contract can call the leverageUp and leverageDown functions. The Vault contract is responsible for managing the underlying assets and positions. The owner of the Vault can set parameters such as the leverage ratio and swap settings.
V3Utils.sol Its core functionality includes executing instructions on provided NFTs (like changing range, withdrawing and swapping, or compounding fees), managing permissions, and swapping tokens The technical characteristics involve using SafeCast for uint256, EIP712 permits for secure execution of instructions, and the IERC721Receiver interface for handling NFT transfers. The importance of this contract lies in its ability to manage and automate complex processes related to Uniswap V3 positions, making it easier for users and developers to interact with the protocol
FlashloanLiquidator.sol Its core functionality is to liquidate loans using flash loans, execute swaps, and transfer the lent amount and fees back to the pool, while returning any leftover tokens to the liquidator. The technical characteristics include using custom structs (FlashCallbackData, LiquidateParams) for data management and the IUniswapV3FlashCallback interface for flash loan callbacks. The importance of this contract is to facilitate seamless liquidations and swaps within the Uniswap V3 ecosystem, and its management is handled through the liquidate and uniswapV3FlashCallback functions, which ensure proper execution of liquidations and swaps while prioritizing security and efficiency.
Swapper.sol Its core functionality includes executing swaps, managing token approvals, and handling swap callbacks. The contract's technical characteristics involve using SafeERC20 for secure token transfers, custom structs (ZeroxRouterData, UniversalRouterData, RouterSwapParams, PoolSwapParams) for data management, and the IUniswapV3SwapCallback interface for swap callbacks. The importance of this Swapper contract lies in facilitating swaps within the Uniswap V3 ecosystem, and its management is handled through functions like _routerSwap, _poolSwap, and uniswapV3SwapCallback, which ensure proper execution of swaps and callbacks while prioritizing security and efficiency.

Systemic Risks, Centralization Risks, Technical Risks & Integration Risks

  • V3Vault.sol

    1. Centralization Risks: The V3Vault.sol contract has an owner who has the power to set various parameters, including the emergency admin, interest rate model, and oracle. If the owner's private key is compromised, it could lead to unauthorized changes in the contract, potentially leading to a loss of funds. Additionally, the contract has a function setTransformer which allows the owner to set a transformer contract. If a malicious contract is set as the transformer, it could potentially steal funds.

    2. Technical Risks:

      • Complex logic for interest calculation, collateral checks etc. increase risk of bugs.

      • Values like collateral factors are configured through the contract. Misconfiguration could lead to issues.

    3. Integration Risks:

      • Adding/removing tokens/strategies also introduces risks from changing integrations.

      • Interfacing with external contracts like Uniswap, permit increases third party risks. Bugs in linked contracts impact this one.

  • V3Oracle.sol

    1. Systemic Risks

      • Circular dependencies between token configurations: The contract allows token configurations to be set using the setTokenConfig function. This function accepts various parameters, including a reference pool for TWAP calculations. However, there is no inherent check to prevent circular dependencies between token configurations. For example, Token A's reference pool could depend on the price of Token B, while Token B's reference pool could depend on the price of Token A. This circular dependency could lead to unpredictable behavior or inaccurate price calculations when using the _getReferenceTokenPriceX96 function.

      To mitigate this risk, it's essential to ensure that token configurations are set up in a way that avoids circular dependencies between reference pools. This can be achieved by carefully designing the token configuration process, either by implementing additional checks within the contract or through off-chain validation before submitting token configurations.

      • Liquidity risk: The contract relies on liquidity pools to provide liquidity for trading. If these pools are not sufficiently liquid, it could be difficult to execute trades or obtain fair prices.
    2. Centralization Risks

      • Owner control: The contract has an owner who has the power to set various parameters, including the emergency admin, the max pool price difference, and the token configurations. If the owner's private key is compromised, it could lead to unauthorized changes in the contract, potentially leading to a loss of funds.

      • Emergency admin control: The contract has an emergency admin who has the power to update the oracle mode for a given token.

    3. Integration Risks

      • Third-party risk: The contract integrates with several third-party services, such as oracles and liquidity pools. If these services are compromised or malfunction, it could impact the functionality of the contract.

      • Configuration errors: The contract has several configurable parameters, such as the max feed age, the TWAP period, and the max price difference. If these parameters are not set correctly, it could lead to incorrect pricing of LP positions. Additionally, the contract allows for updating the oracle mode for a given token. If the oracle mode is not set correctly, it could lead to incorrect pricing of LP positions.

  • InterestRateModel.sol

    1. Systemic Risks

      • Calculation of interest rates: The getRatesPerSecondX96 function calculates both the borrow and supply rates based on the utilization rate, which is determined by the ratio of debt to available cash. If the contract's calculation of utilization rate is flawed or manipulated, it could result in incorrect interest rates being set. This could have significant consequences for the wider system, as it could lead to either borrowers paying too much interest or lenders receiving too little interest. If this contract is used as a reference for interest rates in other parts of the protocol, the impact of a flawed utilization rate calculation could be amplified.
    2. Centralization Risks:

      • The contract is owned by a single entity, which has the power to update the interest rate values. This centralization of control could be exploited by a malicious actor who gains control of the owner's account, or by the owner themselves if they act in their own interests rather than the interests of the system as a whole.
    3. Technical Risks:

      • The contract's setValues function does not include any checks to ensure that the new interest rate values are within acceptable bounds. This could allow a malicious actor to set the interest rates to arbitrarily high or low values, which could have significant consequences for users and other contracts that rely on accurate interest rate calculations.
  • AutoExit.sol

    1. Systemic Risks:

      • Cascading failures: The contract is designed to automatically remove or swap positions when they reach a certain tick, which could lead to cascading liquidations in the event of a sudden market crash. This might amplify market volatility and negatively impact the overall stability of the DeFi ecosystem.

      • Interdependencies: The contract relies on external contracts, such as the INonfungiblePositionManager, swap routers, and token contracts. If any of these contracts have vulnerabilities or experience issues, the AutoExit contract may also be affected, leading to potential unintended consequences.

    2. Centralization Risks:

      • Operator dependency: The contract relies on a revert-controlled bot (operator) for executing optimized swaps using an external swap router. This introduces centralization risks, as the operator could potentially manipulate or censor transactions, or become a single point of failure if it goes offline.

      • Withdrawer dependency: The contract has a withdrawer address that can withdraw accumulated fees. If this address is controlled by a centralized entity, it could lead to centralization risks and potential censorship.

    3. Technical Risks:

      • Incorrect tick trigger configuration: The contract allows users to configure a position with a token0TriggerTick and a token1TriggerTick. If these values are not set correctly, the position might not be executed as intended. For example, if token0TriggerTick is greater than or equal to token1TriggerTick, the contract will revert with an "InvalidConfig" error when attempting to configure the position. This could lead to user confusion or unintended position behavior. To mitigate this risk, ensure that users understand how to correctly configure tick triggers and implement appropriate validation checks when setting these values.
    4. Integration Risks:

      • Swap router compatibility: The AutoExit contract uses external swap routers (ZeroXRouter and UniversalRouter) for executing swaps. If these routers experience downtime, have vulnerabilities, or introduce incompatible changes, the AutoExit contract's functionality could be affected. To mitigate this risk, ensure that the swap routers are thoroughly audited, tested, and monitored for any changes or issues. Additionally, consider implementing a fallback mechanism to use alternative swap routers in case of integration issues.
  • Automator.sol

    1. Systemic Risks

      • Cascading liquidations: The Automator contract is designed to manage liquidity positions and perform swaps. In the event of a sudden market crash, the contract might initiate a large number of liquidations or swaps, which could amplify market volatility and negatively impact the overall stability of the DeFi.
    2. Technical Risks

      • Incorrect TWAP configuration: The contract allows the owner to set the TWAP configuration (TWAPSeconds and maxTWAPTickDifference). If these parameters are set incorrectly, it could lead to inaccurate price calculations or invalid TWAP checks, potentially causing unintended behavior in the contract.
    3. Integration Risks

      • WETH unwrapping: The contract supports unwrapping WETH to ETH using the _transferToken function. If there are any issues with the WETH contract or its compatibility with the Automator contract, it could lead to unintended behavior or loss of funds.
      • INonfungiblePositionManager compatibility: The Automator contract interacts with the INonfungiblePositionManager contract for managing liquidity positions. If there are any compatibility issues, changes in the INonfungiblePositionManager contract, or vulnerabilities, it could impact the functionality of the Automator contract.
      • Swap router compatibility: The contract uses external swap routers (ZeroXRouter and UniversalRouter) for executing swaps. If these routers experience downtime, have vulnerabilities, or introduce incompatible changes, the Automator contract's functionality could be affected. Additionally, if the swap routers do not support specific tokens or have issues with certain token contracts, it could lead to integration issues.
  • AutoCompound.sol

    1. Centralization Risks:

      • The contract has a centralized ownership model, where the contract owner can set the reward rate (setReward).
      • There is a centralized operator account (operators) that can execute compounding operations (execute and executeWithVault).
      • There is a centralized withdrawer account (withdrawer) that can withdraw accumulated protocol fees (withdrawBalances).
      • The contract relies on off-chain calculations for various parameters, such as swap direction (swap0To1) and swap amount (amountIn). If these calculations are incorrect or manipulated, it could lead to undesirable outcomes.
    2. Integration Risks:

      • The contract assumes that the positions it operates on are approved for the contract (approve or setApprovalForAll). If the approvals are not set correctly, the contract may not be able to execute the desired operations.
  • AutoRange.sol

    1. Systemic Risks

      • Revert-controlled bot dependency: The contract relies on a revert-controlled bot (operator) to execute position adjustments and swaps. If the bot experiences issues, is compromised, or becomes unavailable, it could lead to a cascade of unadjusted positions, potentially impacting the overall stability of the DeFi ecosystem, particularly if these positions are significant in size or number.
    2. Integration Risks

      • Vault compatibility: The AutoRange contract interacts with Vault contracts for managing positions. If there are any compatibility issues, changes in the Vault contracts, or vulnerabilities, it could impact the functionality of the AutoRange contract.
  • LeverageTransformer.sol

    1. Systemic Risks

      • liquidations: The LeverageTransformer contract enables users to adjust their leverage positions in a single transaction. In the event of a sudden market crash or significant price movement, multiple users might simultaneously adjust their positions, leading to a cascade of liquidations. This could amplify market volatility and negatively impact the overall stability of the protocol.

      • Leverage-induced market manipulation: The contract allows users to easily leverage or deleverage their positions, which could encourage market manipulation by malicious actors. By rapidly adjusting their positions, these actors could artificially inflate or deflate asset prices, causing market instability and negatively affecting other market participants.

    2. Centralization Risks

      • Vault dependency: The contract relies on Vault contracts for borrowing, repaying, and managing positions. If the Vault contracts are controlled by a centralized entity or have centralization risks, this could lead to potential censorship or single points of failure.

      • Swap router dependency: The contract uses external swap routers for executing swaps. If these routers are controlled by centralized entities or have centralization risks, it could impact the functionality of the LeverageTransformer contract.

    3. Technical Risks

      • Incorrect leverage parameters: The contract allows users to provide leverage parameters, such as borrow amount, swap amounts, and liquidity adjustments. If these parameters are set incorrectly, it could lead to unintended behavior, such as insufficient liquidity, failed swaps, or loss of funds.
    4. Integration Risks

      • Vault compatibility: The LeverageTransformer contract interacts with Vault contracts for managing positions. If there are any compatibility issues, changes in the Vault contracts, or vulnerabilities, it could impact the functionality of the LeverageTransformer contract.

      • Swap router compatibility: The contract uses external swap routers for executing swaps. If these routers experience downtime, have vulnerabilities, or introduce incompatible changes, the LeverageTransformer contract's functionality could be affected. Additionally, if the swap routers do not support specific tokens or have issues with certain token contracts, it could lead to integration issues.

  • FlashloanLiquidator.sol

    1. Systemic Risks:

      • Flash loan risk: Flash loans are a powerful tool, but they also come with risks. If the FlashloanLiquidator contract does not properly repay the flash loan, the borrower could lose their collateral.
      • Liquidation risk: The FlashloanLiquidator contract is designed to liquidate loans that are in default. However, there is always the risk that the loan will not be fully liquidated, and the borrower will still owe money to the lender.
    2. Technical Risks:

      • Slippage risk: The FlashloanLiquidator contract uses swaps to convert the borrowed assets into the desired asset. If the market price of the assets changes significantly during the swaps, the FlashloanLiquidator contract may not be able to repay the flash loan.
    3. Integration Risks:

      • Interoperability risk: The FlashloanLiquidator contract is designed to work with specific versions of the UniswapV3Pool, NonfungiblePositionManager, and Vault contracts. If these contracts are updated or changed, the FlashloanLiquidator contract may not be able to function properly.
      • Configuration risk: The FlashloanLiquidator contract requires careful configuration to ensure that it functions properly. If the contract is not configured correctly, it could result in losses for the borrower or the lender.

Suggestions

What could they have done better?

  1. If we look at the test scope and content of the project with a systematic checklist, we can see which parts are good and which areas have room for improvement As a result of my analysis, those marked in green are the ones that the project has fully achieved. The remaining areas are the development areas of the project in terms of testing ;

test-cases.jpg

Ref:https://xin-xia.github.io/publication/icse194.pdf

nabeel-1.jpg

  1. It is recommended to increase the test coverage to 100% so make sure that each and every line is battle tested

What ideas can be incorporated?

  1. Dynamic Collateral Factors: The protocol could implement dynamic collateral factors that adjust based on market conditions. This could help mitigate risk and ensure that collateral values are always sufficient.

  2. Liquidation Incentives: The protocol could offer incentives for liquidators to encourage them to liquidate under-collateralized positions quickly and efficiently. This could help maintain the health of the system and prevent losses.

  3. Collateral Swaps: The protocol could allow users to swap their collateral for other assets without closing their positions. This could provide more flexibility and allow users to adjust their collateral based on market conditions.

  4. Flash Loan Integration: The protocol could be integrated with flash loan providers to allow users to take out short-term loans for arbitrage opportunities or other purposes.

  5. Automated Rebalancing: The protocol could implement automated rebalancing to help maintain the target collateralization ratio. This could be particularly useful for positions that use Uniswap V3 LP tokens as collateral, as their value can change rapidly.

  6. Fee Discounts for Long-Term Stakers: The protocol could offer fee discounts to users who stake their tokens for a certain period of time. This could incentivize long-term participation and help stabilize the system.

  7. Lending Pools for Different Risk Profiles: The protocol could create separate lending pools for different risk profiles. For example, there could be a low-risk pool with lower interest rates and more conservative collateral requirements, and a high-risk pool with higher interest rates and more aggressive collateral requirements.

  8. Integration with Oracles for Price Feeds: The protocol could be integrated with oracles to provide more accurate and reliable price feeds. This could help prevent liquidations due to inaccurate price data.

  9. Improved Liquidation Mechanism: The protocol could implement an improved liquidation mechanism that allows liquidators to purchase collateral at a discount, rather than selling it at a discount. This could help ensure that liquidations are always profitable for liquidators and reduce the risk of liquidations being ignored.

  10. Collateral Diversification: The protocol could allow users to diversify their collateral by splitting it across multiple assets. This could help reduce risk and increase stability.

  11. Automated Strategy Execution: The protocol could implement automated strategy execution, allowing users to set up complex trading strategies that are executed automatically based on market conditions.

What’s unique?

  1. Use of Uniswap V3 LP Tokens as Collateral: Unlike other lending protocols that typically accept only single assets as collateral, this protocol allows users to use Uniswap V3 LP tokens as collateral. This enables users to leverage their liquidity provider positions and earn interest on their collateral.
  2. Combination of Lending and Liquidity Provision: The protocol combines lending and liquidity provision in a single platform, allowing users to earn interest on their assets and provide liquidity to Uniswap V3 pools simultaneously.
  3. Non-Fungible Position Manager Integration: The protocol uses the NonfungiblePositionManager contract from Uniswap V3 to manage collateral positions. This allows users to add, remove, and transform their collateral positions with flexibility.
  4. Dynamic Interest Rate Model: The protocol's interest rate model adjusts interest rates based on the utilization rate of the asset, providing a more dynamic and responsive lending environment.
  5. Automated Liquidation and Liquidator Incentives: The protocol features an automated liquidation mechanism that liquidates under-collateralized positions and incentivizes liquidators to maintain the health of the system.
  6. Integration with Chainlink and Uniswap V3 TWAP Oracles: The protocol uses both Chainlink and Uniswap V3 TWAP oracles to derive accurate price estimates for collateral assets, providing a more robust price feed.
  7. Emergency Fallback Mechanism: The protocol includes an emergency fallback mechanism that allows an emergency admin to take special actions without a timelock in case of emergencies.
  8. Auto-Compounding and Auto-Range Adjustment: The protocol includes features that allow operators to execute auto-compounding and auto-range adjustment operations, enabling users to increase their liquidity and optimize their positions automatically.
  9. Leverage and Deleverage Operations: The protocol allows operators to execute leverage and deleverage operations directly within a single transaction, providing more flexibility and control over position size.
  10. Flashloan Liquidation: The protocol includes a helper contract that allows atomic liquidation and needed swaps by using Uniswap V3 Flashloans, providing a more efficient and seamless liquidation process.

Issues surfaced from Attack Ideas

  1. Oracle Manipulation: Attackers could manipulate the oracle price feeds used by the protocol to calculate collateral values and interest rates. This could lead to under-collateralized positions, incorrect interest rate calculations, and potential liquidations.
  2. Flash Loan Attacks: Attackers could use flash loans to manipulate market prices, execute arbitrage opportunities, and potentially liquidate other users' positions. This could result in losses for both users and the protocol.
  3. Reentrancy Attacks: Attackers could exploit reentrancy vulnerabilities in the protocol's smart contracts to drain funds, manipulate collateral values, or disrupt the system.
  4. Front-Running Attacks: Attackers could front-run other users' transactions to gain an unfair advantage, such as buying up collateral assets before a liquidation occurs or manipulating market prices.
  5. Collateral Value Manipulation: Attackers could manipulate the value of collateral assets in order to trigger liquidations, cause under-collateralized positions, or disrupt the system.

Time spent:

20 hours