On 10 October 2026, 21 of 25 tokenized stocks on Solana filled a $100 buy within 1% of the real share. One filled 28% above it while the quote showed 0% price impact. The script to check any token is included.
A $100 Buy of Tokenized Silver Showed 0% Price Impact and Paid 28% Over the Share
You open a swap screen on Solana and type $100. You pick a tokenized stock. The screen shows a price impact number, and when it is small you take the price as fair.
In the stock market you already do one more check. An ETF has a market price, and it has the value of what the fund holds, and you look at one against the other. A tokenized stock has the same two numbers. There is the price the token trades at on-chain, and there is the price of the real share behind it. Price impact is about your order and the pool. As the numbers below show, it can read zero while the token sits far from the share.
We ran both checks with one script and no API key, and you can run the same script at the end of this page. On 10 October 2026, 21 of 25 tokenized stocks on Solana filled a $100 buy within 1% of the real share, and one filled 28% above it while the quote showed 0% price impact.
Key findings
- 21 of 25 tokenized stocks paid within 1% of the real share on a $100 buy.
- SLVx, the token for the iShares Silver Trust, showed 0% price impact on that buy and paid 28.28% over the share.
- Five tokens showed an impact that rounds to zero at that size. Four of them paid within a quarter of a percent of the share, the fifth was SLVx.
- At $10,000 the same SLVx quote showed 93.33% impact.
- VOOx had no route at all, and IJRx showed 99.62% impact on the small buy.
What a quote gives you
Every swap screen on Solana that routes through Jupiter starts from a quote. The quote has a field called outAmount. Jupiter’s docs describe it as “Best output amount after deducting AMM fees and platform fees”. So it is the number of tokens you would receive.
The same quote has a field called priceImpactPct. The docs list it as a string and give it no description. A swap screen built on Jupiter can show you this number as price impact.
You do not need the second field to know what you pay. Dollars in, divided by tokens out, is your price. Put that price next to the real share price and you have the check the swap screen leaves out.
What 25 tokens paid
The run took one minute, just after 06:00 UTC on Saturday 10 October 2026. US exchanges were closed for the weekend. Each token got two test buys, a small one and a large one. The share price is the one Jupiter’s asset API reports for the stock behind each token.
| Token | Impact, $100 | Paid vs share, $100 | Impact, $10k | Paid vs share, $10k |
|---|---|---|---|---|
| NVDAx | 0.01% | +0.46% | 0.02% | +0.47% |
| TSLAx | 0.00% | +0.04% | 0.13% | +0.22% |
| AAPLx | 0.21% | +0.17% | 0.43% | +0.39% |
| MSFTx | 0.18% | +0.05% | 0.18% | +0.05% |
| AMZNx | 0.31% | +0.26% | 0.63% | +0.58% |
| GOOGLx | 0.00% | +0.22% | 0.01% | +0.23% |
| METAx | 0.37% | +0.27% | 0.51% | +0.42% |
| MSTRx | 0.00% | +0.22% | 0.05% | +0.31% |
| SPYx | 0.02% | +0.21% | 0.02% | +0.21% |
| QQQx | 0.03% | +0.24% | 0.11% | +0.32% |
| SPCXx | 0.03% | +0.24% | 0.09% | +0.30% |
| VOOx | no route | no route | no route | no route |
| IJRx | 99.62% | no usable market | 100.00% | no usable market |
| GLDx | 0.00% | -0.08% | 0.05% | -0.03% |
| SLVx | 0.00% | +28.28% | 93.33% | no usable market |
| NFLXx | 1.00% | +2.30% | 13.56% | +17.16% |
| MRNA | 0.42% | -0.71% | 2.27% | +1.17% |
| LLY | 0.17% | +0.13% | 0.33% | +0.29% |
| MU | 0.02% | +0.51% | 0.04% | +0.53% |
| INTC | 0.04% | +0.72% | 0.07% | +0.75% |
| AMD | 0.19% | +0.50% | 0.77% | +1.08% |
| MRVL | 0.58% | +0.81% | 0.64% | +0.87% |
| SNDK | 0.17% | +0.75% | 0.18% | +0.76% |
| SKHY | 0.03% | +0.52% | 0.04% | +0.54% |
| HOOD | 0.49% | +0.24% | 0.58% | +0.33% |
Most of the list looks the way you would hope. For 21 of them the price paid stayed inside 1% of the share on the small buy. The lowest was MRNA, a little under the share, and the highest was MRVL, a little over it.
Size changes the picture on the thin names, the same way large trades fail on a DEX. NFLXx is the clear case. Its gap to the share is about seven times wider on the large buy than on the small one. Where the script printed a gap above one thousand percent, we wrote “no usable market” in the table.
The run was on a weekend. Part of each small gap may be the market pricing in news while the exchange is shut. One run cannot separate that from cost, and we make no claim about which it is.
The token that read 0% and paid 28% over
SLVx is the one row where the two checks disagree completely. These are the numbers for it from around the same time.
| What | Value |
|---|---|
| Reported price impact, $100 buy, 06:03 UTC | 0% |
| Reported price impact, $100 buy, 04:36 UTC | 18.29% |
| Tokens returned for $100 | 1.42303173 |
| Price paid per token | $70.27 |
| Real share price, SLV | $54.78 |
| Price paid against the share | +28.28% |
| On-chain price reported by Jupiter | $75.86 |
| Liquidity reported for the token | $504 |
| Volume in 24 hours | about $7 |
| Holders | 313 |
| Route | one Whirlpool pool |
The quote went through a single Whirlpool pool, which is a concentrated liquidity pool. Almost nobody trades there. With that little trading the pool’s price sits far from the share, and a small order does nothing to move it. So the quote comes back with zero impact.
No, a low impact number does not tell you the price is fair, because all it measures is your order against the pool. A pool always quotes a price, even when nobody has traded in it all day.
The number also moves between runs. About ninety minutes earlier the same quote reported a large impact, which is the second row of the table. US exchanges were closed the whole time.
Run it yourself
You need Python 3.9 or newer. There is nothing to install and no key to set. Save this as fill_cost.py.
"""Measure what a tokenized stock buy really costs on Solana.
For each token: ask Jupiter for a quote, then compare the price the quote
pays with the on-chain price and with the real share price.
"""
from __future__ import annotations
import json
import time
import urllib.request
USDC = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
ASSETS_URL = "https://datapi.jup.ag/v1/assets/search?query="
QUOTE_URL = "https://lite-api.jup.ag/swap/v1/quote"
SIZES = (100, 10_000) # USD per test buy
TOKENS: dict[str, str] = {
"NVDAx": "Xsc9qvGR1efVDFGLrVsmkzv3qi45LTBjeUKSPmx9qEh",
"TSLAx": "XsDoVfqeBukxuZHWhdvWHBhgEHjGNst4MLodqsJHzoB",
"AAPLx": "XsbEhLAtcf6HdfpFZ5xEMdqW8nfAvcsP5bdudRLJzJp",
"MSFTx": "XspzcW1PRtgf6Wj92HCiZdjzKCyFekVD8P5Ueh3dRMX",
"AMZNx": "Xs3eBt7uRfJX8QUs4suhyU8p2M6DoUDrJyWBa8LLZsg",
"GOOGLx": "XsCPL9dNWBMvFtTmwcCA5v3xWPSMEBCszbQdiLLq6aN",
"METAx": "Xsa62P5mvPszXL1krVUnU5ar38bBSVcWAB6fmPCo5Zu",
"MSTRx": "XsP7xzNPvEHS1m6qfanPUGjNmdnmsLKEoNAnHjdxxyZ",
"SPYx": "XsoCS1TfEyfFhfvj8EtZ528L3CaKBDBRqRapnBbDF2W",
"QQQx": "Xs8S1uUs1zvS2p7iwtsG3b6fkhpvmwz4GYU3gWAmWHZ",
"SPCXx": "Xs3oZwbHvqis4NYcf4YKWmEia2eC84wSiVrcYcTqpH8",
"VOOx": "Xsd7TduTbjuYCFL7Uoujb8SbkZLmUsuYNLn7KdvX21x",
"IJRx": "XsyZcb97BzETAqi9BoP2C9D196MiMNBisGMVNje2Thz",
"GLDx": "Xsv9hRk1z5ystj9MhnA7Lq4vjSsLwzL2nxrwmwtD3re",
"SLVx": "XsxAd6okt8y1RRK6gNg7iJaqiWNiq5Md5EDf3ZrF2dm",
"NFLXx": "XsEH7wWfJJu2ZT3UCFeVfALnVA6CP5ur7Ee11KmzVpL",
"MRNA": "MRNAzXzhNcaEXJPibHEn8cd4vyekCDiivTyEwswLUCT",
"LLY": "LLYuwZ33keFihgwoxXsBawy31AiRFLFSva32TYq5TvD",
"MU": "MUxEsUKSMACyw5fZf68wxf5FLnZVhtU9CwH8uNNGay1",
"INTC": "iNTCy1qTsUEZQe3DSocLz1ZXXai34Gdw8THQh5rxFaF",
"AMD": "AMD8XwJXgQ9WV45Wyj9yFLejxzf2J6VM1PJY8bJEjeES",
"MRVL": "MRVLSjkR2ceUBukujaD3xCyHP1H3B2SzpsNTZF546jo",
"SNDK": "SNDKbwMUQvZhnLnxLduradgLHG5KrPuKwpnrkkGRhfH",
"SKHY": "SKHYhSjuRWHgikq8eRKbtBbpABgJSkd7ytQV14i9EQ3",
"HOOD": "HooDYv5RewLRiMLnEVq3VJqdqxhuE6c5eYvqejMC3e9A",
}
def _get(url: str) -> object:
"""Fetch a URL and parse the JSON body. Returns None on any failure."""
request = urllib.request.Request(url, headers={"User-Agent": "fill-cost/1.0"})
try:
with urllib.request.urlopen(request, timeout=20) as response:
return json.load(response)
except Exception:
return None
def load_assets(mints: list[str]) -> dict[str, dict]:
"""One call for every token: prices, decimals and the share reference."""
rows = _get(ASSETS_URL + ",".join(mints)) or []
return {row["id"]: row for row in rows if row.get("id") in mints}
def load_quote(mint: str, usd: int) -> dict | None:
"""The quote Jupiter would fill for a buy of `usd` dollars of USDC."""
url = (
f"{QUOTE_URL}?inputMint={USDC}&outputMint={mint}"
f"&amount={usd * 10**6}&slippageBps=100&restrictIntermediateTokens=true"
)
quote = _get(url)
return quote if isinstance(quote, dict) and "outAmount" in quote else None
def paid_vs_share(usd: int, quote: dict, asset: dict) -> float | None:
"""Price paid per share-equivalent against the real share, in percent."""
share = (asset.get("stockData") or {}).get("price")
raw_price = (asset.get("scaledUiConfig") or {}).get("usdPricePrescaled") or asset.get("usdPrice")
if not share or not raw_price or not asset.get("usdPrice"):
return None
paid_raw = usd / (int(quote["outAmount"]) / 10 ** asset["decimals"])
paid = paid_raw * asset["usdPrice"] / raw_price # raw units to share units
return (paid / share - 1) * 100
def main() -> None:
assets = load_assets(list(TOKENS.values()))
print(f"{'token':<7} {'size':>7} {'impact':>8} {'vs share':>9}")
for symbol, mint in TOKENS.items():
for usd in SIZES:
quote = load_quote(mint, usd)
time.sleep(1.1) # the keyless tier allows about one request a second
if quote is None or mint not in assets:
print(f"{symbol:<7} {usd:>7} {'no route':>8}")
continue
impact = float(quote["priceImpactPct"]) * 100
gap = paid_vs_share(usd, quote, assets[mint])
shown = "n/a" if gap is None else f"{gap:+.2f}%"
print(f"{symbol:<7} {usd:>7} {impact:>7.2f}% {shown:>9}")
if __name__ == "__main__":
main()
Run it.
python3 fill_cost.py
The script waits about a second between quotes, so the full list takes about a minute. These are the first lines and the SLVx lines from our run.
token size impact vs share
NVDAx 100 0.01% +0.46%
NVDAx 10000 0.02% +0.47%
TSLAx 100 0.00% +0.04%
TSLAx 10000 0.13% +0.22%
SLVx 100 0.00% +28.28%
SLVx 10000 93.33% +1975.51%
Your numbers will be different, because prices and pools move. To add a token, put its symbol and mint address in TOKENS.
To look at one raw quote without the script, ask for the small SLVx buy directly.
curl -s "https://lite-api.jup.ag/swap/v1/quote?inputMint=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v&outputMint=XsxAd6okt8y1RRK6gNg7iJaqiWNiq5Md5EDf3ZrF2dm&amount=100000000&slippageBps=100&restrictIntermediateTokens=true" | python3 -c 'import json,sys; q=json.load(sys.stdin); print(q["outAmount"], q["priceImpactPct"], q["routePlan"][0]["swapInfo"]["label"])'
At 06:06 UTC it printed this.
142303173 0 Whirlpool
The first number is the token count before the decimal point is placed. SLVx has eight decimals, so move the point eight places and you get the count in the table above. Jupiter’s docs say this version of the Swap API is no longer actively maintained and that a newer version replaces it. It still answered on the day of this run.
Where to see the live numbers
You can see both checks for every token on the chaotic.markets data page. A new reading is saved every 5 minutes, and SLVx has its own page.
On chaotic.markets a token is marked “no market” when a small buy fills more than 10% away from the real share. Baskets leave that token out until the price comes back.
Newsletter
Get chaotic.markets updates and new data articles by email.
You confirm by email, and you can unsubscribe from any message. The list is kept by Kit.