Part II: The backing
5. How one token becomes one share, exactly
This is the section that matters. Everything else Float does is a way of delivering the claim described here, and every design decision elsewhere bends to keep it true.
5.1 The claim, stated precisely
One fSHARE is one ordinary share of the underlying company, held in custody and owed to the holder.
Not one share of a basket. Not a tracker. Not an index. The specific security, in the specific quantity, in a specific account. Where custody holds a receipt rather than the ordinary share (an ADR, a GDR), the reserve is converted to ordinary-share equivalents by a per-market ratio before any of the accounting below runs, so the promise the token makes stays denominated in the company's own shares. Section 6 is entirely about that conversion.
The claim is redeemable. Selling an fSHARE to the Desk burns it and returns USDG at the reference price, and the share behind it is released. The claim carries no voting rights, which is true of every tokenized equity and should be stated rather than implied.
5.2 The five numbers
Every market's reserve is five numbers, all of them public views on
ReserveBook.sol. Nothing about the backing exists off chain except the broker
account itself, and section 5.8 is about what that means.
| number | what it is | how to read it |
|---|---|---|
outstanding |
fSHARE in issue, which is the shares owed to holders | UAsset.totalSupply(), read through ReserveBook.outstanding |
sharesHeld |
ordinary-share equivalents settled in custody | attested by the custodian, or read as a token balance |
inFlightLive |
ordered and paid for, not yet settled, with a live TTL | expires after 3 days so a stuck order cannot prop up a ceiling |
bufferShares |
a deliberate over-hold, absorbing the settlement gap | set per market, publicly |
cashBackedSharesAt |
tokens covered by cash committed to buying their share | falls to zero as custody converts, by construction. Takes (assetId, px, qScale), not the assetId alone |
And one derived number that is the whole product in a single call:
coverageBps = sharesHeld * 10000 / outstanding
10000 means exactly one share per token. More is over-reserved. Less is a shortfall, and it is visible to anyone the moment it happens.
5.3 The buy, step by step
A person buys $500 of fSAMSUNG at 3am Korea time. Here is every step, in order, with what changes on chain at each one.
1. The order arrives. They approve USDG and call
Desk.buy(assetId, quoteIn, minOut, recipient).
2. The Desk prices it. It reads the mark from OracleHub, which is a median
over a poster set with a staleness window. If the price is stale or the poster
set is thin, the quote comes back degraded and the market is in settle-only:
this buy reverts, and the person can still sell. Assuming a good price:
effPx = mark * (1 + spread + impact + txFee)
baseOut = quoteIn / effPx
3. The gate runs, before anything is minted. Desk._checkIssuance computes
what outstanding would be after this trade and refuses if it exceeds the
reserve ceiling:
if (gated) {
if (outstandingAfter > book.mintCeilingAt(assetId, px, qScale)) revert ReserveExceeded();
}
This is the structural part and it is worth being precise about why. The Desk cannot create a token the reserve does not already support or does not already have committed money to support. It is not a policy the operator follows. It is a condition the transaction fails.
4. The token is minted and the money lands. USDG enters the Desk vault,
UAsset.mint issues the fSHARE, netOI rises. At this instant the market is
cash backed: the buyer's $500 is sitting in the vault and it is the money
that will buy the share. This is the only moment of the whole cycle where the
claim is not yet a share, and closing it fast is the reserve keeper's entire
job.
5. The keeper sees the shortfall. services/keepers/reserve-keeper.mjs
polls each gated market:
shortfall = ReserveBook.sharesToBuy(assetId) // owed, in ordinary shares
units = shortfall / sharesPerUnit // what to buy on the actual line
sharesToBuy counts in-flight the same way the ceiling does, deliberately: an
earlier version used the raw figure, so an expired report stopped counting
toward the ceiling while still counting as owed, and the market deadlocked with
no headroom and a keeper told nothing was owed.
6. The ratio is checked against the chain. The keeper reads
sharesPerUnit(assetId) from the contract and compares it to its own config. A
mismatch stops the market rather than trading through, because the keeper sizes
the order while the contract sizes the ceiling, and when they disagree
the market issues against backing it does not have. Shipping 0.25 in the keeper
while the chain still defaults to 1.0 is a 4x fractional reserve on Nintendo
with every on-chain view agreeing with itself.
7. The order is placed, idempotently. The broker order id is derived by hash from the market's on-chain reserve state:
orderId({ assetId, outstanding, held, inFlight }) -> "float-<sha256[:32]>"
A keeper that dies between placing an order and reporting it restarts, computes the same id from the same on-chain state, and the broker rejects it as a duplicate. That is what stops a crash loop from buying the same shares five times.
8. The fill is reported. reportExecuted(assetId, units, ref) records the
purchase in the units the custody statement literally uses, converts to
ordinary-share equivalents, and stamps the in-flight pile. The fill counts
toward the ceiling immediately, because the purchase is done and the price is
locked. Three guards sit on this call:
fillSeen[keccak(assetId, ref)]makes a fill count exactly once. A keeper resubmitting a report it believed had failed used to double the ceiling against a single purchase.inFlightSinceis stamped only when the pile starts, not on every fill, so a steady trickle of new purchases cannot extend the TTL over the whole pile indefinitely.- A ticker that was never listed reverts
NoSuchMarket.
9. Settlement. T+2 in most markets. reportSettled(assetId, units, unitsHeldNow, custodyRef) moves the units out of in-flight and writes the
absolute held figure from the statement, along with the statement reference.
Absolute rather than incremental, so a miscount corrects itself on the next
report instead of compounding forever.
From that block onward, sharesHeld covers the tokens minted in step 4,
coverageBps reads 10000 or better, and the ceiling for the next buyer is
computed off real stock rather than off cash.
5.4 The ceiling, in full
mintCeilingAt = sharesHeld
+ inFlightLive
+ bufferShares
+ cashBackedSharesAt
Four terms, and the fourth is where the care went. cashBackedSharesAt is the
cash cover, and it is built to shrink to nothing on its own as custody grows:
cap = min(oiCapQuote, vaultBacking + BackingVault.totalCash) // real deposits, not the risk dial
allowedQuote = cap * cashBackedBps / 10000
converted = sharesHeld * price // THE RATCHET
if (converted >= allowedQuote) return 0;
allowedQuote -= converted;
return allowedQuote / price;
Three properties of that block, each of which was a bug before it was a property.
Cash and shares do not add. The subtraction of converted means the sum
above collapses to max(sharesHeld, cashAllowance) + inFlightLive + buffer.
Buying a real share does not stack capacity on top of the cash that bought it.
It replaces the cash cover with something better. The reason is that
vaultBacking is a deposit counter and does not fall when that cash is
withdrawn and spent on the very shares it was meant to buy, so without the
subtraction the same dollars count twice. An audit measured exactly this: one
$5,000 cushion authorising $10,000 of issuance while the market reported itself
fully compliant at 51.5% real reserve.
The risk dial cannot be laundered into cash cover. oiCapQuote is real
backing times a multiplier that can be as high as 5x. Multiplying unbacked
issuance by a dealer-risk dial is not something anyone intended, so the cash
term takes min(cap, actual deposits).
It fails closed. If the funder address is unset, the cash term returns zero rather than skipping the clamp. The earlier version skipped the block and handed the market the full risk-multiplied cap.
And one thing that is deliberately permissive: cash counts in both regimes,
open market and closed. An earlier version zeroed the cash term the moment the
home exchange opened, on the logic of "go buy the share instead". Two things
went wrong, both reproduced on testnet. A market with no custody yet could not
be started at all during trading hours, ceiling zero and every buy reverting.
And every existing market stopped issuing at each opening bell until a keeper
caught up. The gate's job is to stop supply outrunning the reserve, not to
schedule the keeper. The conversion obligation stays visible in sharesToBuy,
coverageBps and the reserve page, all of which count shares only and so
keep telling the truth about what is still owed.
5.5 The sell, and why redemption is never gated
Desk.sell burns the fSHARE and pays USDG at mark * (1 - spread - impact - txFee). outstanding falls, so the reserve is now long relative to the claim
and the keeper releases the share back into cash on the next cycle.
The gate runs on skew-increasing trades only. Redemption is never blocked, by any of it: not by a stale oracle, not by a degraded poster set, not by a tripped breaker, not by a shortfall. Every failure state in Float is settle-only, which means holders can always leave and nobody can enter. There is no state of the system in which a person is holding a token they cannot sell back.
5.6 Two kinds of custody, and why the difference is stated rather than blurred
ReserveBook resolves both behind one view, so sharesToBuy, the ceiling and
the Desk's check are identical either way. What differs is the trust assumption,
and blurring that would mean reporting the weaker one as though it were the
stronger.
Attested. Shares sit at a broker (IBKR, Alpaca). The chain finds out because
the custodian key says so, and every report carries the statement reference it
came from. The trust point is the custodian and the key. The ring buffer keeps
the attestation history on chain, so the record is a series rather than a
current value, and an UnderReserved event fires whenever a report lands with
sharesHeld below outstanding. A shortfall is published, not hidden.
Verified. The backing is itself an on-chain token that is redeemable for the
real share, and sharesHeld is read live as balanceOf(account) rather than
reported by anyone. The trust point is the token issuer. There is no key to
trust and no step that can lie, and to keep it that way attest,
reportExecuted and reportSettled all revert with CustodyIsVerified on
these markets. A key cannot overwrite what the chain can see for itself.
A market can move between the two by changing one setting, and the ratio machinery applies to both, so a token representing a fraction of a share converts exactly the way an ADR does.
5.7 Every way this could be faked, and what stops it
The claim "one token, one share" is only as good as the list of ways it could be false. Here is that list, and where each one is closed.
| the attack | what stops it | where |
|---|---|---|
| mint more tokens than the reserve supports | the transaction reverts ReserveExceeded before the mint |
Desk._checkIssuance |
| report the same broker fill twice to double the ceiling | fillSeen[keccak(assetId, ref)], reverts FillAlreadyReported |
ReserveBook.reportExecuted |
| leave a fake order in flight forever to hold up a ceiling | inFlightTtl, 3 days, and the stamp only starts a pile |
inFlightLive, reportExecuted |
| trickle new orders to keep extending that TTL | inFlightSince is set only when the pile starts, never refreshed |
reportExecuted |
| count the same dollars as cash cover and as shares | the ratchet subtraction of converted |
cashBackedSharesAt |
| claim the 5x risk-multiplied cap as if it were cash | min(oiCapQuote, actual deposits) |
cashBackedSharesAt |
| unset a registry key so the clamp is skipped | fails closed, returns zero cover | cashBackedSharesAt |
| double-count a paired market's converted cushion | a paired market's cash term is zero | cashBackedSharesAt |
| write a phantom market that reports full coverage | NoSuchMarket on all three write paths |
attest, reportExecuted, reportSettled |
| change the ADR ratio and keep crediting the old conversion | setCustodyUnit restates held and in-flight |
setCustodyUnit |
| run a keeper whose ratio differs from the chain's | the keeper refuses to trade and says so | reserve-keeper.mjs |
| buy the wrong line (a 144A tranche, a look-alike ADR tier) | the adapter refuses a line with no pinned contract id | adapters/ibkr.mjs, ALPACA-ADR.md |
| overwrite a verified balance with a custodian key | CustodyIsVerified on every attested write |
attest, reportExecuted, reportSettled |
| let a shortfall pass quietly | UnderReserved fires on the report that causes it |
_record |
What is not on that list, and cannot be: the custodian holding fewer shares than its statement says on an attested market. That is the irreducible trust point of attested custody, it is the same one every tokenized equity has, and it is why verified custody exists as the stronger mode and why the attestation history is a public series rather than a number.
5.8 How to check it yourself
Every figure is a public view. Nothing below needs permission, an API key, or Float.
BOOK=0x3A4c63B17292d352879dF8AF662432E8Ed767951
RPC="${FLOAT_RPC_URL:?Set FLOAT_RPC_URL to the deployed contract network RPC}"
ID=$(cast keccak "SAMSUNG")
# the whole claim in one number: 10000 = exactly one share per token
cast call $BOOK "coverageBps(bytes32)(uint32)" $ID --rpc-url $RPC
# the parts
cast call $BOOK "outstanding(bytes32)(uint256)" $ID --rpc-url $RPC # tokens owed
cast call $BOOK "sharesHeld(bytes32)(uint256)" $ID --rpc-url $RPC # shares held
cast call $BOOK "sharesInFlight(bytes32)(uint256)" $ID --rpc-url $RPC # bought, unsettled
cast call $BOOK "shortfall(bytes32)(uint256)" $ID --rpc-url $RPC # still owed
cast call $BOOK "isFullyReserved(bytes32)(bool)" $ID --rpc-url $RPC
# what custody literally holds, and in what
cast call $BOOK "unitsHeld(bytes32)(uint256)" $ID --rpc-url $RPC
cast call $BOOK "sharesPerUnit(bytes32)(uint256)" $ID --rpc-url $RPC
cast call $BOOK "custodyKind(bytes32)(string)" $ID --rpc-url $RPC
# every market at once
cast call $BOOK "allReserves()" --rpc-url $RPC
And the history, which is the part that matters for an attested market, because a single current figure proves less than a series does:
| event | carries |
|---|---|
Attested |
shares held, the statement reference, the timestamp |
Executed |
shares bought, the new in-flight total, the broker order reference |
Settled |
shares settled, the new held total, the remaining in-flight |
UnderReserved |
shares held and tokens outstanding, at the moment coverage broke |
attestationAt(assetId, i) walks the on-chain ring buffer directly.