01/ the claim, and what was already known
Four numbers, each from a source you can fetch yourself.
The issuer publishes a corporate-action feed. The chain publishes a multiplier. They are independent records of the same events, and until you put them side by side, neither one tells you what a holder was actually paid.
Built on
Solana's Token-2022 documentation describes the stale field, and ExDate published the withholding rate and a dollar total on 13 September 2026. Kamino's Scope oracle suspends a price for the 24 hours before an activation, and EquityGuard, another entry in this event, refuses execution inside a transition window.
What this adds
The count: 640 activations timed against the exchange's own calendar. The record: an ordered, permissionless account of each activation a crank writes, read out of the mint rather than out of an oracle report. And the currency the reference price is quoted in, below.
02/ what the chain says
One raw token is not one share, and the obvious field is the previous value.
On EVM chains the contract adjusts balances itself, so balanceOf() is already correct. On Solana the balance stays put and every integrator is individually responsible for applying the multiplier. The extension gives you two candidate values and only one of them is live.
multiplier
1.0268028385
The field a reader reaches for first. It is the value in force before the most recent corporate action. For 370 of 927 mints it is not the multiplier.
new_multiplier
1.0344000942
Live from unix 1788481800. This is the value a wallet must multiply a raw balance by, and the value this program records.
The rule applied here is: the live value is new_multiplier once its timestamp has passed, and multiplier otherwise. That is what Token-2022's own process_update_multiplier does, and it is not taken on trust. The issuer publishes its own view of the live value, and the rule was compared against it on every mint rather than a sample: 927 agreed, 0 disagreed, 0 publishing nothing to compare against. The comparison is one of the build's own checks and it stops the page if it ever fails.
Why the balance cannot help you
Token-2022's scaled-ui-amount extension leaves the raw amount alone. A holder's balance is identical before and after a dividend, so a wallet that shows raw amounts shows a position that has not moved when it has.
Why the history is not on chain
A mint keeps the latest two multipliers and nothing before them. There is no event log, no sequence, no account per activation. The record of what a token has paid lives in an HTTP API and in transaction logs.
Why the pause needs a number
The issuer's own docs recommend that venues and protocols pause for fifteen minutes around each activation, and nothing in a mint account can enforce that. Kamino's oracle suspends a price for the 24 hours before one. Either way the venue has to know when the window is.
Quoted from docs.xstocks.fi/developers/multipliers, not paraphrased: “The multiplier is published on-chain before each corporate event takes effect… we recommend that trading venues and protocols pause all interactions with the token for a brief window (e.g., 15 minutes) before and after each activation timestamp.”
When the multiplier actually moves. 640 activations the issuer has published, counted by the minute of the day they take effect. 631 of them, 98.6%, fall outside the US regular session, and 93.8% of the whole sample lands on the four minutes below.
That is measured two ways, because one definition of "the market is open" is mine and the other is the exchange's. The first is a fixed UTC window drawn wide at 13:00 to 21:00, which covers the session under both daylight time and standard time and can only make the finding harder to reach: by that definition 628 of 640, or 98.1%, are outside. The second is the exchange calendar Pyth publishes with its feed directory: America/New_York, a regular session of 09:30-16:00, 12 date overrides for holidays and half days, and it covers 1043 of the 1070 US equity feeds Pyth carries. Against that, 9 of 640 fall inside the session, so 631 are outside, or 98.6%. The two are computed independently and the build requires both to agree the market is shut, so the result is not an artefact of where the window was drawn. Of the ones the calendar puts outside, 574 land on a weekday that trades but outside its hours and 57 on a day the market does not trade at all.
This is the part of the story that is not a bug in anyone's code. The issuer schedules activation for 00:30 UTC the day after the ex-date, which is four and a half hours after the US close and thirteen hours before the next open. So the multiplier changes when there is no continuous price to settle against and no closing auction to absorb it, and the fifteen minute pause is what stands in for both. A venue that does not pause is not making a mistake about a number. It is settling against a position whose entitlement moved while it was not looking.
That the token trades while the underlying does not is not an assumption here. The Solana Foundation's 13 September newsletter reports that 63% of tokenized-equity volume settles outside US market hours, and the event brief names it as a theme. Kamino, the first major lender to take these as collateral, suspends its price for the 24 hours before an activation, and EquityGuard, another entry in this event, turns the timestamp into a guard. This entry publishes the count and the record behind it.
03/ what was taken
The dividend is reinvested net of tax, and the net is 73.8% of the gross.
Across the 540 scheduled cash dividends the issuer has published, the arithmetic closes exactly: net = gross × (1 − rate) on all 533 records that carry both figures. The withheld part never reaches the token, so it never reaches the multiplier, so it never appears anywhere a holder would look.
Method and its limits. Per-unit dividend times scaled supply, at today's price, over the window the issuer's feed covers. Supply is today's rather than time-weighted, so a token that minted heavily after its dividend is over-counted. The feed is an upcoming feed, so the window runs a few days past today: $23,795,729 of the $24,365,251 gross is dated on or before today and $569,522 is still forward. Read the annual figure as an order of magnitude, not a ledger. The full arithmetic is in scripts/fetch.py.
04/ the proof
Divide the net dividend by the multiplier step and you get the share price.
The corporate-action feed and the mint account are separate records. If they describe the same event, then net per unit ÷ (new multiplier − previous multiplier) is the price of one share of the underlying on that date, recovered with no oracle and no price feed, from the chain and the issuer's feed alone.
That claim makes a prediction you can test. The implied price is fixed on the activation date; the market price is today's. So the gap between them has to be the stock's own movement, which means the gap must grow with the age of the activation. If the identity were an artefact of how the feed is written, the gap would be noise and the same size in every bucket.
It does: a fresh activation reconciles at 2.1% within ten days against 4.8% beyond sixty, and the table below shows every bucket.
Which figure the chain reinvests is asserted, not assumed. The feed publishes a gross cashflow and a net one, 30% apart, and the whole entry rests on the net being the one that reaches the token. Divide either by the multiplier step and you get a share price. Do it with the net figure and the answer lands on the market at 1.033; do it with the gross and it reads 1.476. The control is the 40 events carrying a 0% rate, where the feed's net and gross are the same number and a test that is measuring the unit rather than the arithmetic must have no preference between them. It does not: both read 1.006.
| Token | Activation | Multiplier step | Net dividend / unit | Implied price | Market price today | Gap |
|---|---|---|---|---|---|---|
| BBYx | 2026-09-170d | 0.0072687939 | 0.672 | $92.45 | $94.66 | -2.3% |
| CRMx | 2026-09-170d | 0.0012360712 | 0.308 | $249.18 | $241.79 | +3.1% |
| HBANx | 2026-09-170d | 0.0068584071 | 0.1085 | $15.82 | $15.81 | +0.1% |
| HPEx | 2026-09-170d | 0.00175988 | 0.09975 | $56.68 | $61.45 | -7.8% |
| SATAx | 2026-09-170d | 0.0005396219 | 0.0516 | $95.62 | $95.55 | +0.1% |
| VICIx | 2026-09-170d | 0.0131267835 | 0.322 | $24.53 | $23.84 | +2.9% |
| AIGx | 2026-09-161d | 0.0046064754 | 0.35 | $75.98 | $75.03 | +1.3% |
| ARESx | 2026-09-161d | 0.007319907 | 0.945 | $129.10 | $125.32 | +3.0% |
The eight most recent activations, ordered by age and not selected for how well they agree. The market price is the token's quoted price divided by the multiplier the chain reports, which is a third source neither of the other two has seen.
| Age of the activation | Events | Median gap against today's price |
|---|---|---|
| 0-2 days | 41 | 1.7% |
| 3-10 days | 34 | 2.5% |
| 11-30 days | 160 | 4.9% |
| 31-60 days | 118 | 6.9% |
| over 60 days | 90 | 4.8% |
Across 443 reconciliations on 351 names the median gap is 2.1% where the activation is within ten days (75 events) and 4.8% where it is more than sixty (90). The arithmetic is identical in both buckets. The only thing that changed is how long the stock has had to move, which is what makes this evidence rather than a coincidence. The overall median is 4.5%.
05/ the ledger
The tokens where the most was withheld.
Withheld dollars per token over the window, from per-unit dividends the issuer published times the scaled supply the chain reports. The bar is scaled to the largest here.
- STRCx7 eventswithheld$223,344per unit0.4375multiplier1.0863570206price$97.94
- PFEx2 eventswithheld$165,753per unit0.258multiplier1.0537129709price$27.68
- NVOx2 eventswithheld$130,148per unit0.396956multiplier1.0370549907price$42.99
- CMCSAx2 eventswithheld$113,925per unit0.198multiplier1.087679741price$23.18
- TBLLx5 eventswithheld$113,672per unit0.451278multiplier1.0187608514price$105.75
- XOMx3 eventswithheld$112,966per unit0.927multiplier1.0176489705price$162.05
- MRKx3 eventswithheld$108,611per unit0.765multiplier1.0258591861price$146.80
- YLDEx4 eventswithheld$105,875per unit0.477105multiplier1.0194749277price$55.78
- CVXx2 eventswithheld$104,221per unit1.068multiplier1.0295541832price$210.26
- KOx3 eventswithheld$103,027per unit0.477multiplier1.0225601246price$88.06
- HDx3 eventswithheld$97,202per unit2.097multiplier1.0232993457price$304.47
- PEPx2 eventswithheld$95,765per unit0.888multiplier1.0344000942price$133.59
- FLBLx4 eventswithheld$91,403per unit0.172778multiplier1.0171047698price$22.98
- EWQx1 eventwithheld$88,751per unit0.326201multiplier1.0163263664price$44.41
- MSFTx3 eventswithheld$86,479per unit0.819multiplier1.0059033905price$495.80
- JAAAx5 eventswithheld$72,815per unit0.301846multiplier1.0111858841price$50.65
- EWGx1 eventwithheld$72,334per unit0.249474multiplier1.0137581352price$42.78
- UNHx2 eventswithheld$68,958per unit1.359multiplier1.0273478685price$378.20
- MCDx2 eventswithheld$62,269per unit1.116multiplier1.0211807005price$249.21
- FEZx1 eventwithheld$62,099per unit0.333488multiplier1.01110673price$68.92
- JNJx2 eventswithheld$58,697per unit0.804multiplier1.0195885202price$267.87
- IBMx2 eventswithheld$56,149per unit1.011multiplier1.0204029188price$238.30
- SPYx1 eventwithheld$54,693per unit0.571055multiplier1.0057145603price$762.57
- EWUx1 eventwithheld$52,233per unit0.199876multiplier1.0098892366price$47.92
- FAAAx4 eventswithheld$52,153per unit0.2157multiplier1.0096041759price$50.35
- BACx2 eventswithheld$51,290per unit0.18multiplier1.0179352668price$58.47
- JPSTx4 eventswithheld$49,236per unit0.204249multiplier1.0094580397price$50.37
- GSx2 eventswithheld$48,988per unit2.85multiplier1.0157573238price$953.93
- NVDAx2 eventswithheld$48,274per unit0.15multiplier1.0017011968price$218.84
- JPMx2 eventswithheld$44,693per unit0.9multiplier1.0139174714price$350.30
06/ the program
Entitlement, as an account you can read in one call.
A dividend on Solana is a change to the meaning of a balance. This program reads the mint directly, resolves the multiplier correctly, and writes each activation a crank brings it as a permanent, ordered receipt that any protocol can read without an API.
// the whole trap, in one comparison // Token-2022's ScaledUiAmountConfig::current_multiplier, mirrored exactly: the // timestamp decides, and the stored value is not consulted at all. pub fn effective(&self, now: i64) -> f64 { if self.new_multiplier_effective_timestamp <= now { self.new_multiplier // live } else { self.multiplier // previous. not the multiplier. } }
Once per deployment. Holds the authority and the two counters.
Reads an xStock mint and stores the live multiplier alongside the value in the field the mint calls multiplier, so the gap between them is auditable.
Permissionless. If the multiplier has moved, writes a Receipt: previous, new, the issuer's own timestamp, the supply. Ordered by sequence and never edited.
Raw units in the units a wallet should display. Return data is a little-endian u128. Integer arithmetic throughout.
One byte: has the multiplier moved since this program last looked? A cranker calls this first so it does not pay for a transaction that reverts.
Seconds since the last activation. A protocol that wants to follow the issuer's advice to pause refuses to settle while that is inside 900.
Binds a registered mint to a Pyth feed id. The id is stored rather than the price account's address, because a PriceUpdateV2 account is rewritten on every publish and its address is not stable.
Reads a Pyth price account and refuses it if the receiver program does not own it, if it is for a different feed, if it is older than a limit the caller sets, or if it differs from the caller's price by more than a tolerance the caller sets. This is the only instruction here that compares against a number this program does not own.
The mint is read as raw bytes, not through the spl-token-2022 crate, because the program does not link against the program that owns it. The layout is not the one the docs describe: a mint account is a 165 byte base region, then the account-type byte, then the extensions. The mint fills only the first 82 of those bytes. So the header is computed rather than searched for, and a non-zero byte in the padding is an error. Asserted on all 927 mints: the padding is zero in every one and the ScaledUiAmountConfig header is at byte 275 in every one. cargo test covers the parser, the read rule and the fixed-point arithmetic, and for the Pyth instructions it runs against two PriceUpdateV2 accounts captured from mainnet and devnet rather than fixtures written to match the parser, because a fixture built from the parser can never disagree with it.
07/ the checks
What has to be true for this page to be right.
Every figure above is generated by one script that asserts its own claims and refuses to write the page if one fails. These are the assertions, with what they actually found.
100 symbols on page 0 of the issuer's asset API, 100 of them present in the 927 mints read
927 of 927
927 of 927 padded with zeros, 927 of 927 type byte is 1, 0 rejected
275 x927, across 927 mints; the largest extension body stepped over is 205 bytes
927 of 927 exact, 0 overran, 0 undershot, at most 8 entries
533 of 533 records match exactly
94.2% of 400 symbols at 30%
3 rows collapsed to 540 distinct events, 0 survivors are not the highest version; the superseded rows carried 0.71% of the per-unit gross
540 scheduled cash dividends against 554 scheduled actions of all types
443 reconciliations across 351 names
640 activations, 12 (1.9%) inside 13:00-21:00 UTC; most common times 00:30 x407, 23:55 x177, 00:15 x11, 01:15 x5
9 of 640 (1.4%) inside 09:30-16:00 America/New_York, which is the session 1043 of 1070 USD equity feeds on Pyth carry, over 12 listed overrides
12 inside the UTC window against 9 inside the exchange calendar, a difference of 3 across 640 activations
Pyth puts the next open at Fri 18 Sep 09:30 and the next close at Thu 17 Sep 16:00, and 1043 feeds carrying this calendar agree on both; the parser matches at 5 of 5 boundary probes
median 2.1% on the 75 activations within 10 days against 4.8% on the 90 older than 60, so the residual is the stock moving, not the method
the implied price over the market reads 1.033 on the net figure against 1.476 on the gross across 400 events at a rate above 29%, so the net is the one landing on a share price; on the 40 zero-rate events, where the two figures are the same number, both read 1.006, which is the control
10 events where the two price fields differ by over 20%; the field this run used reconciles to a median error of 0.9%, the field it rejected to 33.1%
370 of 927 mints differ
927 agreed, 0 disagreed, 0 published no value
133 agreed, 0 disagreed, 0 unavailable
548 never, 297 exactly one, 82 two or more
unrounded $6,373,807.48 vs $6,373,807.48, difference $0.00
ledger $6,373,805 vs headline $6,373,807, drift $2.48 within $190 from 379 rounded rows
all rates $6,373,807 vs 30%-only $6,343,594, the rest is $30,213
$24,365,251 = $17,991,444 + $6,373,807
paid $23,795,729 of $24,365,251, forward $569,522
31 of 784 priced mints are non-dollar listings and every one is converted at the ECB rate for 2026-09-17; 0 converted by nothing
27 LSE mints priced, the published value is 74.8 times the dollar price on every one of them, because the ratio is pinned to 100 divided by the GBP rate of 1.337649 rather than varying with the share; drop the division and it reads 0.75
the London listings are 1.54% of the converted book and 100% of the gap between the converted and face-value totals
0.70% on $3,399,961,459 across the 370 mints that both pay and quote
784 of 927 mints quoted
every figure matches
08/ scope
Scope, and one more finding.
The reference price is not always in dollars
174 of the 927 mints track an equity that does not trade in dollars, and the reference price published beside them is quoted in the underlying's own currency. 31 of the priced mints are non-dollar, and 27 of those are London listings quoted in pence, so each is divided by 100 before it is converted at the ECB rate for 2026-09-17. Read as dollars instead, the same prices value the book at $13,812,308,339 rather than $6,460,200,460, a factor of 2.14, and the yield denominator with it.
The window is the feed's, not a clean year
2026-03-06 to 2026-09-24. The annual figure is that window scaled, not twelve measured months. Re-run the script and you get a different window and a slightly different number.
This is one issuer
927 mints from Backed's own asset API, which is exhaustive over what Backed publishes on Solana.
09/ the sources
Everything, public, no key.
No API token, no account, no paid feed. Run python3 scripts/fetch.py and it re-fetches all of it and re-asserts the checks above.
One source is used for less than it offers, and it is worth saying which. Pyth's feed directory is public, and the session definition in section 02 is taken from it. Its price values are a different surface, and the distinction is easy to get wrong: the Hermes HTTP endpoint serves equity price updates only to a key carrying a grant, while Pyth also posts every update to Solana as a PriceUpdateV2 account owned by its receiver program, and a posted account is public state. Two of those accounts are committed as test fixtures, read with a plain RPC call and no credential, and the program's verify_against_pyth instruction reads one at settlement time.
https://api.xstocks.fi/api/v2/public/assetshttps://api.xstocks.fi/api/v2/public/corporate-actions/upcominghttps://api.xstocks.fi/api/v2/public/assets/{SYMBOL}/multiplier/historyhttps://api.mainnet-beta.solana.comhttps://api.jup.ag/price/v3https://api.frankfurter.app/latest?from=USDhttps://hermes.pyth.network/v2/price_feedshttps://docs.xstocks.fi/developers/multipliers