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
name | type | description |
---|---|---|
factory | address | UniswapV3Factory contract used to verify uniswap pool addresses |
Public Properties
name | type | description |
---|---|---|
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 |
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 |
Internal Properties
name | type | description |
---|---|---|
_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 |
_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
name | type | description |
---|---|---|
lowerTick | int24 | lower Uniswap V3 tick boundary of position |
upperTick | int24 | upper Uniswap V3 tick boundary of position |
feeTier | uint24 | Uniswap V3 feeTier |
PositionLiquidity
name | type | description |
---|---|---|
liquidity | uint128 | Uniswap V3 liquidity amount to mint/burn (pass |
range | Range | Range and fee tier to mint/burn |
SwapPayload
name | type | description |
---|---|---|
payload | bytes | low level swap payload |
router | address | swap router to call |
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 |
Rebalance
name | type | description |
---|---|---|
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 |
minBurn1 | uint256 | minimum amount of token1 burned across all |
minDeposit0 | uint256 | minimum amount of token0 deposited across all |
minDeposit1 | uint256 | minimum amount of token1 deposited across all |
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 :
name | type | description |
---|---|---|
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 :
name | type | description |
---|---|---|
amount0 | uint256 | Amount of token0 deposited to mint |
amount1 | uint256 | Amount of token1 deposited to mint |
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 :
name | type | description |
---|---|---|
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 :
name | type | description |
---|---|---|
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 :
name | type | description |
---|---|---|
amount0 | uint256 | Amount of token0 withdrawn on burn of |
amount1 | uint256 | Amount of token1 withdrawn on burn of |
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 :
name | type | description |
---|---|---|
ranges | Range[] | Array of Uniswap V3 LP ranges that vault is tracking (all positions vault has created with |
getPools
view the Uniswap V3 pools whitelisted for use by manager (when adding liquidity in rebalance
method)
returns :
name | type | description |
---|---|---|
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 :
name | type | description |
---|---|---|
routers | address[] | addresses that can be used as a swap router |
addPools
whitelist UniswapV3 pools of the desired fee tiers
parameters :
name | type | description |
---|---|---|
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 :
name | type | description |
---|---|---|
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 :
name | type | description |
---|---|---|
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 :
name | type | description |
---|---|---|
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 :
name | type | description |
---|---|---|
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 :
name | type | description |
---|---|---|
manager | address | Only address with access rights to call |
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 :
name | type | description |
---|---|---|
restrictedMint | address | If set, only address with access rights to call |
modifiers :
only owner
events :
LogRestrictedMint(address minter)
setManagerFeeBPS
set a percentage of Uniswap fees earned aside to accrue to the manager.
parameters :
name | type | description |
---|---|---|
managerFeeBPS | uint16 | Percent of Uniswap fees collected to accrue to manager, in Basis Points ( |
events:
LogSetManagerFeeBPS(uint16 managerFeeBPS)
uniswapV3MintCallback
Uniswap V3 callback function, calls us back on all IUniswapV3Pool.mint calls
parameters :
name | type | description |
---|---|---|
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 | type | description |
---|---|---|
name | string | Name of ERC20 token |
symbol | string | Symbol of ERC20 token |
params | InitializePayload | Struct containing vault initialization parameters (see |
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