Scrip

Docs

Corporate actions, and why a dividend is not a gain.

xStocks handle dividends and splits with an on-chain multiplier that rebases balances. Store raw balances and compute returns from them, and every number is wrong from the first ex-date.

The multiplier is not the field called multiplier

A Token-2022 ScaledUiAmount config carries two values and a timestamp: multiplier (the older), new_multiplier (the newer) and when the newer takes over. Read on mainnet on 2026-09-12, the SPYx mint held 1.003909240011759 and 1.005714560286254, effective three months in the past. An app that reads the obvious field paints every SPYx balance 0.18% short, forever, with nothing about the number looking wrong.

The timestamp on the mint decides. Read across fourteen mints on 2026-09-15, activations fell at 23:55, 00:30 and 04:00 UTC, so nothing in Scrip assumes an hour. The program reads the extension by hand in finish_sweep and applies the live value when the price feed is quoted per share.

Two feeds, and which one carries the multiplier

FeedPricesPublishedMultiplier
Crypto.SPYX/USDone raw token, as it tradesaround the clockalready inside the price
Equity.US.SPY/USDone sharemarket hoursapplied by the program

On 2026-09-12 SPYX/USD divided by SPY/USD came to 1.00567 against a live multiplier of 1.00571, the difference being feed latency. That agreement is the strongest single check that the multiplier handling is right.

What Scrip stores

Receipts and measurements carry raw units. Keep-rate is computed from raw units. Screens show raw units through the live multiplier as share-equivalents, and say when the adjustment could not be read rather than assuming a multiplier of one, because assuming one is assuming no corporate action ever happened. Every multiplier ever seen is kept, keyed on when it activated, so a rebase is auditable after the fact.

The two failures this makes impossible