A ZKDepth vault takes your tokens, runs a liquidity position for you and gives you shares of it. This chapter covers LPVault, one Uniswap v3 position that takes a single token, and DlmmVault and StockVault, which sit on ZKDepth's own pools.
Choosing a vault
LPVault | DlmmVault | StockVault | |
|---|---|---|---|
| Position | one Uniswap v3 range | bins around the active one | a base and a limit range in a stock pool |
| You bring | one token | both tokens, or one through the zap | both tokens |
| Re-centred by | anyone | the factory's keeper or the owner | the factory's keeper or the owner |
| Fee to ZKDepth | 10 % of harvested fees | none of its own | none of its own |
| Created by | anyone | the protocol owner | the protocol owner |
Hedged vaults and structured notes are built on LPVault.
Depositing and withdrawing
deposit(assets, receiver) mints shares with three more decimals than the asset. The vault adds its idle balance to the position once that balance is worth at least 0.5 % of totalAssets(), and until then it still counts in the share price.
totalAssets() values the idle tokens and what the position would return if closed now, and leaves out uncollected trading fees, so a harvest can only add value.
withdraw and redeem burn your shares and pull liquidity out. If the vault still holds too little asset, it sells the other leg with a floor of the spot quote less maxSlippageBps. If that is not enough, the call reverts Shortfall rather than pay less than the preview. A withdrawal takes no fee.
The price check
Spot is the price an attacker can move inside a block. So LPVault runs TwapGuard.check(pool) before every deposit, withdrawal and rebalance:
- The pool's observation ring must reach back at least 10 min, or the call reverts
TwapWindowTooShort. - Spot must sit within 300 bps of the mean over 30 min, or over the history there is, or the call reverts
PriceDeviation.
After a jump of more than 3 %, these calls revert until the mean catches up. VaultFactory grows each pool's ring to 60 slots at creation. The check is skipped while a vault has no shares, so the first depositor can get in.
Harvest and rebalance
Anyone may make either call. harvest() collects every fee the position has earned and runs no price check, because it moves no principal. rebalance() mints a new position centred on the current tick, once the tick is past a range edge by the hysteresis. ZKDepth's keeper bot sends harvest for each deployed vault every 6 h.
| Name | Allowed | Default | Effect |
|---|---|---|---|
widthTicks | multiple of the spacing | 2 x 2231 | Full range width, about ±25 %. |
hysteresisTicks | 0 or more | 10 spacings | How far past an edge the tick must sit before a rebalance. |
minInterval | seconds | 6 h | Least time between two harvests, and between two rebalances. |
maxSlippageBps | 0 - 9999 | 100 | Floor on every swap, against a spot quote. |
VaultFactory.createV3Vault is open to anyone, so the app shows only the vaults in the deployment manifest and those graduation created. The deploy creates ZKDepth ETH Vault and ZKDepth USDG Vault on the WETH/USDG 0.05 % pool.
Vaults on ZKDepth pools
DlmmVault and StockVault never swap and charge no fee of their own. Deposits and rebalances stop while the protocol is paused, and withdrawals never do. Only the factory's keeper or the protocol owner can rebalance either, at most every 5 min.
A DlmmVault is due a rebalance once the active bin is more than half the half-width from the centre, and ZKDepth's bot waits until that has held for 120 s. DlmmVaultZap turns one token, ETH included, into a deposit, and a withdrawal back into one token.
A StockVault centres a base range on the oracle price, wider while the market is closed. What the base cannot take waits in a one-sided limit range next to it.
contracts/src/LPVault.soltotalAssets, deposit, withdraw, harvest, rebalancecontracts/src/libraries/TwapGuard.solthe price check and its constantscontracts/src/venue/vaults/DlmmVault.solthe DLMM vault: deposit, withdraw, rebalance, shapes