Uniswap V3 Strategies Code Review
The following strategies are reviewed:
- Charm Finance
- Visor Finance
Visor Finance
GitHub Org: https://github.com/VisorFinance
Smart Contracts Repo: private
ETH-USDT Hypervisor: https://etherscan.io/address/0xa08583b36a809934e019574695392b516be9354f
Terminology
- Hypervisor: They call Vaults or Rebalancer contract as a Hypervisor.
- There is only one imp function called
createHypervisor()
which allows owner (or governance) to deploy a new Hypervisor.
- There cannot be two separate Hypervisor contracts for a single Uniswap Pool.
- While deploying, the owner specifies these initial parameters:
- Base Lower Tick
- Base Upper Tick
- Limit Lower Tick
- Limit Upper Tick
- Worth noting that these above names are also present in Charm Finance strategy too.
This linked etherscan link is of ETH-USDT 0.3% Pool.
- When deployed, it sets infinite deposit limit and penalty percent as 2.
- This contract maintains a whitelist, which allows only certain addresses to use the deposit function.
- The deposit function:
- It accepts user deposits in any proportion.
- To bring the pool into 50-50 asset value proportion, depositors are penalized by 2% for a part of their asset that worsens the proportion.
- If user's deposit propotion helps to balance the pool then they are not penalized.
- Whenever anyone deposits, the fees are updated, which increases the share price.
- Rebalance:
- It is performed by owner address.
- The owner manually specifies the base ticks and limit ticks. As well as quantity of tokens to swap into other if required.
- Fees are claimed.
- Then the two positions: base and limit are closed.
- And new base position is created with maximum possible liquidity.
- If there is any asset remaining then a limit order can be used to create it.
- Withdraw:
- The function withdraws partial liquidity from the pool.
- The rebalance is pretty much manual, a stregist decides on the base ticks and limit ticks. The market conditions may change slightly.
- Deposit function does not add liquidity on deposit. But withdraw function always withdraws liquidity from the pool. This is not capital efficient as well as vulnerable to this attack vector: A user takes flash loan, deposits and then withdraws. The attacker does not gain anything but majority of liquidity (99.99%) can be moved from uniswap pool to the hypervisor contract keeping it unused until the next rebalance, hence preventing users from making profit.
- The owner has ability to completely rug the users using the function
emergencyWithdraw()
.
- The source code is not made public on GitHub. (Though it seems like a private beta testing).
Charm Finance
GitHub Repo: https://github.com/charmfinance/alpha-vaults-contracts/
Contracts:
- Alpha Vault
- Alpha Strategy
A lot of code from Visor is similar to Charm's code. Given that Charm has been public since the start, Visor likely copied this code. Also charm's code is better readable.
- The deposit function
- User can only deposit in the vault's proportion of vault's current holdings.
- Whenever anyone deposits, the fees are updated, which increases the share price.
- Rebalance
- The function is only callable by strategy contract, which dynamically calculates values of base and limit ticks.
- It keeps aside 5% of fees as protocol fees. Doesn't immediately send to some address. There is another function which allows governance to claim the fees.
- Withdraw
- Withdraws partial liquidity from pool
Alpha Strategy (code)
- This contract is used to dynamically calculate the base and limit ticks.
- Owner/Governance sets some parameters:
baseThreshold
, limitThreshold
, maxTwapDeviation
, twapDuration
.
- A keeper address is allowed to call the rebalance function
- The rebalance function is explained well in this medium blog post.
- It seems that same vector still lies in deposit and withdraw contracts of Charm too. Though no funds at risk.
- Visor copied only the Alpha Vaults code from Charm
- Charm's contracts also have the emergency methods, but there is also a functionality of renouncing those emergency controls.
- The governance address is a private key wallet (charmfinance.eth).