RoboVault - Smart Contract Audit Report

Summary

RoboVault Audit Report RoboVault is developing a single-asset yield farming strategy on the Fantom Blockchain in which users users deposit tokens such as USDC, WBTC, and WETH, and earn rewards from both a lending protocol and an LP yield farming platform.

We audited the project team's BaseStrategy, HedgedFarmingVault, HedgedFarmingStrategy, and rvUSDCCreamSpooky contracts at commit ba2664e17bc1e7b6eb70dd26f896db909be49587 on the team's private Github repository.

Audit Findings Summary:
  • No security threats from outside attackers were identified.
  • The LP tokens held by the vault are not fully protected from impermanent loss, but the project team can mitigate the effects by balancing the pools; impermanent loss can impact profit and even result in a permanent loss.
  • Ensure trust in the team as they have substantial control in the ecosystem and must manually maintain the Vault and balance it's position in order to mitigate risks due to price volatility and other factors.
  • Date: September 22nd, 2021
Notes on the Contracts:
Deposit Funds:
  • Anyone can deposit any amount of the base asset token, as long as their account deposit limit, the platform's collateral capacity limit, and the Vault total value limit has not been reached.
  • The deposited tokens are stored in the contract balance, and shares are minted to the user proportional to the value that their deposit in the pool represents.
Allocate Funds:
  • Once base asset tokens are deposited into the contract, it is up to the project team to allocate the funds accordingly.
  • While the collateral capacity limit has not been reached, the Strategist address or the Governance address must lend a portion of the base asset token and receive a secondary asset token in exchange.
  • The remaining base asset tokens are then paired with the received secondary asset tokens and added as liquidity to the base-secondary asset pair.
  • The received LP tokens are stored in the contract and subsequently deposited into the Farm to earn rewards.
Vault Maintenance:
  • The Keeper address is responsible for maintaining the health of the RoboVault. The Keeper is able to rebalance the debt ratio and the collateral ratio if either falls outside the bounds deemed acceptable by the protocol.
  • The Keeper is also able to allocate any excess base asset tokens in the contract balance to the lending protocol and farm, in accordance with the protocol's standards.
  • The Strategist address or Governance address is able to exit the RoboVault's leveraged position at any time by removing all the liquidity and repaying as much debt as possible.
  • The Strategist or Governance address can also choose to liquidate any portion of the RoboVault's position at any time.
Harvest Rewards:
  • The Keeper, Strategist, or Governance address can harvest any rewards from the lending protocol or the yield farming platform at any time.
  • A portion of the reward tokens received from each platform is swapped for the secondary asset token in such a manner as to ensure that the ratio of the secondary tokens to reward tokens in the liquidity pool stays as consistent as possible.
  • The received secondary asset tokens are used to repay the contract's debt and reduce the borrow balance in the lending platform.
  • On harvesting, the value of the RoboVault shares is calculated in order to determine the profit earned on the shares; a portion of the profit is minted in shares to the Rewards address as a fee, another portion is minted to the Governance address.
  • Regardless of profit level, an operational fee based on the time since the last harvest is minted in shares to the Governance address.
Withdraw Funds:
  • In order to withdraw, the user must exchange shares for a proportional amount of the base asset token that the shares represent.
  • The user will be subject to a withdrawal fee in the event that there is not enough of the base asset token in the contract's balance in order to cover the entire withdrawal; the fee is based on the amount of assets that needs to be liquidated.
  • In order to cover the user's withdrawal, the contract will decouple all the liquidity pool tokens that are in the contract, supplementing the rest with some of the LP tokens in the Farm. The contract will then rebalance the liquidity in order to regulate the debt ratio.
  • Any secondary asset tokens received from the process are used to reduce the contract's borrow balance in the lending platform; depending on the contract's calculated debt to collateral ratio, and if there are still more want tokens needed to support the withdrawal, the collateral received in exchange is redeemed for the base asset token.
Ownership:
  • The Governance address is initially set to the address that deployed the contract.
  • The Strategist or Governance address is able to set the Strategist, Keeper, and Rewards addresses to any address at any time.
  • The Strategist or Governance address is able to enter or exit the market for the base asset token in the lending platform at any time.
  • The Strategist or Governance address is able to grant or remove unlimited allowance of all tokens used by the platform to the appropriate addresses at any time.
  • The Strategist or Governance address is able to set the upper and lower bounds for the slippage when interacting with Uniswap to any values at any time.
  • The Strategist or Governance address is able to set the upper and lower bounds for the debt thresholds as long as the lower bound is less than 100% and the upper bound is greater than 100%; a debt ratio of 100% is considered well balanced.
  • The Strategist or Governance address is able to set the target ratio, upper and lower bounds for the collateral thresholds as long as the upper bound is less than a 3:4 ratio and the target is between the upper and lower thresholds.
  • The Strategist or Governance address is able to set the reserve, lend, and debt allocations to any values at any time as long as the reserve allocation is no more than 10% and the debt to collateral allocation ratio is not more than 3:4.
  • The Strategist or Governance address is able to rebalance the debt ratio or the collateral ratio at any time.
  • Usage of ReentrancyGuard to prevent re-entrancy attacks.
  • The contract complies with the ERC-20 standard.
  • As the contract utilizes SafeMath libraries, it is protected from overflows.

External Threat Results

Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Delegate Call to Untrusted ContractN/APASS
Dependence on Predictable VariablesN/APASS
Deprecated OpcodesN/APASS
Ether ThiefN/APASS
ExceptionsN/APASS
External CallsN/APASS
Flash LoansN/APASS
Integer Over/UnderflowN/APASS
Multiple SendsN/APASS
OraclesN/APASS
SuicideN/APASS
State Change External CallsN/APASS
Unchecked RetvalN/APASS
User Supplied AssertionN/APASS
Critical Solidity CompilerN/APASS
Overall Contract Safety PASS

Smart Contract Graph

Multi-file Token

												
($) = payable function
 # = non-constant function

 + [Lib] SafeMath 
    - [Int] add
    - [Int] sub
    - [Int] sub
    - [Int] mul
    - [Int] div
    - [Int] div
    - [Int] mod
    - [Int] mod

 + [Int] IERC20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 + [Lib] Address 
    - [Int] isContract
    - [Int] sendValue #
    - [Int] functionCall #
    - [Int] functionCall #
    - [Int] functionCallWithValue #
    - [Int] functionCallWithValue #
    - [Prv] _functionCallWithValue #

 + [Lib] SafeERC20 
    - [Int] safeTransfer #
    - [Int] safeTransferFrom #
    - [Int] safeApprove #
    - [Int] safeIncreaseAllowance #
    - [Int] safeDecreaseAllowance #
    - [Prv] _callOptionalReturn #

 +  Context 
    - [Int] _msgSender
    - [Int] _msgData

 +  ERC20 (Context, IERC20)
    - [Pub]  #
    - [Pub] name
    - [Pub] symbol
    - [Pub] decimals
    - [Pub] totalSupply
    - [Pub] balanceOf
    - [Pub] transfer #
    - [Pub] allowance
    - [Pub] approve #
    - [Pub] transferFrom #
    - [Pub] increaseAllowance #
    - [Pub] decreaseAllowance #
    - [Int] _transfer #
    - [Int] _mint #
    - [Int] _burn #
    - [Int] _approve #
    - [Int] _setupDecimals #
    - [Int] _beforeTokenTransfer #

 +  ReentrancyGuard 
    - [Int]  #

 +  BaseStrategy (ERC20, ReentrancyGuard)
    - [Pub]  #
       - modifiers: ERC20
    - [Ext] setStrategist #
       - modifiers: onlyAuthorized
    - [Ext] setKeeper #
       - modifiers: onlyAuthorized
    - [Ext] setRewards #
       - modifiers: onlyStrategist
    - [Ext] deactivate #
       - modifiers: onlyAuthorized
    - [Ext] activate #
       - modifiers: onlyAuthorized
    - [Pub] estimatedTotalAssets
    - [Ext] isActive
    - [Ext] setMinReportDelay #
       - modifiers: onlyAuthorized
    - [Ext] setMaxReportDelay #
       - modifiers: onlyAuthorized
    - [Ext] setProfitFactor #
       - modifiers: onlyAuthorized
    - [Int] _liquidatePosition #
    - [Pub] tendTrigger
    - [Ext] tend #
       - modifiers: onlyKeepers
    - [Pub] balancePendingHarvest
    - [Ext] harvestTrigger
    - [Ext] harvest #
       - modifiers: onlyKeepers
    - [Int] _harvestInternal #
    - [Pub] getPricePerShare
    - [Int] takeFees #
    - [Pub] withdraw #
    - [Pub] deposit #
       - modifiers: nonReentrant
    - [Pub] checkDeposit #
    - [Ext] depositAll #
    - [Ext] withdrawAll #
    - [Ext] setFees #
       - modifiers: onlyAuthorized
    - [Ext] setLimits #
       - modifiers: onlyAuthorized
    - [Int] _protectedTokens
    - [Ext] sweep #
       - modifiers: onlyGovernance

 + [Int] IComptroller 
    - [Ext] enterMarkets #
    - [Ext] exitMarket #
    - [Ext] mintAllowed #
    - [Ext] mintVerify #
    - [Ext] redeemAllowed #
    - [Ext] redeemVerify #
    - [Ext] borrowAllowed #
    - [Ext] borrowVerify #
    - [Ext] repayBorrowAllowed #
    - [Ext] repayBorrowVerify #
    - [Ext] liquidateBorrowAllowed #
    - [Ext] liquidateBorrowVerify #
    - [Ext] seizeAllowed #
    - [Ext] seizeVerify #
    - [Ext] transferAllowed #
    - [Ext] transferVerify #
    - [Ext] claimComp #
    - [Ext] liquidateCalculateSeizeTokens

 + [Int] InterestRateModel 
    - [Ext] getBorrowRate
    - [Ext] getSupplyRate

 + [Int] ICTokenStorage 

 + [Int] ICToken (ICTokenStorage)
    - [Ext] transfer #
    - [Ext] transferFrom #
    - [Ext] approve #
    - [Ext] allowance
    - [Ext] balanceOf
    - [Ext] balanceOfUnderlying #
    - [Ext] getAccountSnapshot
    - [Ext] borrowRatePerBlock
    - [Ext] supplyRatePerBlock
    - [Ext] totalBorrowsCurrent #
    - [Ext] borrowBalanceCurrent #
    - [Ext] borrowBalanceStored
    - [Ext] exchangeRateCurrent #
    - [Ext] exchangeRateStored
    - [Ext] getCash
    - [Ext] accrueInterest #
    - [Ext] seize #
    - [Ext] totalCollateralTokens
    - [Ext] accountCollateralTokens
    - [Ext] isCollateralTokenInit
    - [Ext] collateralCap
    - [Ext] _setPendingAdmin #
    - [Ext] _acceptAdmin #
    - [Ext] _setComptroller #
    - [Ext] _setReserveFactor #
    - [Ext] _reduceReserves #
    - [Ext] _setInterestRateModel #

 + [Int] ICTokenErc20 (ICToken)
    - [Ext] mint #
    - [Ext] redeem #
    - [Ext] redeemUnderlying #
    - [Ext] borrow #
    - [Ext] repayBorrow #
    - [Ext] liquidateBorrow #
    - [Ext] _addReserves #

 + [Int] ICCapableErc20 
    - [Ext] mint #
    - [Ext] redeem #
    - [Ext] redeemUnderlying #
    - [Ext] borrow #
    - [Ext] repayBorrow #
    - [Ext] liquidateBorrow #
    - [Ext] gulp #
    - [Ext] _addReserves #

 + [Int] CCollateralCapStorage 
    - [Ext] totalCollateralTokens
    - [Ext] accountCollateralTokens
    - [Ext] isCollateralTokenInit
    - [Ext] collateralCap

 + [Int] IFarmMasterChef 
    - [Ext] deposit #
    - [Ext] withdraw #
    - [Ext] userInfo

 + [Int] IUniswapV2Router01 
    - [Ext] factory
    - [Ext] WETH
    - [Ext] addLiquidity #
    - [Ext] addLiquidityETH ($)
    - [Ext] removeLiquidity #
    - [Ext] removeLiquidityETH #
    - [Ext] removeLiquidityWithPermit #
    - [Ext] removeLiquidityETHWithPermit #
    - [Ext] swapExactTokensForTokens #
    - [Ext] swapTokensForExactTokens #
    - [Ext] swapExactETHForTokens ($)
    - [Ext] swapTokensForExactETH #
    - [Ext] swapExactTokensForETH #
    - [Ext] swapETHForExactTokens ($)
    - [Ext] quote
    - [Ext] getAmountOut
    - [Ext] getAmountIn
    - [Ext] getAmountsOut
    - [Ext] getAmountsIn

 + [Int] IUniswapV2Router02 (IUniswapV2Router01)
    - [Ext] removeLiquidityETHSupportingFeeOnTransferTokens #
    - [Ext] removeLiquidityETHWithPermitSupportingFeeOnTransferTokens #
    - [Ext] swapExactTokensForTokensSupportingFeeOnTransferTokens #
    - [Ext] swapExactETHForTokensSupportingFeeOnTransferTokens ($)
    - [Ext] swapExactTokensForETHSupportingFeeOnTransferTokens #

 + [Int] IBandProtocol 
    - [Ext] getReferenceData
    - [Ext] getReferenceDataBulk

 +  PriceOracle 
    - [Pub]  #
    - [Ext] getPrice

 +  HedgedFarmingVault (BaseStrategy)
    - [Pub]  #
       - modifiers: BaseStrategy
    - [Ext] enterMarket #
       - modifiers: onlyAuthorized
    - [Ext] exitMarket #
       - modifiers: onlyAuthorized
    - [Int] _farmPendingRewards
    - [Pub] estimatedTotalAssets
    - [Pub] calcDebtRatio
    - [Pub] calcCollateral
    - [Ext] calcReserves
    - [Int] convertShortToWantLP
    - [Int] convertShortToWantOracle
    - [Int] convertWantToShortLP
    - [Pub] balanceLp
    - [Pub] balanceDebt
    - [Pub] balanceDebtOracle
    - [Pub] balancePendingHarvest
    - [Pub] balanceReserves
    - [Pub] balanceShort
    - [Pub] balanceShortWantEq
    - [Pub] balanceLend
    - [Pub] balanceLendCollateral
    - [Int] calcBorrowAllocation
    - [Int] getWantInLending
    - [Int] getWantInLp
    - [Int] countLpPooled
    - [Int] _getShortInLp
    - [Int] _lendWant #
    - [Int] _borrowWantEq #
    - [Int] _borrow #
    - [Int] _repayDebt #
    - [Int] _getHarvestInHarvestLp
    - [Int] _getShortInHarvestLp
    - [Int] _redeemWant #
    - [Int] _withdrawLpRebalance #
    - [Int] _withdrawLpRebalanceCollateral #
    - [Int] _addToLpFull #
    - [Int] _addToLP #
    - [Int] _depoistLp #
    - [Int] _withdrawSomeLp #
    - [Int] _removeAllLp #
    - [Int] _withdrawAllPooled #
    - [Int] _pathFarmToWant
    - [Int] _sellHarvestWant #
    - [Int] _pathFarmToShort
    - [Int] _pathCompToShort
    - [Int] _sellHarvestShort #
    - [Int] _sellCompShort #
    - [Int] _pathWantToShort
    - [Int] _pathShortToWant
    - [Int] _swapWantShort #
    - [Int] _swapShortWant #
    - [Int] _swapWantShortExact #
    - [Int] _protectedTokens

 +  HedgedFarmingStrategy (HedgedFarmingVault)
    - [Pub]  #
       - modifiers: HedgedFarmingVault
    - [Ext] approveContracts #
       - modifiers: onlyAuthorized
    - [Ext] resetApprovals #
       - modifiers: onlyAuthorized
    - [Ext] setSlippageAdj #
       - modifiers: onlyAuthorized
    - [Ext] setDebtThresholds #
       - modifiers: onlyAuthorized
    - [Ext] setCollateralThresholds #
       - modifiers: onlyAuthorized
    - [Ext] setFundingAllocations #
       - modifiers: onlyAuthorized
    - [Ext] rebalanceDebtForced #
       - modifiers: onlyAuthorized
    - [Ext] rebalanceCollateralForced #
       - modifiers: onlyAuthorized
    - [Ext] deployAuth #
       - modifiers: onlyAuthorized
    - [Ext] liquidatePositionAuth #
       - modifiers: onlyAuthorized
    - [Ext] exitLeveragePosition #
       - modifiers: onlyAuthorized
    - [Ext] deployStrat #
       - modifiers: onlyKeepers
    - [Ext] rebalanceCollateral #
       - modifiers: onlyKeepers
    - [Ext] tend #
       - modifiers: onlyKeepers
    - [Pub] rebalanceDebt #
       - modifiers: onlyKeepers
    - [Int] _harvestInternal #
       - modifiers: onlyKeepers
    - [Pub] checkDeposit #
    - [Pub] tendTrigger
    - [Pub] collateralCapReached
    - [Int] _liquidityCheck
    - [Int] _calcWithdrawalFee
    - [Int] _rebalanceCollateralInternal #
    - [Int] _deployCapital #
    - [Int] _rebalanceDebtInternal #
    - [Int] _rebalanceHighDebt #
    - [Int] _rebalanceLowDebt #
    - [Int] _rebalanceVeryLowDebt #
    - [Int] _removeLpPercent #
    - [Int] _liquidatePosition #

 + [Int] SpiritFarm 
    - [Ext] pendingSpirit

 +  rvUSDCCreamSpooky (HedgedFarmingStrategy)
    - [Int] _farmPendingRewards
    - [Pub]  #
       - modifiers: HedgedFarmingStrategy
    - [Int] _sellCompShort #