Desk
Purpose
Section titled “Purpose”A series is only useful if both legs fill. The Desk pools USDG and, on governance instruction, subscribes to COUPON when SHIELD demand exceeds COUPON demand, so stock holders can always find some protection to buy. Desk depositors earn the coupons (and take the note-buyer’s risk) on the notional the Desk fills.
Structure
Section titled “Structure”fact Desk is an ERC-4626 vault over USDG (reconciled with contracts/src/token/Desk.sol).
| Property | Value |
|---|---|
| Deposits | Open (deposit/mint), pausable by guardian |
| NAV | totalAssets = idle USDG + deployed principal + held Stock Token value (unharvested coupons excluded, conservative) |
| Fills | fillCoupon(seriesId, amount), owner (timelock) only, only while S > D during Subscription |
| Caps | Caps{perSeriesCapBps, perUnderlyingCapBps, totalDeployedCapBps} as bps of totalAssets; DeployToken.s.sol sets 1,000 / 2,500 / 6,000. A breach reverts CapExceeded(cap, requested, limit) with cap one of "perSeries", "perUnderlying", "totalDeployed" |
| Utilisation | utilisationBps = deployed × 1e4 / totalAssets |
| Withdrawals | Immediate up to idle USDG; otherwise FIFO requestWithdraw(shares, receiver) queue filled by processQueue(n) as series settle and coupons are harvested |
| Stock on breach | Held and valued at the Treasury feed; governance may liquidateToTreasury at feed price (Treasury.StockPurchased) |
| Harvest | harvest(seriesId), permissionless: claims coupons, redeems or refunds, updates deployed |
utilisationBps feeds the bond discount: when the Desk is heavily deployed, bonds cheapen to raise Treasury reserves.
Worked example
Section titled “Worked example”illustrative Desk totalAssets 4,000,000 USDG (2,300,000 idle, 1,500,000 deployed, 200,000 held stock). NVDA series: SHIELD 900,000, COUPON 500,000. The Desk already holds 200,000 in another NVDA series.
| Constraint | Room |
|---|---|
Gap S − D | 400,000 |
| Per series 10% | 400,000 − 0 = 400,000 |
| Per underlying 25% | 1,000,000 − 200,000 = 800,000 |
| Total 60% | 2,400,000 − 1,500,000 = 900,000 |
| Idle USDG | 2,300,000 |
| Fillable | 400,000 |
After filling, D = 900,000 = S, the series matches fully at strike (subject to notionalCap), the Desk holds 400,000 COUPON units, deployed = 1,900,000 and utilisation is 47.5%.
Withdrawal queue
Section titled “Withdrawal queue”maxWithdraw(owner)is bounded byidleAssets(). Withdrawing up to that amount is a normal ERC-4626withdraw/redeem.- Beyond idle,
requestWithdraw(shares, receiver)escrows shares and appends a request.cancelWithdrawRequest(id)returns them. - Anyone may call
processQueue(n)to fill up tonrequests from idle USDG in FIFO order at the current share price.queueProcessLimitboundsn.
Withdrawals and queue processing are not pausable; maxDeposit/maxMint return zero while paused. processQueue(n) reverts QueueLimitTooHigh above queueProcessLimit (constructor default 10, hard maximum MAX_QUEUE_PROCESS = 50).
Risk to Desk depositors
Section titled “Risk to Desk depositors”The Desk is a note buyer. It earns coupons while the barrier holds and receives stock at s0 if the barrier breaks at maturity, at which point NAV reflects the feed value of that stock. Depositors bear market risk on the underlyings the Desk has filled, concentration risk bounded by the caps, and liquidity risk when most assets are deployed. Desk shares are not NOTE and carry no governance rights.
The Desk never buys SHIELD and never fills a series above its notionalCap.
Governance surface
Section titled “Governance surface”| Function | Effect |
|---|---|
setCaps(Caps) | Per-series, per-underlying, total caps |
setMaxFeedStaleness(seconds) | Valuation staleness bound for held stock |
setQueueProcessLimit(n) | Max requests per processQueue |
fillCoupon(seriesId, amount) | Subscribe to COUPON within caps |
liquidateToTreasury(token, amount) | Sell held stock to the Treasury at feed value |
sweepToken(token, to, amount) | Recover tokens that are not part of NAV |
setGaugeController(controller) | Sets the single address allowed to steer per-underlying caps; emits GaugeControllerUpdated |
setPerUnderlyingCapFromGauge(underlying, bps) | Gauge controller only, once per week per underlying via GaugeController.syncCaps; bounds 100 to 4,000 bps; emits PerUnderlyingCapSet |
Gauge-steered caps
Section titled “Gauge-steered caps”fact The governed Caps.perUnderlyingCapBps is a ceiling. Each week GaugeController.syncCaps writes a per-underlying value derived from the series-gauge vote, and effectivePerUnderlyingCapBps(underlying) returns the lower of the governed cap and the gauge value (min). fillCoupon uses the effective value; an underlying with no gauge, or one that has not been synced yet, keeps the governed cap. The mechanics and a worked example are under Gauges.
The module is a UUPS proxy whose implementation can only be replaced by the 7-day UpgradeTimelock; see Upgradeability and recovery.
Exit guard and marked NAV
Section titled “Exit guard and marked NAV”fact Share price is computed from a marked NAV: deployed principal is valued at the Treasury’s live mark for each series (par for series not yet live) plus coupons accrued but not yet harvested, so depositing just before a harvest or withdrawing just before a mark-down no longer transfers value between holders. Direct withdraw/redeem require the shares to have been held for minHold (default 1 day, governance-settable up to 7 days) and are refused while a settled series is waiting to be harvested; the withdrawal queue is exempt from the hold and has its USDG reserved at request time. Bonds read the Desk’s utilisation as of the previous block.