Arrakis V1 Docs (old)
Legacy Arrakis V1 Developer Documentation
Introduction to Arrakis V1
Arrakis V1 vaults are generic ERC20 wrappers on Uniswap V3 Positions. Vaults with any price bounds on any Uniswap V3 pair can be deployed via the ArrakisFactory
instantiating a tokenized V3 Position. When liquidity is added into the vault, Arrakis vault tokens are minted and credited to the provider. Inversely, Arrakis tokens can be burned to redeem that proportion of the pool's V3 position liquidity and fees earned. Thus, Arrakis tokens represent proportional ownership (or "shares") of the underlying Uniswap V3 position. Similar to the Uniswap V2 LP experience, anyone can add liquidity to or remove liquidity from a Arrakis Vault, and can earn their portion of the fees generated just by holding the fungible tokens.
Some Arrakis vaults may have a special privileged manager
role (see the Manager Functions
sections).
ArrakisFactory (V1)
The ArrakisFactory
smart contract governs over the creation of Arrakis Vaults. In theory, any account or smart contract can create a Arrakis Vault via the factory by calling deployVault
. This creates a tokenized UniswapV3 Position with a given initial price range on the token pair and fee tier of your choice. Anyone can now participate as an LP in that range, by adding liquidity into this position and minting Arrakis tokens. Whatever account is set as the manager role is the only account that may alter the price range of all the underlying vault liquidity with executiveRebalance()
deployVault
Deploy a Arrakis Vault on the Uniswap V3 pair and with the Position parameters of your choosing.
Arguments:
tokenA
One of the tokens in the Uniswap V3 pairtokenB
The other token in the Uniswap V3 pairuniFee
Fee tier of the Uniswap V3 pair (100, 500, 3000, 10000)manager
Account which is initial "manager" (ability to rebalance range). If you want vault position to be entirely immutable (position range can never change) set manager to Zero Address.managerFee
% cut of fees earned that accrue to manager, in Basis Points (9750 is max since 2.5% of earned fees already accrue to Arrakis Protocol).lowerTick
Initial lower price bound for the position, represented as a Uniswap V3 tick.upperTick
Initial upper price bound for the position, represented as a Uniswap V3 tick.
The lowerTick
and upperTick
:
1. MUST be set to integers between -887272 and 887272 where upperTick > lowerTick
2. MUST be integers divisible by the tickSpacing of the Uniswap pair.
Returns:
vault
address of newly deployed Arrakis Vault ERC20 contract (proxied).
To have full verification and functionality on etherscan (read/write methods) verify the proxy contract. Etherscan will recognize the contract address as an ERC20 token and generate the token page after minting of the first Arrakis tokens.
In order for a new vault to be searchable on the arrakis beta ui list of vaults, the new vault needs to be added to the Arrakis community-data (make a pr here). (If any underlying tokens of the vault aren't on are token list yet, you can add those to this repo as well.)
ArrakisRouter (V1)
The ArrakisRouter
smart contract is responsible for handling user interactions, namely:
adding liquidity to an Arrakis vault and minting Arrakis tokens
removing liquidity from an Arrakis vault by burning Arrakis tokens (redeeming that share of the vault's underlying balances)
addLiquidity
remember to approve the ArrakisRouter to spend up to amount0Max
and amount1Max
before calling this method
Arguments:
arrakisVault
: vault address to add liquidity toamount0Max
: max amount token0 to depositamount1Max
: max amount token1 to depositamount0Min
: min amount token0 to deposit (slippage param)amount1Min
: min amount token1 to deposit (slippage param)amountSharesMin
: min amount Arrakis tokens to mint (slippage param)receiver
: address receiving Arrakis tokens
use getMintAmount
view method of ArrakisVault to get expected values and calculate min thresholds, for example:
const { amount0, amount1, mintAmount } =
await vault.getMintAmounts( amount0Max, amount1Max ); const amount0Min = amount0.mul(99).div(100) // 1% slippage const amount1Min = amount1.mul(99).div(100) const amountSharesMin = mintAmount.mul(99).div(100)
Returns:
amount0
: amount token0 depositedamount1
: amount token1 depositedmintAmount
: amount Arrakis token shares minted
addLiquidityETH
same functionality and arguments as addLiquidity
but expects ETH transfers and wraps for WETH token (for vaults with WETH as one of the tokens in the pair)
removeLiquidity
remember to approve Arrakis token to be spent by the router before calling this method.
Arguments:
arrakisVault
: vault address to remove liquidity fromburnAmount
: vault shares to burnamount0Min
: minimum amount of token0 to receiveamount1Min
: minimum amount of token1 to receivereceiver
: address receiving tokens
Returns:
amount0
: amount token0 depositedamount1
: amount token1 depositedliquidityBurned
: amount liquidity burned from Uniswap
removeLiquidityETH
same functionality and arguments as removeLiquidity
but unwraps WETH to ETH before remitting underlying to receiver.
ArrakisVault (V1)
State Changing Methods on the ArrakisVault
contract are low level and are NOT RECOMMENDED for direct interaction by end users unless they know why and what they are doing. For standard addLiquidity / removeLiquidity interaction with Arrakis see ArrakisRouter
The ArrakisVault
smart contract is the core implementation that powers the Arrakis protocol (all Arrakis token proxy contracts point to this implementation). It is an extension of the ERC20 interface so all normal ERC20 token functions apply, as well as a number of custom methods particular to Arrakis which will be outlined below:
mint
NOT SAFE to approve vault and call mint
naively from your EOA, since providing DEX liquidity requires sandwich attack protection (slippage tolerance on market price passed from off-chain), see addLiquidity
for safe entry method.
burn
getMintAmounts
View method to compute the amount of Arrakis tokens minted (and exact amounts of token0 and token1 forwarded) from and amount0Max
and amount1Max
getUnderlyingBalances
get the current underlying balances of the entire Arrakis Vault
getUnderlyingBalancesAtPrice
Get the current underlying balances given a custom price (not simply taking the current Uniswap price which can be manipulated).
This function is useful for getting a fair unmanipulatable price of a Arrakis token for things like lending protocols (simply pass a time weighted average sqrtPrice to this function to get the unmanipulated underlying balances).
getPositionId
get the Identifier of the Arrakis position on the Uniswap V3 pair (useful for fetching data about the Position with the positions
method on UniswapV3Pool.sol
)
Vault Manager Functions
Vaults created with a manager
account who can configure the Gelato Executor meta-parameters and also can control and alter the range of the underlying Uniswap V3 position.
The manager is the most important and centrally trusted role in the Vault. It is the only role that has the power to potentially extract value from the principal invested or potentially grief the vault in a number of ways. One should only put funds into "managed" vaults if they have some information about the manager account: manager could be fully controlled by a DAO (token voting), or could simply be escrowed in a project's multi-sig, or be locked in a smart contract that automates rebalances under a certain codified strategy, or be trusted by the user for some other reason.
executiveRebalance
By far the most important manager function is the executiveRebalance
method on the ArrakisVault
. This permissioned method is the only way to change the price range of the underlying Uniswap V3 Position. Manager accounts who control this function are the means by which custom rebalancing strategies can be built on top of Arrakis. These strategies can be implemented by governance (slow, but decentralized) or by some central managerial party (more responsive but requiring much more trust) and in the future the manager role can be granted to a Keeper automated smart contract, where some LP strategy is fully codified on-chain!
Arguments:
newLowerTick
The new lower price bound of the position represented as a Uniswap V3 tick.newUpperTick
The new upper price bound of the position represented as a Uniswap V3 tick.swapThresholdPrice
A sqrtPriceX96 that acts as a slippage parameter for the swap that rebalances the inventory (to deposit maximal liquidity around the new price bounds).swapAmountBPS
Amount of inventory to swap represented as Basis Points of the remaining amount of the token to swap.zeroForOne
The direction of the rebalancing swap.
In order to generate the parameters for an executive rebalance one has to understand the flow of this operation. First, the Arrakis vault removes all the liquidity and fees earned. Then, it tries to deposit as much liquidity as possible around the new price range. Next, whatever is leftover is then swapped based on the swap parameters. Finally, another deposit of maximal liquidity to the position is attempted and any leftover sits in the contract balance waiting to be reinvested.
To generate the swap parameters for an executive rebalance tx, simulate the entire operation. It works like this:
1. Call getUnderlyingBalances
on the ArrakisVault to obtain amount0Current
and amount1Current
2. Compute amount0Liquidity
and amount1Liquidity
using LiquidityAmounts.sol library, the new position bounds, the current price and the current amounts from step 1.
3. Compute amount0Leftover
and amount1Leftover
with formula amount0Leftover = amount0Current - amount0Liquidity
. In most cases one of these values will be 0 (or very close to 0).
4. Use amount0Liquidity
and amount1Liquidity
to compute the current proportion of each asset needed.
5. Use the amount0Leftover
and amount1Leftover
and the proportion from previous step to compute which token to swap and the swapAmount.
6. Convert swapAmount to swapAmountBPS by doing swapAmount * 10000 / amountLeftover
for the token being swapped.
A complete example of this calculation can be found in this test file
updateManagerParams
Another important role of the manager
is to configure the manager parameters including those that restrict the functionality of Gelato Executors
. These parameters include how often Gelato bots can reinvest fees and withdraw manager fees, as well as other safety params like the slippage check. Only the manager can call updateManagerParams
.
Arguments:
newManagerFeeBPS
Change the cut of fees earned that accrue to manager in Basis Points (9750 max since 2.5% of fees go to Arrakis)newManagerTreasury
The treasury address where manager fees are auto withdrawn.newRebalanceBPS
The maximum percentage the auto fee reinvestment transaction cost can be compared to the fees earned in that feeToken. The percentage is given in Basis Points (where 10000 mean 100%). Example: if rebalanceBPS is 200 and the transaction fee is 10 USDC then the fees earned in USDC must be 500 UDSC or the transaction will revert.newSlippageBPS
The maximum percentage that the rebalance slippage can be from the TWAP.newSlippageInterval
length of time in seconds for to compute the TWAP (time weighted average price). I.e. 300 means a 5 minute average price for the vault.
transferOwnership
Standard transfer of the manager role to a new account.
Arguments: newOwner
the new account to act as manager.
toggleRestrictedMint
Make it so only the manager role can mint LP tokens. Useful for creating a "Wrapped" vault where LP token minting is restricted to the wrapper.
renounceOwnership
Burn the manager role and set all manager fees to 0.
Arrakis Subgraph
The Arrakis subgraph tracks relevant data for all Arrakis Positions created through the ArrakisFactory
createVault
method. Most relevant information about about a Arrakis position is indexed and queryable via the subgraph. Query URL is: https://api.thegraph.com/subgraphs/name/arrakisfinance/vault-v1-mainnet
Here is an example query which fetches all information about all Arrakis Positions:
id
: subgraph identifier for the vault (contract address)
blockCreated
: block Arrakis position was deployed
address
: contract address of Arrakis positions
uniswapPool
: contract address of Uniswap V3 pair
token0
: token0 info
token1
: token1 info
feeTier
: Uniswap V3 Pair fee tier (500, 3000, 10000)
liquidity
: amount of liquidity currently in Arrakis position
lowerTick
: current lower tick of Arrakis Position
upperTick
: current upper tick of Arrakis Position
totalSupply
: current total supply of Arrakis token
positionId
: Uniswap V3 ID of the Arrakis position
managerFee
: managerFee in BPS (cut of trading fees taken by manager)
name
: Arrakis token name
reranges
: info about historical V3 position bounds (past executiveRebalances)
snapshots
: a fee APR snapshot taken whenever mint/burn (whenever arrakis vault liquidity amount in uniswap changes). Multiply BigDecimal apr
by 100 to get as a percentage.
numSnapshots
: number of snapshots in the list
apr
: weighted average fee APR since inception of vault. Multiply BigDecimal averageApr
by 100 to get a percentage.
Contract Addresses
Ethereum Mainnet
Polygon
Optimism
Arbitrum
Last updated