A shared fungible (ERC20) position for Uniswap V3 passive liquidity providers. Grizzly Vaults are auto-compounded to reinvest accrued fees into the position.
The position bounds are static by default, but can be updated by vault manager via executiveRebalance
which redeposits liquidity into a new range.
function mint(uint256 mintAmount, address receiver)
external
nonReentrant
returns (
uint256 amount0,
uint256 amount1,
uint128 liquidityMinted
) {
Arguments:
mintAmount
amount of Grizzly vault tokens to mintreceiver
account that receives the Grizzly vault tokens
Returns:
amount0
amount of token0 actually deposited into Grizzly vaultamount1
amount of token1 actually deposited into Grizzly vaultliquidityMinted
amount of liquidity added to Grizzly vault position
Note: to find out the amount of token0 and token1 you would owe by minting that many Grizzly vault tokens use getMintAmounts
view method.
function burn(
uint256 burnAmount,
bool onlyToken0,
bool onlyToken1,
address receiver
)
external
nonReentrant
returns (
uint256 amount0,
uint256 amount1,
uint128 liquidityBurned
) {
Arguments:
_burnAmount
number of Grizzly vault tokens to burnonlyToken0
if true the user zaps out with only token0onlyToken1
if true the user zaps out with only token1receiver
account that receives the remitted token0 and token1
Returns:
amount0
amount of token0 remitted to receiveramount1
amount of token1 remitted to receiverliquidityBurned
amount of liquidity burned from Grizzly vault position
function getMintAmounts(uint256 amount0Max, uint256 amount1Max)
external
view
returns (
uint256 amount0,
uint256 amount1,
uint256 mintAmount
) {
Arguments:
amount0Max
maximum amount of token0 to deposit into Grizzly vaultamount1Max
maximum amount of token1 to deposit into Grizzly vault
Returns:
amount0
actual amount of token0 to deposit into Grizzly vaultamount1
actual amount of token1 to deposit into Grizzly vaultmintAmount
amount of Grizzly vault tokens to pass to mint function (will cost exactlyamount0
andamount1
)
function rebalance() external onlyAuthorized
Note: Reinvest fees earned into underlying position, only authorized executors can call.
If governance/admin wants to change bounds of the underlying position, or wants to force a rebalance for any other reason, they are allowed to call this executive rebalance function.
function executiveRebalance(
int24 newLowerTick,
int24 newUpperTick,
uint128 minLiquidity
) external onlyManager {
Arguments:
newLowerTick
the tick to use as position lower bound on reinvestmentnewUpperTick
the tick to use as position upper bound on reinvestmentminLiquidity
minimum liquidity of the new position in order to not revert
Basic zap that allows to deposit in the vault with one of the underlying pool tokens. ZapContract balances properly the amounts in order to maximize the liquidity provision.
function zapIn(
address pool,
address vault,
uint256 amount0Desired,
uint256 amount1Desired,
uint256 maxSwapSlippage
) external {
Arguments:
pool
the desired UniV3 pool to zapInvault
the Grizzly vault chosen to deposit the tokensamount0Desired
amount of token0 the user wants to invest into the vaultamount1Desired
amount of token1 the user wants to invest into the vaultmaxSwapSlippage
maxSlippage allowed for the underlying swap
Every clone is a 100% replica of the Vault instance but serving for different variables. The proxy factory pattern helps us to deploy a bunch of immutable Vault clones with a considerably lower gas cost. These clones have the exact same logic as the implementation contract but with its own storage state.
function cloneGrizzlyVault(
address tokenA,
address tokenB,
uint24 uniFee,
uint24 managerFee,
int24 lowerTick,
int24 upperTick,
address manager
) external override returns (address newVault) {
Arguments:
tokenA
one of the tokens in the uniswap pairtokenB
the other token in the uniswap pairuniFee
fee tier of the uniswap pairmanagerFee
proportion of earned fees that go to pool managerlowerTick
initial lower bound of the Uniswap V3 positionupperTick
initial upper bound of the Uniswap V3 positionmanager
address of the manager of the new Vault
To install all the dependencies run
yarn
Tests are performed on a mainnet fork. Set your Alchemy key on an .env file. See .env.example.
Some tests are performed on mainnet pools. To configure the information of these pools check this file.
To perform all the tests run
yarn hardhat test
To deploy contracts, first set up your private key in a .env file, as in .env.example, and run:
yarn hardhat deploy --network <network> --tags <network>
To verify your deployed contracts, first set up your Etherscan API key in a .env file, as in .env.example, and run:
yarn hardhat --network <network> etherscan-verify