ArrakisV2

ERC20 vault smart contract at the heart of this LP management system.

ArrakisV2 instances cannot be arbitrarily trusted. ArrakisV2 is the core tokenized vault contract that can be flexibly configured for multiple use-cases (by anyone, via the ArrakisV2Factory). There are trust assumptions on privileged roles owner & manager.Only certain implementations of these roles would provide trustless guarantees for all shareholders (i.e. where no party has a way to drain funds deposited into the vault by others)

Constant/Immutable Properties

nametypedescription

factory

address

UniswapV3Factory contract used to verify uniswap pool addresses

Public Properties

nametypedescription

token0

address

ERC20 token. token0 MUST be smaller than token1.

token1

address

ERC20 token. token1 MUST be greater than token0.

init0

uint256

Amount that defines the proportion of token0 required by first minter

init1

uint256

Amount that defines the proportion of token1 required by first minter

manager

address

Role responsible for calling rebalance function i.e. for market making activities managing vault holdings and Uniswap liquidity positions. Manager is a semi-trusted party that passes sensitive calldata. Manager smart contract should implement additional on-chain checks to achieve trustlessness.

managerFeeBPS

uint16

Amount of Uniswap V3 fees earned that are reserved for the manager (in basis points)

managerBalance0

uint256

Accumulated fees on token0 that can be retrieved by the manager

managerBalance1

uint256

Accumulated fees on token1 that can be retrieved by the manager

restrictedMint

address

Anyone can call mint function while restrictedMint is set to the zero-address, else only restrictedMint can call.

Internal Properties

nametypedescription

_owner

address

Owner of ArrakisV2 vault contract. Admin who assigns manager role, sets security parameters. Trusted party (for trustlessness this role should be burned after vault is configured or escrowed in some otherwise trusted account e.g. DAO Timelock)

_ranges

Range[]

Array of Uniswap V3 LP ranges that vault is tracking (all positions vault has created with liquidity>0)

_pools

AddressSet

Set of addresses of Uniswap V3 pools that manager can deploy liquidity into (owner can whitelist specific fee tiers)

_routers

AddressSet

Set of addresses that can be used as a swap router (owner can whitelist specific routers)

Structs

Range

nametypedescription

lowerTick

int24

lower Uniswap V3 tick boundary of position

upperTick

int24

upper Uniswap V3 tick boundary of position

feeTier

uint24

Uniswap V3 feeTier

PositionLiquidity

nametypedescription

liquidity

uint128

Uniswap V3 liquidity amount to mint/burn (pass uint128.max to signify "all" liquidity, for burns)

range

Range

Range and fee tier to mint/burn liquidity amount from

SwapPayload

nametypedescription

payload

bytes

low level swap payload

router

address

swap router to call payload on

amountIn

uint256

expected amountIn to swap (MUST forward less than or equal to this amount on swap)

expectedMinReturn

uint256

expected amountOut of swap (MUST receive greater than or equal to this amount on swap) (sensitive security parameter!)

zeroForOne

bool

directionality of swap (token0 -> token1 if true)

Rebalance

nametypedescription

burns

PositionLiquidity[]

Uniswap V3 liquidity to burn

mints

PositionLiquidity[]

Uniswap V3 liquidity to mint

swap

SwapPayload

Swap operation information

minBurn0

uint256

minimum amount of token0 burned across all burns

minBurn1

uint256

minimum amount of token1 burned across all burns

minDeposit0

uint256

minimum amount of token0 deposited across all mints (sensitive security parameter!)

minDeposit1

uint256

minimum amount of token1 deposited across all mints (sensitive security parameter!)

External Functions

mint

mint shares of an ArrakisV2 ERC20 LP token by depositing token0 and token1 in correct proportion. MUST approve ArrakisV2 contract to spend enough token0/token1 before call.

Don't call this method naively - it requires additional checks on-chain to be safe from sandwich attacks!

parameters :

nametypedescription

mintAmount

uint256

Number of Arrakis LP token shares to mint, requires deposit of token0 and/or token1

receiver

address

Receiver of minted Arrakis LP token shares

returns :

nametypedescription

amount0

uint256

Amount of token0 deposited to mint mintAmount of shares

amount1

uint256

Amount of token1 deposited to mint mintAmount of shares

modifiers :

  • reentrancy protection.

checks :

  • mintAmount should be higher than 0.

  • restrictedMint should be address(0), else restrictedMint must be the msg.sender.

events :

  • LogMint(address indexed receiver, uint256 mintAmount, uint256 amount0In, uint256 amount1In)

rebalance

This is the low-level entry point for manager to rebalance the vault. Has sensitive calldata that either needs to be checked on-chain in the manager contract implementation, or else manager must be otherwise trusted by the LP(s) to pass non-manipulable calldata.

ArrakisV2 vault holdings and liquidity can be rebalanced by manager account at any time. This function may do all or some of these operations:

  1. remove token0/token1 liquidity from existing Uniswap V3 Positions of choice into vault

  2. swap vault holdings (in either direction on the token pair) on any whitelisted swap router

  3. add token0/token1 from vault as liquidity into Uniswap V3 Positions of choice

parameters :

nametypedescription

rebalanceParams

Rebalance

struct that defines actions for rebalance. This may include: burning uni v3 liquidity, swapping tokens, minting uni v3 liquidity

modifiers :

  • only manager.

  • reentrancy protection.

checks :

  • if swapping, check swap router against whitelisted routers.

  • check that amounts withdrawn are not below minBurn amounts.

  • check that amounts deposited are not below minDeposit amounts.

events:

  • LogCollectedFees(uint256 fee0, uint256 fee1)

burn

burn ArrakisV2 ERC20 LP token shares to receive underlying token0 and token1

parameters :

nametypedescription

burnAmount

uint256

Amount of Arrakis LP token that user wants to burn

receiver

address

receiver of amount0 and amount1 of token0/1 after burning shares

returns :

nametypedescription

amount0

uint256

Amount of token0 withdrawn on burn of burnAmount shares

amount1

uint256

Amount of token1 withdrawn on burn of burnAmount shares

modifiers :

  • reentrancy protection.

checks :

  • check total supply is greater than 0.

  • if leftover on the vault is smaller than the amount0 and amount1, check burns array is not empty (need to burn some ranges to be able to send back amount0 and amount1 to receiver).

events :

  • LogCollectedFees(uint256 fee0, uint256 fee1)

  • LPBurned(address indexed user, uint256 burnAmount0, uint256 burnAmount1)

  • LogBurn(address indexed receiver, uint256 burnAmount, uint256 amount0Out, uint256 amount1Out)

withdrawManagerBalanace

Sends accrued manager balances of token0 and token1 to the manager account.

Note that owner has the ability to expropriate earned but uncollected fees of a manager by resetting the manager role. (Easy to eliminate this in the periphery, if it is not a desired feature)

events :

  • LogWithdrawManagerBalance(uint256 amount0, uint256 amount1)

getRanges

view the set of ranges where the vault has active Uniswap V3 positions

returns :

nametypedescription

ranges

Range[]

Array of Uniswap V3 LP ranges that vault is tracking (all positions vault has created with liquidity>0)

getPools

view the Uniswap V3 pools whitelisted for use by manager (when adding liquidity in rebalance method)

returns :

nametypedescription

pools

address[]

addresses of Uniswap V3 pools that manager can deploy liquidity into

getRouters

view the "swap router" contracts whitelisted for use by manager (when swapping in rebalance method)

returns :

nametypedescription

routers

address[]

addresses that can be used as a swap router

addPools

whitelist UniswapV3 pools of the desired fee tiers

parameters :

nametypedescription

feeTiers

uint24[]

Fee tiers to whitelist for use by manager

modifiers :

  • onlyOwner.

checks :

  • checks pool addresses on uniswap v3 factory from feeTier, token0, token1.

  • check that pool addresses are not zero address.

  • check that pool addresses are not already whitelisted.

events :

  • LogAddPools(uint24[] feeTiers)

removePools

remove Uniswap V3 pools from the whitelist

parameters :

nametypedescription

pools

address[]

Uniswap V3 pool addresses to remove from whitelist that manager was using.

modifiers :

  • should only be called by the owner.

checks :

  • check pools addresses are not equal to zero address.

  • check pools addresses are whitelisted pools.

events :

  • LogRemovePools(address[] pools)

whitelistRouters

add contract addresses to the whitelist of swap routers.

parameters :

nametypedescription

routers

address[]

Swap routers to whitelist for manager to use in rebalance method.

modifiers :

  • only owner.

checks :

  • check that router address is not token0 or token1.

  • check that router addresses are not already whitelisted.

events :

  • LogWhitelistRouters(address[] routers)

blacklistRouters

remove contract addresses from swap router whitelist

parameters :

nametypedescription

routers

address[]

Previously whitelisted routers to remove.

modifiers :

  • only owner

checks :

  • router addresses should be whitelisted.

events :

  • LogBlacklistRouters(address[] routers)

setInits

set token ratios for the initial mint of ArrakisV2 shares

parameters :

nametypedescription

init0

uint256

Initial ratio token0 (supplying exactly the init values would mint 1 LP token)

init1

uint256

Initial ratio token1 (supplying exactly the init values would mint 1 LP token)

checks:

  • checks that init0 or init1 is greater than zero

  • checks that totalSupply is 0

  • checks that caller is owner (if restrictedMint is unset) or else is restrictedMint address

events :

  • LogSetInits(uint256 init0, uint256 init1)

setManager

set the manager account that is permitted to call rebalance function and manage liquidity positions

parameters :

nametypedescription

manager

address

Only address with access rights to call rebalance vault method

modifiers :

  • only owner

events :

  • LogSetManager(address newManager)

setRestrictedMint

set restrictedMint account which (when set to non-zero address) is only account permitted to call mint function

parameters :

nametypedescription

restrictedMint

address

If set, only address with access rights to call mint method and setInits method. If unset, mint method unrestricted.

modifiers :

  • only owner

events :

  • LogRestrictedMint(address minter)

setManagerFeeBPS

set a percentage of Uniswap fees earned aside to accrue to the manager.

parameters :

nametypedescription

managerFeeBPS

uint16

Percent of Uniswap fees collected to accrue to manager, in Basis Points (10000 == 100%)

events:

  • LogSetManagerFeeBPS(uint16 managerFeeBPS)

uniswapV3MintCallback

Uniswap V3 callback function, calls us back on all IUniswapV3Pool.mint calls

parameters :

nametypedescription

amount0

uint256

Amount of token0 to forward to uniswap pool

amount1

uint256

Amount of token1 to forward to uniswap pool

checks :

  • check msg.sender is one of the whitelisted pools

initialize

initialize a new ArrakisV2 instance (called by ArrakisV2Factory on deployVault)

parameters :

nametypedescription

name

string

Name of ERC20 token

symbol

string

Symbol of ERC20 token

params

InitializePayload

Struct containing vault initialization parameters (see ArrakisV2Factory structs section)

modifiers :

  • initializer (only callable once)

checks :

  • check that at least one uniswap fee tier is set

  • check that tokens are not address(0)

  • check token0/token1 ordering

  • check that manager is not address(0)

  • check that init0 or init1 is greater than 0

events :

  • LogSetInits(uint256 init0, uint256 init1)

  • LogSetManager(address newManager)

  • LogAddPools(uint24[] feeTiers)

  • LogSetBurnBuffer(uint16 newBurnBuffer)

Inherited Standard Interfaces:

  • Ownable (transferOwnership)

  • ERC20 (transfer, approve, transferFrom, balanceOf etc)

Last updated