INSTRUCTION BOOKLET · KEEP FOR REFERENCE
SAND MANUAL
SECTION 01
START
Power on. The console boots SAND OS, checks the channel (chain id 4663) and prints the current head. Pick a cart from the menu with ↑↓ and press A. Paste a cartridge, press START (or BOOT) to read it.
A = select / save slot · B = back · START = boot / re-read · SELECT = READOUT ⇄ RAW · RH = channel details · ←→ = tabs · ↑↓ = scroll
The boot animation can be skipped after your first visit; the preference is stored locally. Motion is disabled entirely when your system asks for reduced motion.
SECTION 02
CARTRIDGES
SAND detects the cartridge type from what you paste:
- 0x + 64 hex characters → TRACE (transaction)
- 0x + 40 hex characters → address; bytecode decides WALLET vs CONTRACT, and ERC-20 / pool probes decide TOKEN or POOL
- digits, or "latest" → BLOCK
- an explorer URL → the identifier inside it
An address is never called a token because it looks like one. It is a token when totalSupply(), decimals(), balanceOf() and allowance() return well-formed words and the bytecode dispatcher carries the core ERC-20 selectors.
SECTION 03
TOKEN CART
Reads name(), symbol(), decimals() and totalSupply() by eth_call, all pinned to one block. Adds bytecode size, the contract's own ETH balance, the EIP-1967 proxy slot, and Blockscout verification when the indexer answers.
MARKET tab: the deepest pool located across the registered V2 and V3 factories (price, depth), every other pool that answered, indexed holders, indexed activity counters and the SAND SCORE. Pool price, liquidity and the fully-diluted market cap are printed only when a real pool was read; otherwise they say NOT AVAILABLE.
The explorer's own market figures (USD price, 24h volume, circulating market cap) are shown as separate rows labelled INDEXER. They come from Blockscout's market data, never from a pool read, and they never feed the SAND SCORE. Activity uses the token's lifetime transfer counter from the explorer.
With a controller connected, YOUR BALANCE is read from balanceOf(your address).
SECTION 04
WALLET CART
ETH balance (eth_getBalance), nonce (eth_getTransactionCount), type (bytecode is 0x) and the block the reads were pinned to. Transaction history is INDEXER DATA from Blockscout, first page only; the RPC alone cannot list transactions by address, and SAND says so on the screen.
TOKENS tab: ERC-20 holdings listed by the indexer, then the top eight re-read with balanceOf(wallet) at the pinned block. A ✓ means the contract and the indexer agree; a ≠ prints both values.
SECTION 05
TRACE CART
eth_getTransactionByHash + eth_getTransactionReceipt. Fee = gasUsed × effectiveGasPrice and is labelled CALCULATED. The method selector is matched against a small local table of common signatures; a match is labelled, a miss stays UNDECODED.
Events are decoded in two labelled layers. First, SAND's fixed ABI of standard events (ERC-20/721/1155 Transfer and Approval, ERC-1155 TransferSingle/Batch, UniswapV2 Swap/Sync/Mint/Burn, WETH Deposit/Withdrawal). Then, for logs that layer could not read, the explorer's decoding from the emitter's verified ABI or signature database, tagged INDEXER. The method name and decoded input parameters use the same explorer source when the target contract is verified. Anything still unknown prints its raw topics and data. SAND never invents an ABI.
SECTION 06
POOL CART
Pools are read only from registered factories (SUPPORTED_POOLS). For a token, SAND calls getPair(token, quote) on each registered Uniswap V2-compatible factory for each quote asset, verifies the pair has bytecode, then reads token0(), token1(), getReserves() and totalSupply() at one block.
price = reserve_quote × 10^dec_base ÷ (reserve_base × 10^dec_quote)
Uniswap V3-compatible factories use getPool(token, quote, fee) for the 0.05% / 0.3% / 1% tiers and read slot0(), liquidity() and fee(). Price comes from sqrtPriceX96. V3 depth is the pool contract's real token balances (balanceOf(pool) on both sides); the in-range virtual reserve is shown in the STATE tab as a labelled estimate. The registered V3 factory is the verified Robinhood Chain UniswapV3Factory 0x1f7d…2efa, checked on-chain before registration.
When several pools answer, the deepest one (quote-side depth, in USDG where a reference exists) is priced and the others are listed under OTHER POOLS.
WETH-quoted values get a USDG reference (price × WETH/USDG from the same factory at the same block). USDG is a stablecoin, so the label is USDG, never USD.
SECTION 07
SAND SCORE
Deterministic, never model-generated. Weights: LIQUIDITY 30, DISTRIBUTION 25, ACTIVITY 20, CONTRACT 15, FRESHNESS 10. Signals that cannot be measured are removed from the available weight instead of scoring zero:
FINAL = earned ÷ available × 100
LIQUIDITY (30)
pool in a registered factory → 10 pts
quote depth in USDG:
- ≥ 100,000 USDG → 15 pts
- ≥ 10,000 USDG → 11 pts
- ≥ 1,000 USDG → 7 pts
- ≥ 100 USDG → 3 pts
- otherwise → 0 pts
quote depth in WETH (no USDG reference):
- ≥ 50 WETH → 15 pts
- ≥ 5 WETH → 11 pts
- ≥ 0.5 WETH → 7 pts
- ≥ 0.05 WETH → 3 pts
- otherwise → 0 pts
reserves read ≤ 20 blocks behind head → 5 pts
DISTRIBUTION (25)
top holder share:
- ≤ 5 % → 12 pts
- ≤ 15 % → 9 pts
- ≤ 30 % → 6 pts
- ≤ 50 % → 3 pts
- otherwise → 0 pts
top ten share:
- ≤ 20 % → 13 pts
- ≤ 40 % → 10 pts
- ≤ 60 % → 6 pts
- ≤ 80 % → 3 pts
- otherwise → 0 pts
ACTIVITY (20)
indexed transactions (lifetime):
- ≥ 100,000 txs → 12 pts
- ≥ 10,000 txs → 9 pts
- ≥ 1,000 txs → 6 pts
- ≥ 100 txs → 3 pts
- ≥ 1 txs → 1 pts
- otherwise → 0 pts
indexed token transfers (lifetime):
- ≥ 10,000 transfers → 8 pts
- ≥ 1,000 transfers → 6 pts
- ≥ 100 transfers → 4 pts
- ≥ 10 transfers → 2 pts
- ≥ 1 transfers → 1 pts
- otherwise → 0 pts
CONTRACT (15)
ERC-20 confirmed → 5 pts · no EIP-1967 proxy → 4 pts · verified source → 6 pts (excluded when the indexer is down)
FRESHNESS (10)
reads ≤ 5 blocks behind → 6 pts · ≤ 50 → 4 pts · else 1 pt
indexer ≤ 1,000 blocks behind → 4 pts · ≤ 10,000 → 2 pts
SAND SCORE describes observable on-chain conditions. It is not a prediction, recommendation, or guarantee. See METHOD for a worked example.
SECTION 08
SOURCES
- RPC — Robinhood Chain JSON-RPC (eth_getBalance, eth_getCode, eth_getBlockByNumber, eth_getTransactionByHash, eth_getTransactionReceipt, eth_getStorageAt, eth_getTransactionCount, eth_chainId, eth_blockNumber)
- CONTRACT — eth_call answers from the contract itself
- POOL — pair/pool state read at the pinned block
- INDEXER — Blockscout API v2: tokens (+ market figures), token counters, holders, addresses, address counters, ERC-20 balances, transactions (decoded), transaction logs (decoded), verified smart-contract source/ABI, network stats; always labelled, always with a retrieval time
- CALCULATED — derived values; the formula is printed in RAW
Hover any badge for the exact origin. Open RAW on any readout to see every read in order.
SECTION 09
LIMITATIONS
- JSON-RPC cannot enumerate holders or list transactions by address; those screens depend on the indexer.
- The public node is not an archive node: reads are pinned to the current head, not to arbitrary old blocks.
- Only registered factories are consulted; a token traded elsewhere shows NO POOL, not a guessed price.
- Interface detection is evidence-based: ERC-721/1155 are YES only through ERC165; selector scans alone produce UNKNOWN.
- Holder concentration counts pools, lockers and bridges as holders because the chain does not say which is which.
- Volume, market history and off-chain facts are never printed.
SECTION 10
RPC
CHANNEL 4663 · NATIVE ETH · PUBLIC RPC https://rpc.mainnet.chain.robinhood.com · EXPLORER https://robinhoodchain.blockscout.com
The server tries RH_RPC_URL, then ALCHEMY_ROBINHOOD_RPC_URL, then the public RPC, failing over on transport faults only. Every response verifies eth_chainId first; a mismatch suspends readouts and prints CHANNEL MISMATCH. Private endpoint keys never reach the browser: the page talks to same-origin routes and a read-only relay.