ASSAY · independent valuation-integrity audit · Stock Tokens on chain 4663

balanceOf() is not a share count.

Stock Tokens on Robinhood Chain implement ERC-8056: a corporate action moves uiMultiplier(), not balances, so the share count is balance × uiMultiplier() / 1e18. The largest gap on the board right now: CRWD: reading balanceOf() as shares understates by 75.0000% (multiplier 4.000000000x). ASSAY sweeps every Stock Token every 8 minutes, reads the multiplier, the Chainlink feed and its heartbeat from chain state, and publishes only findings whose every citation re-fetches byte-for-byte. It never moves capital and has no control path over anything it grades.

59
published findings
118/118
citations reproduced
0
withheld by the verifier
194
assets read
0 of 35
24/5 feeds stale
1
critical

Check a wallet

Paste any address to see balanceOf() next to its share-equivalents for every Stock Token whose multiplier is not 1, as the on-chain ERC8056Guard reports them, refusals included.

No address handy? . Reads 48 divergent-multiplier Stock Tokens straight from rpc.mainnet.chain.robinhood.com in your browser. Free; nothing is signed or sent to ASSAY.
The same call from a terminal
cast call 0x674f9b0eC3C3643c1f51c0a40D4837932F9c1648 \
  "shareEquivalents(address,address)(uint256,bool,string)" \
  0xaF3D76f1834A1d425780943C99Ea8A608f8a93f9 <holder> \
  --rpc-url https://rpc.mainnet.chain.robinhood.com
Returns (share-equivalents in the token's base units, safe, reason). The guard refuses with a reason instead of returning a number it cannot stand behind, and it reverts if the token address has no code, so pass a Stock Token address.

Who holds the exposure

Findings — 59

Critical, high and medium findings, most severe first
SeverityAsset readFindingClassEvidence
criticalCRWDCRWD: reading balanceOf() as shares understates by 75.0000% (multiplier 4.000000000x)SHARE_COUNT_MISREAD_RISK2/2 ✓
highCCLCCL: reading balanceOf() as shares understates by 2.1034% (multiplier 1.021486445x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumAVGOAVGO: reading balanceOf() as shares understates by 0.1256% (multiplier 1.001257319x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumCRMCRM: reading balanceOf() as shares understates by 0.1147% (multiplier 1.001148323x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumCSCOCSCO: reading balanceOf() as shares understates by 0.2668% (multiplier 1.002674650x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumGEGE: reading balanceOf() as shares understates by 0.1048% (multiplier 1.001049054x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumHPEHPE: reading balanceOf() as shares understates by 0.1714% (multiplier 1.001716958x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumINTUINTU: reading balanceOf() as shares understates by 0.3217% (multiplier 1.003226934x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumKSSKSS: reading balanceOf() as shares understates by 0.4589% (multiplier 1.004610069x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumLHXLHX: reading balanceOf() as shares understates by 0.4898% (multiplier 1.004922488x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumMPWRMPWR: reading balanceOf() as shares understates by 0.1002% (multiplier 1.001003337x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumORCLORCL: reading balanceOf() as shares understates by 0.2206% (multiplier 1.002210915x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumORCLORCL: off-chain share price and on-chain token price differ by 0.221%CROSS_SURFACE_PRICE_MIX2/2 ✓
mediumPRPR: reading balanceOf() as shares understates by 0.4458% (multiplier 1.004477942x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumQCOMQCOM: reading balanceOf() as shares understates by 0.1227% (multiplier 1.001228123x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumSCHDSCHD: reading balanceOf() as shares understates by 0.5508% (multiplier 1.005538607x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumSGOVSGOV: reading balanceOf() as shares understates by 0.7136% (multiplier 1.007186931x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumSGOVSGOV: off-chain share price and on-chain token price differ by 0.719%CROSS_SURFACE_PRICE_MIX2/2 ✓
mediumSHYSHY: reading balanceOf() as shares understates by 0.2051% (multiplier 1.002055340x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumSPMOSPMO: reading balanceOf() as shares understates by 0.2021% (multiplier 1.002024884x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumSPYSPY: reading balanceOf() as shares understates by 0.1715% (multiplier 1.001717991x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumSPYSPY: off-chain share price and on-chain token price differ by 0.172%CROSS_SURFACE_PRICE_MIX2/2 ✓
mediumTSMTSM: reading balanceOf() as shares understates by 0.2721% (multiplier 1.002728577x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumTSMTSM: off-chain share price and on-chain token price differ by 0.273%CROSS_SURFACE_PRICE_MIX2/2 ✓
mediumUNHUNH: reading balanceOf() as shares understates by 0.4224% (multiplier 1.004241501x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumUPSUPS: reading balanceOf() as shares understates by 0.2204% (multiplier 1.002208725x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumVSTVST: reading balanceOf() as shares understates by 0.1113% (multiplier 1.001114739x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumVTIVTI: reading balanceOf() as shares understates by 0.1748% (multiplier 1.001751012x)SHARE_COUNT_MISREAD_RISK2/2 ✓
mediumXOMXOM: reading balanceOf() as shares understates by 0.1038% (multiplier 1.001039564x)SHARE_COUNT_MISREAD_RISK2/2 ✓
Show 30 low-severity findings
Low-severity findings
SeverityAsset readFindingClassEvidence
lowAAPLAAPL: reading balanceOf() as shares understates by 0.0566% (multiplier 1.000566080x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowAAPLAAPL: off-chain share price and on-chain token price differ by 0.057%CROSS_SURFACE_PRICE_MIX2/2 ✓
lowAMATAMAT: reading balanceOf() as shares understates by 0.0045% (multiplier 1.000044656x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowAMKRAMKR: reading balanceOf() as shares understates by 0.0866% (multiplier 1.000866851x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowASMLASML: reading balanceOf() as shares understates by 0.0101% (multiplier 1.000101323x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowASMLASML: off-chain share price and on-chain token price differ by 0.010%CROSS_SURFACE_PRICE_MIX2/2 ✓
lowCOSTCOST: reading balanceOf() as shares understates by 0.0612% (multiplier 1.000612040x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowDELLDELL: reading balanceOf() as shares understates by 0.0064% (multiplier 1.000063709x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowFF: reading balanceOf() as shares understates by 0.0145% (multiplier 1.000145503x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowGOOGLGOOGL: reading balanceOf() as shares understates by 0.0194% (multiplier 1.000193924x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowGOOGLGOOGL: off-chain share price and on-chain token price differ by 0.019%CROSS_SURFACE_PRICE_MIX2/2 ✓
lowJNJJNJ: reading balanceOf() as shares understates by 0.0021% (multiplier 1.000021490x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowLLYLLY: reading balanceOf() as shares understates by 0.0002% (multiplier 1.000002289x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowLMTLMT: reading balanceOf() as shares understates by 0.0021% (multiplier 1.000021051x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowLRCXLRCX: reading balanceOf() as shares understates by 0.0732% (multiplier 1.000732563x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowMETAMETA: reading balanceOf() as shares understates by 0.0541% (multiplier 1.000541460x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowMETAMETA: off-chain share price and on-chain token price differ by 0.054%CROSS_SURFACE_PRICE_MIX2/2 ✓
lowMSFTMSFT: reading balanceOf() as shares understates by 0.0413% (multiplier 1.000412953x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowMSFTMSFT: off-chain share price and on-chain token price differ by 0.041%CROSS_SURFACE_PRICE_MIX2/2 ✓
lowMUMU: reading balanceOf() as shares understates by 0.0075% (multiplier 1.000074823x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowNVDANVDA: reading balanceOf() as shares understates by 0.0775% (multiplier 1.000775159x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowNVDANVDA: off-chain share price and on-chain token price differ by 0.078%CROSS_SURFACE_PRICE_MIX2/2 ✓
lowQQQQQQ: reading balanceOf() as shares understates by 0.0700% (multiplier 1.000700791x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowQQQQQQ: off-chain share price and on-chain token price differ by 0.070%CROSS_SURFACE_PRICE_MIX2/2 ✓
lowSKHYSKHY: reading balanceOf() as shares understates by 0.0060% (multiplier 1.000060354x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowSOXXSOXX: reading balanceOf() as shares understates by 0.0451% (multiplier 1.000450838x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowTERTER: reading balanceOf() as shares understates by 0.0647% (multiplier 1.000647858x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowVRTVRT: reading balanceOf() as shares understates by 0.0163% (multiplier 1.000162789x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowWDCWDC: reading balanceOf() as shares understates by 0.0218% (multiplier 1.000217565x)SHARE_COUNT_MISREAD_RISK2/2 ✓
lowXLKXLK: reading balanceOf() as shares understates by 0.0804% (multiplier 1.000804405x)SHARE_COUNT_MISREAD_RISK2/2 ✓

Asset read names the contract whose state was read. It is not an accusation against that contract — a Stock Token that moves uiMultiplier() is doing exactly what ERC-8056 specifies. The exposure lands on an integrator that reads balanceOf() as a share count.

Use it

Free first: this wall, the wallet check, the on-chain guard and the public MCP. Pay for the full answer. Both paid calls are x402, settled in USDC on Base to 0x6328f2fE483922721D94b33eE99e9938Da3b7911. In a browser, the paywall page is OpenServ's: it asks you to connect a Base wallet holding USDC, and the input fields appear only after you connect. An agent pays the trigger URL directly.

$0.01 · assay_true_position(symbol, holder)

Free on MCP: whether this position can be valued safely, and if not, why: the confidence, the refusal reason, which oracle checks completed, and any scheduled multiplier change.

$0.01 adds the position: raw balance, uiMultiplier(), share-equivalents, the token's decimals, and the feed, price, age and heartbeat behind those checks, with the USD value, all read at one block.

x402 trigger · https://api.openserv.ai/webhooks/x402/trigger/006ecd4add4a459d8ae92362869a42a6
$0.25 · assay_check_contract(address)

Free on MCP: the verdict alone (NOT_AWARE, AWARE, NOT_APPLICABLE with its role, PROXY_UNRESOLVED, TOO_SMALL, or no code), with the code hash, the block and whether the reading is conclusive.

$0.25 adds the audit: every holding of every Stock Token whose on-chain multiplier is not 1, the share-equivalents unaccounted for, the USD held (null when any holding is unpriced or unread, never a silent zero), and the eth_call citations behind each number.

x402 trigger · https://api.openserv.ai/webhooks/x402/trigger/a1bb2a3946d1411eb945200d43ebc740

From code

curl -m 20 -i -X POST \
  https://api.openserv.ai/webhooks/x402/trigger/006ecd4add4a459d8ae92362869a42a6 \
  -H 'content-type: application/json' \
  -d '{"buyerAddress":"0xYourBuyerAddress","payload":{"symbol":"NVDA","holder":"0xHolderAddress"}}'
# -> HTTP 402 and the x402 payment terms (USDC on Base). Nothing is charged.

The audit takes the same shape with "payload":{"address":"0x…"}. Any x402 client can pay; with wrapFetchWithPayment, pass a ceiling of at least the price, because its default of $0.10 refuses the $0.25 call before sending it. The reply is {status, settleTxHash, output: {value}}, and output.value is itself a JSON string. OpenServ allows 60 seconds per call. The input schemas are in the agent card.

Before you pay. Payment settles before the task runs. A bad input comes back as ok: false JSON with an errorClass and a retryable flag, and whether OpenServ still settles a task that errors is not verified, so check a symbol or address with the free MCP first.

Which tokens get a USD answer at $0.01

These 35 tickers have a Chainlink feed on chain 4663, so the $0.01 call can value them: AAPL AMD AMZN ASML BABA CLSK COIN CRCL CRWV DELL EWY GME GOOGL INTC IONQ META MSFT MSTR MU NBIS NVDA ORCL PLTR QQQ RGTI RKLB SGOV SLV SNDK SPCX SPY TSLA TSM USAR USO. Every other Stock Token (159 of 194 in this sweep, CRWD among them) returns the corrected share-equivalents with the USD value refused, because there is no on-chain price to use. A priced token whose feed is past its heartbeat, as the 24/5 feeds are for part of every weekend, comes back degraded with the feed's age stated. Listed from the Chainlink directory the paid call reads, re-read hourly.

Free, no key

Where SERV Reasoning runs

Nothing on this page, and neither paid call, uses a model: every number is read from chain state and re-fetched before it is published. SERV Reasoning does the one job that needs judgement. When a subject asks for an ERC-8004 verdict about itself, it decides whether a byte-verified finding is material against the subject's own declared mandate.

One recorded adjudication · 2026-09-22
finding CRWD-share-count · uiMultiplier() == 4000000000000000000 · 2/2 reproduced byte-for-byte

Declared mandate (a measurement fixture, not a real subject): “…Positions and P&L are displayed to the user in shares.”

Verdict CONTROL_WEAKNESS (medium)

The mandate places the subject in the affected area by stating that positions and P&L are displayed in shares, but it does not explicitly state that the share count is derived from balanceOf(). Therefore the operation corrupted by the anomaly is not established as performed by the subject. No incorrect output is established, so the decision stops at the control gate rather than reaching the misstatement gate.
The unsafe answer would have been MATERIAL_MISSTATEMENT: accusing the subject of a defect the evidence never shows, since “displayed in shares” is not “computed from balanceOf()”. input hash 0x9d8d93a9c63d3be1… · raw artifact

Against 5 hostile mandates, with the guard on and off, 0 of 40 calls were talked into BENIGN and 37 were WITHHELD. serv_prompt_guard reported no trigger in any of the 40; the refusals were the adjudicator's own (artifact). The current rubric scored 24/24 per arm on the hard set, but its gate 4 was tightened against that same set, so that is a tuning-set result. On 14 held-out mandates, written blind and pre-registered, BRAID off got 13 right (95% interval 69–99%); BRAID on refused 35 of its 56 calls (artifact). What we measured, in full.

Chain notes

On-chain proofs

ERC-8004 identity
Contract audit · x402
$0.25 · settled on Base to 0x6328…7911
Guard on 4663 · free
ERC8056Guard · verified
Position check · x402 · under frozen 95265
$0.01 · settled on Base to the 95265 wallet, whose key is lost
Self-attestation · 8453:95374 · self-issued

Withheld by the verifier — 0

Findings the detector produced and the verifier refused to publish. They are shown because a verification claim is only worth anything if the misses are visible too, and because could not check and is false are different statements that most tools collapse into silence. Only mismatch impugns a finding; the rest record the limits of what this RPC could confirm.

Separately, 5 verified findings that would name a holder contract are withheld from this site by policy: they are counted in the integrator panel above, and the $0.25 contract audit answers for an address you supply.

The verifier withheld nothing at block 82990434.
All 118 citations across 59 findings re-fetched and matched byte-for-byte. Earlier sweeps withheld up to 11 at a time — the cause was the RPC pruning state faster than a 12-minute sweep could finish, which is why verification now runs inline at each asset's own block rather than as a later pass.