Platform: Code4rena
Start Date: 04/03/2024
Pot Size: $88,500 USDC
Total HM: 31
Participants: 105
Period: 11 days
Judge: ronnyx2017
Total Solo HM: 7
Id: 342
League: ETH
Rank: 57/105
Findings: 1
Award: $83.05
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 14si2o_Flint
Also found by: Bauchibred, K42, Sathish9098, hunter_w3b, invitedtea, popeye, yongskiws
83.0533 USDC - $83.05
Revert-Lend is a sophisticated non-custodial lending protocol that allows users to borrow against their Uniswap V3 LP positions. The protocol consists of the core V3Vault contract for lending/borrowing, various yield optimization strategy contracts (AutoCompound, AutoExit, AutoRange), leverage management contracts (LeverageTransformer, FlashloanLiquidator), a custom V3Oracle for price feeds, an InterestRateModel for interest rate calculations, and utility contracts (V3Utils, Swapper).
The V3Vault is the clear heart of the Revert-Lend ecosystem. It integrates with the following key components:
Users can deposit base assets to mint vault shares (following ERC4626) and use their Uniswap V3 LP tokens as collateral to borrow base assets. The automation contracts interact with the Vault to execute yield optimization strategies on the collateral LPs.
1. Key Data Structures and Libraries
The protocol makes extensive use of well-known and audited libraries:
The use of these battle-tested libraries definitely reduces the likelihood of common vulnerabilities.
Key data structures:
2. Use of Modifiers and Access Control
Access control is primarily handled using OpenZeppelin's Ownable contract. The owner has permissions to set critical protocol parameters.
Specific access controls:
The use of modifiers is inconsistent across contracts. Some use onlyOwner
directly, others check it manually. I recommend using modifiers more consistently.
3. Use of State Variables
State variables are used appropriately to store protocol configuration and state:
Some naming inconsistencies exist, like dailyDebtIncreaseLimitMin
and dailyDebtIncreaseLimitLeft
in V3Vault which could be confusing. More distinct naming could improve readability.
4. Use of Events and Logging
All key state changes and actions emit appropriate events:
Recommend also emitting events in the _beforeTokenTransfer
hook of V3Vault for completeness.
5. Key Functions that need special attention
Critical functions:
V3Vault:
create
, add
, remove
: Directly manipulate user collateral NFTs. Bugs could lead to loss of funds.borrow
, repay
: Incorrect calculations could lead to under/over-collateralized loans.liquidate
: Needs to be incentivized properly for timely liquidations but not make it profitable to deliberately liquidate.transform
: Allows approved contracts to arbitrarily manipulate collateral NFTs. Approvals need strict vetting.V3Oracle:
getValue
: Provides critical price data for lending. Errors could lead to systemic issues.setTokenConfig
: Changes to token configurations can significantly impact price feed behavior. Robust access controls and sanity checks needed.AutoCompound, AutoExit, AutoRange:
execute
: Interact with external protocols (Uniswap) and involve complex calculations. Thorough testing under various conditions necessary.LeverageTransformer, FlashloanLiquidator:
leverageUp
, leverageDown
, liquidate
: Involve flash loans which are difficult to use safely. The callbacks need to be thoroughly stress tested.6. Upgradability
None of the contracts are upgradeable. They use the constructor-based deployment pattern. This reduces the complexity and potential vulnerabilities of upgradeability, but it also means that future bugs cannot be fixed, and new features cannot be added without redeployment and migration.
Consider implementing a effective pause and migration mechanism to handle potential issues, especially while in the early stages of the protocol.
Separate the yield strategy execution logic from the main automation contracts into separate modules for better maintainability and extensibility.
Break up the monolithic V3Vault contract into smaller, more focused contracts (e.g., collateral management, borrowing, liquidations) for better modularity and upgradability.
Implement a formal access control framework with granular roles (e.g., owner, liquidator, price admin) instead of just owner and approved transformers/operators. Use modifiers consistently for these roles.
Use a timelock controller for all privileged functions to give users time to react to potential malicious changes.
Implement circuit breakers that can pause certain operations (e.g., borrows, liquidations) if certain thresholds are breached to limit damage in extreme scenarios.
The owner has significant control of course, over protocol parameters (interest rate model, collateral factors etc.). Misconfiguration can lead to insolvency. Change management processes are necessary.
The owner can approve transformer contracts which have significant power over user collateral. The approval process needs to be stringent and transparent.
The V3Oracle's emergencyAdmin
can change price feed modes instantly. While intended for emergencies, this power could be abused. Consider a multi-sig. like gnosis safe, or DAO governance for such critical functions.
Using Uniswap V3 LP positions as collateral is innovative but untested at scale. The risk and reward mechanics for LPs in various market conditions need thorough modeling.
The V3Oracle, which combines Chainlink and Uniswap TWAPs, is meant to be robust but the specific failure modes and thresholds need extensive testing. The protocol's behavior during high volatility or divergence between Chainlink and Uniswap prices needs to be clearly defined.
The yield optimization strategies (AutoCompound, AutoExit, AutoRange) are complex and their interactions with the core lending/borrowing mechanics need careful analysis to avoid unintended consequences like manipulation of borrow/supply rates or oracle prices.
The protocol's heavy dependence on Uniswap V3 introduces concentration risk. Issues with Uniswap, either in terms of liquidity or price manipulation, could significantly impact the protocol's health. This is unlikely, but not impossible.
Oracle failures, leading to incorrect borrow amounts or liquidation thresholds, pose a significant risk. The protocol needs safe fallback mechanisms and circuit breakers to handle such scenarios.
The flash loan liquidation mechanism, while capital-efficient, is subject to the usual risks around flash loans such as price manipulation and sandwich attacks. The liquidity and gas constraints around this mechanism need more testing. Its useful to note, MEV will always be captured, this can be creatively captured for users, for more value utilization throughout the protocol. By strategically leveraging MEV, the protocol can enhance its value proposition to users.
The protocol's complex interactions with external contracts (Uniswap, Chainlink, 0x etc.) introduce multiple potential points of failure. Thorough end-to-end testing and continuous monitoring is crucial.
The transformer pattern in V3Vault is powerful but risky if not implemented correctly, it seems to be well implemented. The transformer contracts have significant control over user funds though and could potentially drain collateral if malicious. The process for approving transformer contracts and the constraints on their behaviour need to be clearly defined and enforced.
The V3Oracle's critical role means that any vulnerabilities or failures here could be catastrophic. The logic for combining Chainlink and Uniswap prices, handling outliers, and falling back to safe values in case of issues needs to be completely airtight.
The yield optimization strategies, particularly AutoRange, involve complex interactions with Uniswap that are dependent on market conditions. Thorough scenario analysis is needed to ensure these strategies behave as expected and don't introduce unintended risks.
The protocol's economic model around borrowing and lending needs to be stress-tested under various conditions, ones that are unlikely even. Parameters like the reserve factor, liquidation bonus, and keeper rewards need to be chosen very carefully to ensure the long-term sustainability of the protocol.
The flash loan liquidation mechanism introduces the risk of the protocol becoming insolvent if the liquidation fails midway (e.g., due to insufficient gas). Consistent handling of such edge cases is necessary.
The V3Vault contract is the core of the Revert-Lend protocol. It manages user deposits, share minting, collateral, borrows, and liquidations.
Share Minting/Burning (ERC4626):
Collateral Management:
Borrowing:
Liquidation:
Transformer Pattern:
create(uint256 tokenId, address recipient)
borrow(uint256 tokenId, uint256 assets) external
liquidate(LiquidateParams calldata params) external returns (uint256 amount0, uint256 amount1)
The V3Oracle contract provides price feeds for the LP tokens used as collateral in the protocol. It combines Chainlink and Uniswap V3 TWAP prices.
Chainlink Price Feeds:
Uniswap V3 TWAPs:
Price Aggregation:
Emergency Mode:
setValue(uint256 tokenId, address token) external view returns (uint256 value)
setTokenConfig(address token, AggregatorV3Interface feed, uint32 maxFeedAge, IUniswapV3Pool pool, uint32 twapSeconds, Mode mode, uint16 maxDifference) external
The InterestRateModel contract calculates the borrow and supply interest rates for the V3Vault based on utilization.
Utilization Calculation:
Kinked Model:
Interest Rate Calculation:
setValues(uint256 baseRatePerYearX96, uint256 multiplierPerYearX96, uint256 jumpMultiplierPerYearX96, uint256 _kinkX96) public
The AutoCompound contract allows users to automatically compound their Uniswap V3 LP fees back into their position.
Fee Collection:
Swapping Fees:
Adding Liquidity:
execute(ExecuteParams calldata params) external nonReentrant
params
(e.g., swap amounts, slippage tolerances) are not properly validated, it could lead to a suboptimal or failing compound operation.withdrawBalances(address[] calldata tokens, address to) external override nonReentrant
to
address is not properly validated, funds could be withdrawn to an unintended recipient.to
is a valid, non-zero address. Consider limiting withdrawals to only the contract owner or a whitelist of addresses.The AutoExit contract allows users to set up automatic exits from their Uniswap V3 LP positions when certain price conditions are met.
Price Monitoring:
Liquidity Removal:
Swapping Assets:
execute(ExecuteParams calldata params) external
The AutoRange contract automatically adjusts the price range of users' Uniswap V3 LP positions based on predefined rules.
Range Calculation:
Liquidity Removal:
Liquidity Addition:
execute(ExecuteParams calldata params) external
The LeverageTransformer contract allows users to leverage their Uniswap V3 LP positions by borrowing from the V3Vault and adding the borrowed assets to their position.
Borrowing:
Swapping:
Adding Liquidity:
leverageUp(LeverageUpParams calldata params) external
The FlashloanLiquidator contract uses flash loans to liquidate undercollateralized positions in the V3Vault.
Flash Loan:
Liquidation:
Swapping:
liquidate(LiquidateParams calldata params) external
The V3Utils contract provides a suite of utility functions for managing Uniswap V3 positions.
Permit:
Swapping:
Liquidity Management:
swap(SwapParams calldata params) external payable returns (uint256 amountOut)
params
are not properly sanitized, it could lead to unexpected swap behavior.The Swapper contract provides token swapping functionality using 0x API or Uniswap Universal Router.
0x API:
Uniswap Universal Router:
Slippage Tolerance:
_routerSwap(RouterSwapParams memory params)
params
are not properly validated, it could lead to unintended swaps.amountIn
and amountOutMin
are within reasonable bounds. Consider adding a maximum slippage tolerance to prevent accidental high slippage trades.V3Vault-->create; V3Vault-->add; V3Vault-->remove; V3Vault-->borrow; V3Vault-->repay; V3Vault-->liquidate; V3Vault-->transform; V3Vault-->setLimits; V3Vault-->setReserveFactor; V3Vault-->setTokenConfig;
V3Oracle-->getValue; V3Oracle-->setTokenConfig; V3Oracle-->setOracleMode; V3Oracle-->setMaxPoolPriceDifference; V3Oracle-->setEmergencyAdmin;
InterestRateModel-->getUtilizationRateX96; InterestRateModel-->getRatesPerSecondX96; InterestRateModel-->setValues;
AutoCompound-->execute; AutoCompound-->executeWithVault; AutoCompound-->withdrawLeftoverBalances; AutoCompound-->withdrawBalances; AutoCompound-->setReward;
AutoExit-->execute; AutoExit-->approveTransform; AutoExit-->transform;
AutoRange-->executeWithVault; AutoRange-->execute; AutoRange-->configToken;
LeverageTransformer-->leverageUp; LeverageTransformer-->leverageDown;
FlashloanLiquidator-->liquidate; FlashloanLiquidator-->uniswapV3FlashCallback;
V3Utils-->executeWithPermit; V3Utils-->execute; V3Utils-->onERC721Received; V3Utils-->swap; V3Utils-->swapAndMint; V3Utils-->swapAndIncreaseLiquidity;
Swapper-->_routerSwap; Swapper-->_poolSwap; Swapper-->_validateSwap; Swapper-->_prepareAddApproved; Swapper-->_prepareAddPermit2;
Implement a governance framework with timelock for all critical protocol changes. This includes changes to the interest rate model, collateral factors, oracle configurations, and approved transformer contracts. Use a multi-sig wallet for the most sensitive operations.
Establish a clear risk framework that defines the criteria for listing new collateral types, setting collateral factors, and approving transformer contracts. This framework should be public and any changes should go through a community review process.
Conduct thorough stress testing of the protocol under various market conditions. This should include testing liquidity crisis scenarios, extreme price volatility, oracle failures, and flash loan attacks. Establish clear risk parameters and circuit breakers based on these tests.
Give reference to Security Alliance's SEAL-911 to help with trust and incident response.
Implement comprehensive monitoring and alerting for key protocol metrics and events. This includes monitoring for large borrows, liquidations, price deviations, and abnormal contract interactions. Use tools like OpenZeppelin Defender for automated monitoring and response.
Foster a culture of openness and transparency within the community. Regularly publish updates on the protocol's financial health, risk parameters, and governance decisions. Engage actively with the community and be receptive to feedback and criticism.
Revert-Lend In conclusion, Revert-Lend is a pioneering protocol that brings the capital efficiency of Uniswap V3 to the lending market, offering users the ability to borrow against their LP positions and optimize yields through automated strategies. While this innovation opens up exciting possibilities, it also introduces significant risks due to the complexity of the system and the unique challenges of using LP tokens as collateral.
To succeed, the protocol must prioritize creative risk management, including thorough stress testing, like mutation testing, and comprehensive monitoring, with a strong governance framework. Transparency, continued regular audits, and active community engagement will continue to be crucial.
Despite the welcomed challenges, Revert-Lend has the hopeful potential to become a major player in the DeFi space. The protocol's success will ultimately depend on its ability to balance further innovation with sound risk management and governance practices.
16 hours
#0 - c4-pre-sort
2024-03-24T09:06:21Z
0xEVom marked the issue as sufficient quality report
#1 - c4-judge
2024-04-01T13:39:21Z
jhsagd76 marked the issue as grade-b