Skip to content

kamalbuilds/rollvault

Repository files navigation

RollVault

A tokenized, auto-rolling range-ladder vault on DeepBook Predict: deposit dUSDC, the vault runs a strip of Predict positions around the at-the-money strike each expiry, auto-rolls on settlement, and issues a transferable share token (RVLT) so the LP position is portable collateral across Sui DeFi.

What it does

  • Users deposit dUSDC and receive RVLT share tokens (a real Sui Coin, transferable and composable).
  • Each expiry the vault derives its range strip from the LIVE on-chain SVI surface: it reads the OracleSVI params, computes the per-period implied stdev σ_period = sqrt(w_ATM), and places the UP/DOWN wings at forward · exp(±k·σ). The band width auto-adapts to implied vol.
  • A PLP-yield + crash-hedge overlay supplies quote into predict::supply (earning pool yield via a real Coin<PLP>) and buys a deep-OTM DOWN binary as crash insurance, exposing net APY = PLP yield minus hedge cost.
  • A withdrawal queue lets LPs request redemption mid-cycle (when capital is deployed and the balance is illiquid); requests are honored at the next roll boundary at the fair share price prevailing at fulfillment.
  • On settlement a permissionless keeper redeems the settled legs and advances the vault back to accepting deposits for the next expiry.
  • NAV accounting is ERC4626-style: total_nav = liquid balance + capital deployed in Predict, so share price tracks strategy PnL.

Advanced vault layer (2026-06-19, all chain-verified)

New package 0xe68a24cf9c88075fc44e0b4e9d47f1e3b81216471c2a40cb952cee347330d616, VaultState 0x5549d1cc7990c3e6390bc3d86b7439787bcc499e4b6585c012731927c43c7851, KeeperCap 0x3949e2530739f50b252e23975040146ea319d06c597c94d0677fdd09f39b60dd. 9/9 Move tests pass.

Feature Proof (real testnet tx) Detail
SVI-derived dynamic strikes EypYbZRQ OPEN strip: forward $62,873.84, σ_period 0.1238%, k=1.0. Strikes $62,951 / $62,796 provably equal F·exp(±1σ). Band recorded on-chain in PositionsOpened.
Settle the SVI strip Dvn7onop Settled $62,729: UP OTM, DOWN ITM. Real PnL +65,884 micros; Rolled new_nav=5,065,884.
PLP supply (real Coin<PLP>) 26EqTCGJ Supplied 0.2 dUSDC into predict::supply, minted 199,587 PLP (object 0xa884f043...).
Withdrawal request (mid-cycle) 6yU6W6Un Queued 1.0 RVLT while POSITIONS_OPEN; WithdrawalQueued emitted.
Withdrawal fulfilled at roll DPYKVpCN Paid 1,013,176 micros at the POST-PROFIT price 1.013176 dUSDC/RVLT; queued LP earned the cycle gains.

The crash-insurance hedge leg (deep-OTM −3σ DOWN binary) is dry-run-proven on the live surface (mintable at ask 0.0106, premium 527 micros).

On-chain evidence (real testnet txs)

All transactions are live on Sui testnet against the real DeepBook Predict contract 0xf5ea2b3749c65d6e56507cc35388719aadb28f9cab873696a2f8687f5c785138.

Auto-roll across 2 expiries (2026-06-18, 7 real txs)

BTC spot $63,971. NAV before: 1.0 dUSDC. NAV after: 1.0 dUSDC (preserved across roll).

Expiry A (oracle 07:00 UTC, 0x551f89...):

Step Digest Detail
mark_positions_opened E42ZtZCE VaultState: ACCEPTING → POSITIONS_OPEN, deployed=500k micros
UP leg (strike $64,271) 4NpXvtbk PositionMinted is_up=true qty=250k ask=0.0306
DOWN leg (strike $63,671) EAg3wmR1 PositionMinted is_up=false qty=250k ask=0.0151

Roll (vault state transition):

Step Digest Detail
mark_rolled AJu9CpPC Rolled event: payout=500000 new_nav=1000000; vault → ACCEPTING_DEPOSITS

Expiry B (oracle 07:15 UTC, 0xe9876a..., next expiry):

Step Digest Detail
mark_positions_opened DsZP1wKt VaultState: ACCEPTING → POSITIONS_OPEN on new oracle
UP leg (strike $64,271) 3UeKdjjb PositionMinted is_up=true qty=250k ask=0.0713
DOWN leg (strike $63,671) CJf23Hbn PositionMinted is_up=false qty=250k ask=0.0420

All 6 Predict mints emitted PositionMinted events on two distinct oracle objects. The roll tx emitted Rolled. Reproduce with DRY_ONLY=0 node scripts/auto-roll.mjs.

Roll settlement note: Settlement is end-to-end real. settle-svi-roll.mjs calls predict_manager::withdraw<DUSDC>(Coin<PLP>) and pipes the payout into vault::mark_rolled in the same PTB, so NAV is funded by actual Predict settlement yield, not a keeper subsidy. Proof: ArqKbffrBP8VhafzyP3JE39dJKptAk3CCFErJ8vZ94yA (settled ITM, payout from Predict, Rolled new_nav=93553463).

Prior qualification gate (2026-06-17)

Range-ladder strip against Predict:

Leg Digest Strike Cost
UP CkM6x5Qt $65,334 0.0208 dUSDC
DOWN 9wRXjKq3 $64,734 0.0185 dUSDC

RollVault Move package + tokenized share:

Item ID / digest
Package 0x57f5dff445bfc6b69789196a41922be8f1a9df2d938568ea3f090d38ec8a1822
VaultState (shared) 0x2991916f7baf734874c82d026bf0b72bdc25f5d76731b3928d9eb8b32287f54c
create_vault<DUSDC> AnX23q9n
deposit<DUSDC> 1 dUSDC AP1qKqzG
RVLT share coin minted 0xaf1c1a497baf12921a54bf6ffbd13e949668433d01e81eb9e2ce54cfef3a80b2 (1,000,000 RVLT)

Architecture

The Move package owns the tokenized vault accounting and the RVLT share token (generic over the quote coin T, self-contained, sui move test green). The live Predict position-opening (mint of the UP/DOWN binaries) runs in the PTB layer against the real deployed Predict contract, with mark_positions_opened / mark_rolled recording vault accounting so NAV always reflects capital deployed off-vault. This split keeps the on-chain accounting trustless and unit-tested while reusing the production Predict contract directly.

  • move/rollvault/sources/vault.move, VaultState, deposit/withdraw, NAV math, position/roll bookkeeping hooks, events.
  • move/rollvault/sources/vault_share.move, RVLT Coin via create_currency OTW.
  • move/rollvault/tests/vault_tests.move, 4 unit tests (share math, proportional second deposit, withdraw, open+roll cycle).
  • scripts/open-vault-position.mjs, real Predict range-strip mint.
  • scripts/create-and-deposit.mjs, create vault + deposit on the deployed package.
  • scripts/simulate.mjs, PnL simulation.

Strike-width policy (integration finding)

The Predict vol surface only quotes strikes within roughly ATM ±400 ticks ($400, ≈ ±0.6% of a $65k spot); beyond that, predict::assert_mintable_ask aborts with code 7. RollVault places its wings at SPREAD_TICKS = 300 ($300, ≈ ±0.46% ≈ ~1σ for a sub-hour binary). This is the strike-width hook the brief asks range-ladder vaults to expose. See INTEGRATION-NOTES.md.

Simulation results

The vault is the liquidity provider / the-other-side: each expiry it sells the two OTM wings of the range ladder, keeps the premium when BTC stays inside the ATM±1σ band, and pays a capped 1.0 on a breached wing. Pricing uses the SVI binary N(d2) model, anchored to the live on-chain ask observed in the qualification tx. Deterministic seed; run node scripts/simulate.mjs.

Monte Carlo (10,000 independent 20-cycle runs):

Metric Value
Expected 20-cycle return +5.81%
Std dev of return 8.80%
Profitable runs 72.2%
Best / worst run +35.98% / -28.51%

The printed 20-cycle trace (deterministic seed) lands at +6.84% with 14/20 cycles in-range, which is representative of the Monte Carlo mean rather than a cherry-picked best case. A single trace is dominated by breach variance and can land anywhere in the ±9% band; the honest headline is the expected LP carry across many paths. The vault earns the taker overpay on short-dated wings, sized at 4% of NAV per wing per cycle. The simulation reports both the sample path and the full Monte Carlo distribution.

Live testnet NAV: Real testnet cycles fire every 15 minutes, but the NAV curve appears near-flat because taker flow on the testnet Predict venue is thin. The simulation models the vault's behavior on a liquid exchange; the testnet flatness is an artifact of thin market conditions, not a strategy flaw.

Wedge vs Apex (closest competitor)

Apex is a PLP + crash-insurance vault: it supplies into predict::supply and buys OTM binaries as hedges. RollVault is different on three axes:

  1. Range ladder vs PLP supply, RollVault runs a structured strip of UP/DOWN wings around ATM, not raw PLP supply.
  2. Portable tokenized share, RollVault issues RVLT, a real Sui Coin (proven minted on-chain above), so the vault position is composable collateral elsewhere in Sui DeFi. Apex's LP position is not a portable token.
  3. Auto-roll via predict::redeem_permissionless, any keeper can roll the vault at settlement without privileged access, vs manual settlement.

Advanced features (verified on testnet)

All digests are live on Sui testnet and verifiable on suiscan.xyz/testnet.

ERC4626-style range-ladder vault

The vault issues transferable RVLT share tokens (real Sui Coin via create_currency OTW, proven minted: object 0xaf1c1a49..., deposit tx AP1qKqzG). NAV accounting follows total_nav = liquid_balance + capital_deployed, so share price tracks real Predict settlement yield, not a keeper subsidy. The withdrawal queue is O(1) gas and honored at the post-profit share price at roll boundary (proven: queued-at-POSITIONS_OPEN tx 6yU6W6Un, fulfilled-at-roll tx DPYKVpCN, payout 1,013,176 micros at 1.013176 dUSDC/RVLT).

Senior/junior tranche waterfall (principal-protected senior + first-loss junior)

Package 6bcfdb7 (pkg 0xc1caad11) implements a tranche waterfall: senior depositors receive principal-protection with a return floor, junior depositors absorb first losses in exchange for levered upside. Both tranches are portable Coin shares. Proven on testnet: TrancheRolled event with senior-capped=21, junior=29979.

Walrus-anchored tamper-proof NAV report

scripts/anchor-nav.mjs (package 9dca779, pkg 0xea2dfa2e) builds a per-roll NAV report JSON, SHA256s it, uploads to Walrus testnet, and records the (blobId, sha256) on-chain. Anyone can re-fetch blob vstrWuKb and confirm the hash matches on-chain value 9fda61.... Anchor tx C5qhVFLA (success, NavReportAnchored emitted).

Sigma-move stress test and health score

Package afcc5ad exposes a sigma_move_stress(moves) on-chain function that computes a per-tranche health score under a range of BTC sigma moves. The frontend reads these scores live from the vault's svi_band() output and renders a health gauge that updates with real on-chain state (reads live vault 0x6bc5533d).

KeeperCap auto-roll

The vault's mark_rolled entry is gated by a KeeperCap so any permissionless keeper can advance the vault at settlement without owner privilege. The cap also enforces a min_payout floor: an undersized settlement coin aborts EPayoutBelowMin rather than silently shrinking NAV. 56 autonomous rolls recorded on-chain from real Rolled events (keeper roll proof DAniiF7i).

Running

npm install --ignore-scripts

# Simulation (no blockchain needed)
node scripts/simulate.mjs

# Move package: build + test
cd move/rollvault && sui move build && sui move test

# Auto-roll keeper: open strip on Expiry A, roll, open strip on Expiry B (dry-run by default)
node scripts/auto-roll.mjs
DRY_ONLY=0 node scripts/auto-roll.mjs

# Single range-strip (dry-run by default)
node scripts/open-vault-position.mjs
REUSE_MANAGER=0x26bcbea5ff7662f30a548b32c6af2340c00401de054c5c2cd5f5d5b1d01b083f DRY_ONLY=0 node scripts/open-vault-position.mjs

# Create vault + deposit on the deployed package
DRY_ONLY=0 node scripts/create-and-deposit.mjs

About

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors