feat(hedge): sketch CappedSynth — margined, capped, RFQ-settled synthetic#43
feat(hedge): sketch CappedSynth — margined, capped, RFQ-settled synthetic#43tiero wants to merge 10 commits into
Conversation
Perpetual, BTC-settled, fully-collateralized market-maker inventory hedge generalizing stability_vault.ark: a desk converts residual BTC inventory into a delta-flat fiat claim (claim leg) while a treasury holds the BTC long leg and earns funding. Oracle-marked, no liquidation, one instance per BTC/<fiat> pair. - examples/hedging/inventory_hedge.ark (+ compiled .json): transfer, updateFunding, addCapital, removeCapital, claimExit, longExit (12 tapleaves). - tests/inventory_hedge_test.rs: roundtrip (both variants, non-empty witness schemas), oracle-path checks, claimExit clamp branches, <SERVER_KEY> injection, updatedAt-stripped determinism. - docs/mm-residual-hedge.md (design note) + docs/hedging/inventory_hedge_tx_flows.md (per-function tx layouts). - playground: Hedging project folder wired in main.js. https://claude.ai/code/session_01E3fpVJfLdM3ye3ZWy5VxGg
Merge docs/hedging/inventory_hedge_tx_flows.md into docs/mm-residual-hedge.md as 'Part II — Transaction flows', cross-referencing the design sections (§2/§4/§6/ §9). Remove the standalone file and point the playground Hedging folder at the single doc. https://claude.ai/code/session_01E3fpVJfLdM3ye3ZWy5VxGg
Drop the Exit suffix: claimExit -> redeem (desk redeems its fiat claim for BTC), longExit -> withdraw (treasury-driven settlement). Update the contract, tests, and the Part II transaction-flow doc. https://claude.ai/code/session_01E3fpVJfLdM3ye3ZWy5VxGg
Add require(newTargetFiat > 0) in removeCapital so a claim driven non-positive by a negative *initial* funding rate (not prevented at construction) can't make minCollateral <= 0 and trivially pass the ratio check — which would let the long leg drain the vault. Matches the existing updateFunding guard. Deliberately NOT added to redeem/withdraw: their claimRaw <= 0 clamp branch is the correct terminal settlement for a wiped claim (all collateral to the long leg); a hard require there would abort a legitimate withdraw. Documented inline. Also: clarify fundingRatePerSec doc (runtime >= 0; negative only possible at construction, unsupported), and note split/merge are deferred (design doc Part II). https://claude.ai/code/session_01E3fpVJfLdM3ye3ZWy5VxGg
- tests: assert the oracle message is RECONSTRUCTED on-chain (>=2 OP_CAT + OP_SHA256), matching stability_vault_test, so a compiler regression that drops cat/hash can't slip the replay guard; add addCapital-must-not-call-oracle negative test (code-review finding 5). - tests: reword redeem clamp-branch comment — the dust guard IS the third OP_IF, not a fourth branch (CodeRabbit nitpick). - docs: add 'text' language tags to fenced code blocks (markdown-lint nitpick). https://claude.ai/code/session_01E3fpVJfLdM3ye3ZWy5VxGg
Per design decision (leave logic as-is, document only): - updateFunding: note the known limitation that a negative *initial* rate bricks repricing (require(delta > 0) can't pass); funds aren't locked since redeem/withdraw still settle; a validating factory would seal it off. - Settlement math: note the fail-closed int64 ceiling (~9.2e10 minor units / ~$922M) on claimRaw, inherited verbatim from stability_vault.ark — overflow aborts via OP_MUL64+OP_VERIFY, never a wrong payout. Split-division deferred (no modulo operator; avoid diverging from the audited reference). https://claude.ai/code/session_01E3fpVJfLdM3ye3ZWy5VxGg
…dback) A passive provider settling at a lagging oracle mark is adversely selected: the settlement initiator holds a free option on the oracle delay, which is why oracle-priced AMMs died on Ethereum (picked off when oracle error > fee, ignored when below). Stability-style lending tolerates the 0.2-0.3% enter/exit premium because settlement is rare; a hedging book may not. - design doc: new §9.b spelling out the problem, why §6 internalization is load-bearing (not an optimization), that the dropped exit fee is only sound desk<->own-treasury, that 'no perp-spot basis' needs qualification, and that the §8 order-book/RFQ layer is closer to required than optional for any public version. - contract header: trust-scope note on fee-free redeem/withdraw — reinstate seekerExitFee for any external counterparty. https://claude.ai/code/session_01E3fpVJfLdM3ye3ZWy5VxGg
CodeRabbit finding: the constructor cannot validate collateralRatioPct, and a negative ratio (<= -100) makes minCollateral non-positive so the ratio check trivially passes — the long leg could drain a live claim. Add require(collateralRatioPct >= 0), the same in-function defense-in-depth pattern as the existing newTargetFiat guard. StabilityOffer seals this at take() time; with no factory here the in-function guard is the equivalent. https://claude.ai/code/session_01E3fpVJfLdM3ye3ZWy5VxGg
…etic
A design alternative to InventoryHedge explored in discussion: a perpetual
BTC-settled *margined* synthetic (bounded CFD) rather than a fully-funded
forward. Three deliberate changes over InventoryHedge:
1. PnL struck against an entryPrice with per-leg margin, so the posted pot is
margin (< notional) — the capital efficiency a desk wants. Payout clamps
into [0, totalCollateral], so each leg's loss is bounded by its own margin
and there is no liquidation engine to run (the rung that fits Arkade's
settlement-container model).
2. Headline path settle() is COOPERATIVE: both legs co-sign the price, no
oracle, hence zero adverse selection (doc 9.b).
3. The oracle path survives only as a fee'd fallback (settleOracleClaim),
charging the adverse-selection premium to the initiator.
Marked SKETCH: funding resizes notional (inherited) rather than transferring
margin; only the claim-initiated fallback is written; no removeMargin, no price
collar / cooperative-settle timeout. Compiles; covered by the example-
enumerating roundtrip/asm tests. Not wired into a dedicated test or the
playground registry yet.
https://claude.ai/code/session_01E3fpVJfLdM3ye3ZWy5VxGg
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Playground PreviewA live preview of this PR's playground is available at:
|
Standalone doc for the capped-synthetic sketch, cross-linking mm-residual-hedge.md §9.b (adverse selection). Covers: why a margined instrument, the forward/capped/perp design-rung table, the margin/PnL bound that removes the need for a liquidation engine, cooperative settle vs. fee'd oracle fallback, the RFQ price-discovery boundary, the leaf table, and the deliberately-deferred list. https://claude.ai/code/session_01E3fpVJfLdM3ye3ZWy5VxGg
What this is
A design sketch (not a finished feature) exploring a capital-efficient alternative to
InventoryHedge(#41): a perpetual, BTC-settled margined synthetic — a bounded contract-for-difference — rather than a fully-funded forward.It is
InventoryHedgewith three deliberate changes:entryPrice, with per-leg margin, so the posted pot is margin (< notional) — the capital efficiency a market-making desk actually wants when hedging residual delta. Payout clamps into[0, totalCollateral], so each leg's loss is bounded by its own margin.settle()is cooperative — both legs co-sign the settlement price, so there is no oracle and therefore zero adverse selection (see feat: InventoryHedge — market-maker inventory-hedging vault #41 design doc §9.b).settleOracleClaim()survives only for an unresponsive counterparty and charges the adverse-selection premium (exitFeeBps) to the initiator instead of waving it away.Margin / PnL model (claim leg = short BTC / long fiat)
Leaves
transferaddMarginupdateFundingsettlesettleOracleClaimexitFeeBpsDeliberately deferred (it's a sketch)
removeMargin(needs an oracle MTM check likeremoveCapital).tx.time) gating the fallback.compilation_roundtrip/asm_structuralsuites.Validation
cargo fmt --checkcleancargo testgreen (the example-enumerating tests pick upcapped_synth.ark)checkSigFromStackconfined tosettleOracleClaimonly — the cooperativesettlecarries no oracle in either variant, matchingInventoryHedge's redeem/withdraw variant split.Relationship to #41
Independent instrument; #41 is unchanged. If the direction is wanted, the follow-up is: dedicated tests, playground registration, a
docs/mm-residual-hedge.md§11 (forward / capped-synthetic / perp comparison), and the deferred pieces above.https://claude.ai/code/session_01E3fpVJfLdM3ye3ZWy5VxGg
Generated by Claude Code