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
factory
address
UniswapV3Factory contract used to verify uniswap pool addresses
Public Properties
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
_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
lowerTick
int24
lower Uniswap V3 tick boundary of position
upperTick
int24
upper Uniswap V3 tick boundary of position
feeTier
uint24
Uniswap V3 feeTier
PositionLiquidity
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
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
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 :
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 :
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:
remove token0/token1 liquidity from existing Uniswap V3 Positions of choice into vault
swap vault holdings (in either direction on the token pair) on any whitelisted swap router
add token0/token1 from vault as liquidity into Uniswap V3 Positions of choice
parameters :
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 :
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 :
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 :
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 :
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 :
routers
address[]
addresses that can be used as a swap router
addPools
whitelist UniswapV3 pools of the desired fee tiers
parameters :
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 :
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 :
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 :
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 :
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 :
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 :
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 :
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 :
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 :
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