Protocol
Architecture

uUSDv

A Token-2022 token whose every unit is a share of the USDv the uUSDv program holds, worth more USDv as Solomon Labs' rewards are released to holders at one price for wrapping and unwrapping.

uUSDv (Umbra USDv) carries Solomon Labs' USDv yield into places USDv itself earns nothing. One uUSDv is a share of the USDv the uUSDv program holds. Solomon pays rewards to the program's yield account, and the program releases them to every share, so a uUSDv balance never changes while each unit becomes worth more USDv. Anyone may wrap or unwrap at any time, without permission, and use uUSDv anywhere a Token-2022 token goes.

How the price works

A share's price is the program's assets divided by the share count. Wrapping buys shares at that price, and unwrapping sells them at that price. Both round in favour of the shares that stay, so no sequence of wraps, unwraps and payments within one moment returns more USDv than went in.

The assets are the USDv the program holds, less everything not yet released. A payment from Solomon raises the balance at once but the price only gradually: it releases linearly over a release window fixed at launch, counted from when it arrived. Someone who wraps just before a payment and unwraps just after it earns only the seconds they held. Payments that arrive within the same fourteenth of a window share one release schedule, so the program needs at most fifteen of them.

Releases are capped. The release cap, a yearly rate between 5% and 20% of the assets set when the program is initialised, limits how fast income becomes price. Income beyond what the cap allows over one window waits in a backlog, which drains only at the part of the cap that the scheduled releases leave unused. A large donation, or Solomon catching up on missed payments, therefore raises the price at the cap's pace rather than at once.

When someone unwraps, they give up their share of the income still releasing. That share moves to the backlog, so those who stay never collect it at once: it releases at the cap's spare room, which can be sooner than the payment it came from would have released, but never faster than the cap.

The window must be at least as long as the longest gap between Solomon's payments, late payments included. A shorter window lets a well-timed entrant collect part of a payment without having held through it. Measurements behind these choices, from the design's simulator, are in the program's property tests.

The formulas

All amounts are raw USDv units, which uUSDv shares since both have six decimals. CC is the USDv the program has booked in its two accounts, SS the uUSDv share count, WW the release window in seconds, cc the release cap in basis points and Y=31 536 000Y = 31\,536\,000, the seconds in a 365-day year. Time tt is the cluster's clock.

Assets. The price counts the USDv held, less the income still releasing in the buckets, U(t)U(t), and the backlog not yet drained, B(t)B(t):

A(t)=C−U(t)−B(t),P(t)=A(t)SA(t) = C - U(t) - B(t), \qquad P(t) = \frac{A(t)}{S}

P(t)P(t) is the USDv one uUSDv is worth.

Release. A bucket holding aia_i that started releasing at sis_i has left, at time tt:

Ui(t)=ai⋅min⁡(W, max⁡(0, si+W−t))W,U(t)=∑iUi(t)U_i(t) = a_i \cdot \frac{\min\bigl(W,\ \max(0,\ s_i + W - t)\bigr)}{W}, \qquad U(t) = \sum_i U_i(t)

Wrap and unwrap. Unwrapping ss shares pays, and wrapping dd USDv mints:

payout=⌊s⋅Aredeem(t)S⌋,shares=⌊d⋅SAmint(t)⌋\text{payout} = \left\lfloor \frac{s \cdot A_{\text{redeem}}(t)}{S} \right\rfloor, \qquad \text{shares} = \left\lfloor \frac{d \cdot S}{A_{\text{mint}}(t)} \right\rfloor

AredeemA_{\text{redeem}} rounds each UiU_i up and AmintA_{\text{mint}} rounds each down, so both sides round in favour of the shares that stay. The two differ by at most one raw unit per bucket.

The cap. The cap releases at most this much a second, and this much over one window:

rcap=A⋅c104⋅Y,RW=⌊A⋅c⋅W104⋅Y⌋r_{\text{cap}} = \frac{A \cdot c}{10^4 \cdot Y}, \qquad R_W = \left\lfloor \frac{A \cdot c \cdot W}{10^4 \cdot Y} \right\rfloor

Income. A payment II found by a checkpoint goes to the current slot's bucket up to the room the cap leaves over one window, and the rest to the backlog:

Ibucket=min⁡(I, max⁡(0, RW−U)),Ibacklog=I−IbucketI_{\text{bucket}} = \min\bigl(I,\ \max(0,\ R_W - U)\bigr), \qquad I_{\text{backlog}} = I - I_{\text{bucket}}

Backlog. The backlog drains at whatever part of the cap the buckets leave unused, until it is empty. rcapr_{\text{cap}} is fixed at the assets of the last operation:

dBdt=−max⁡(0, rcap−∑i releasingaiW)\frac{dB}{dt} = -\max\Bigl(0,\ r_{\text{cap}} - \sum_{i \text{ releasing}} \frac{a_i}{W}\Bigr)

Leaving. An unwrap of ss shares scales every bucket by S−sS\frac{S - s}{S}, and what that removes from UU joins the backlog, so the price does not move when someone leaves.

The freeze

Only an unwrap moves USDv out of the program's two accounts, and the program records each account's balance after every wrap and unwrap. Before doing anything else, every wrap, unwrap and checkpoint compares those records with the real balances. If either account holds less than it should, even by one raw unit and even when the other account rose by as much, USDv has left without an unwrap, which only Solomon's powers over USDv could do. The program then freezes: nothing can be wrapped or unwrapped until governance unfreezes it. Solomon freezing either account freezes the program the same way. Permanent counters record every unit that ever left each account without an unwrap.

A refused wrap or unwrap cannot record anything, because a failed instruction changes nothing. The next one finds the same shortfall and is refused too, and the first checkpoint records the freeze for good. Anyone may call a checkpoint.

The missing USDv is taken first from the backlog, then from the income still releasing, and only then from the price, where the program records it as a loss. While the program is frozen, USDv that arrives repays that loss straight to the price. Nobody can enter or leave in the meantime, so a repayment reaches exactly the holders who bore the loss, at once.

Governance unfreezes the program through the timelock. Its proposal names the freeze it ends and when that freeze began, so every new outflow is a new freeze that an earlier proposal cannot end. An unfreeze is refused while either account is still frozen, and while a loss is still outstanding, unless the proposal writes the rest off. A write-off declares the loss final: USDv that arrives afterwards releases like any other income, because with wrapping open an instant repayment could be timed by a newcomer. If a loss leaves the shares worth nothing, anything that arrives goes straight to the price, so restitution can never be locked away.

Instructions

Wrap

Moves USDv from any account the signer owns or is delegated, and mints the shares it buys to any uUSDv account. The program first books any payment that has arrived, so the price is current. It counts what actually reached its account, not what was asked. A wrap is refused while the program is frozen or wrapping is paused, when it would pass the deposit limit, or when it buys fewer shares than the caller's minimum.

Unwrap

Burns shares from an account the signer owns or is delegated, and pays the USDv they are worth to any USDv account outside the program. The payout comes from the yield account and, for any part it cannot cover, the principal account. When the destination requires a memo on incoming transfers, the program logs one first. Neither the guardian nor governance can stop an unwrap. Only a freeze does, and only USDv leaving the program's accounts, or Solomon freezing one of them, causes one.

Checkpoint and quote

checkpoint books whatever the program's two USDv accounts show: a payment, a donation, USDv taken from either account, or a frozen account. Anyone may call it, and it never moves tokens. quote returns what a checkpoint would leave, without writing anything: the assets an unwrap prices against, the share count, and the assets a wrap prices against. A lending market or any other integrator should price uUSDv with quote, never with a market price, which a flash loan can move.

The two USDv accounts

The program holds USDv in two accounts and counts their combined balance. Wraps pay into the principal account and Solomon pays rewards into the yield account. No instruction moves USDv from one to the other, so USDv leaves the principal account only through an unwrap. Solomon pays rewards on the two accounts' combined balance, so rewards compound without being moved.

USDv sent to any other token account, including one that names a program authority as its owner, is not counted and no instruction can move it.

Initialize

Opens the program once. It creates the USDv accounts, the uUSDv mint and the account that holds the seed: 1 USDv wrapped at launch, whose shares no instruction can move. The seed keeps the share count above zero, so the first depositor cannot set the price. It also writes uUSDv's name, symbol and URI into the mint, where wallets read them; governance can replace them later. Only the bootstrap key built into the program may run it.

Who controls what

The guardian

One key may pause wrapping, at once. A pause never touches unwrapping, so it can slow money coming in but never trap money going out.

Governance

Through the governance timelock, governance may resume wrapping, set the release cap between 5% and 20%, set the deposit limit, replace the guardian, unfreeze the program, and replace uUSDv's name, symbol and URI. Each proposal names the value it replaces, so it executes only against the state it was made for. A resume names the pause it ends and the moment that pause began, so a resume can never be queued ahead of a pause, and one queued before a later pause cannot end it; an unfreeze is bound to its freeze the same way. A resume ends only the guardian's pause, never a freeze. A metadata update names the count of earlier updates, so it never lands on metadata that changed after it was proposed. Governance cannot move USDv, mint or burn uUSDv, or change the release window.

The program upgrade authority

The upgrade authority can replace the program, as for every Umbra program.

Solomon

USDv is Solomon's token, and its mint keeps powers the program cannot override. Solomon can pause USDv, freeze an account, move tokens through its permanent delegate, or set a transfer hook. A paused USDv stops wrapping and unwrapping until it resumes. A clawback from either of the program's accounts, or freezing either of them, freezes the program until governance unfreezes it. The program forwards the accounts a transfer hook needs, up to sixteen per transfer, so a hook set later does not stop it; a hook that needed more would stop wrapping and unwrapping until the program was upgraded.

The program relies on Solomon paying rewards on the principal and yield accounts' combined balance, into the yield account, and on Solomon never using its permanent delegate on the program's accounts or freezing them, acting against a thief's own addresses instead.

Limits

  • Stolen USDv. Wrapping is instant and unscreened, so a thief can wrap stolen USDv and unwrap clean USDv. Holders are protected only by Solomon acting against the thief's own addresses, as for every pool of USDv.
  • Missed payments. When Solomon misses payments and then catches up, someone who wraps just before the catch-up shares in it. The cap bounds how much.
  • Changes in Solomon's schedule or rate. When the yield still releasing drops at once, because Solomon pays more often, cuts its rate or resumes after a pause, whoever holds across the change receives a one-time share of it. This comes out of yield, never out of USDv deposited.
  • Large exits and entries. A holder who leaves gives up their share of the yield still releasing; in steady flows this balances what entrants inherit.
  • CPI Guard. An account with Token-2022's CPI Guard on wraps or unwraps through a delegate.

Reference

Last updated

On this page