near-toll-audit / thesis/README.tmpl.md · raw
# NEAR Toll AuditAn evidence-first investment thesis on NEAR that anyone can re-run, built at NEAR HACKATHON for the Investment Thesis track (`thesis`).- **Live dashboard:** https://apps.swiftbotlab.workers.dev/near-toll-audit/- **Memo, with the case against it:** [THESIS.md](THESIS.md)- **Definitions:** [METHODS.md](METHODS.md)![Dashboard](docs/assets/hero.png)## What it isNEAR's investment case now rests on NEAR Intents. Most public numbers repeat one data source and stop at volume. This project asks the questions an investor would ask next: is the volume real, who keeps the fee, does any of it reach the token, and can the toll be raised?It is a one-command pipeline from public data to a thesis, a live dashboard, an editable valuation model and kill criteria that grade themselves.This is research, not investment advice. We make no claim about holdings.## Conclusion: chain data through {{m:as_of:text}}, prices and fees {{m:market_as_of:text}}**NEAR built a real toll road. The token does not own the tolls yet.**| Question | Answer | Evidence ||---|---|---|| Is the flow real? | Settled flow yes, user demand is a range | End-user demand is about {{m:wd_floor_share_of_reported_pct:pct0}} to {{m:wd_ex_top10_share_of_reported_pct:pct0}} of reported volume, leaving out the 100 or the 10 largest addresses. One-way on-chain flow, {{m:flow_ratio_median:pct_from_x}}, is a ceiling and includes solver rebalancing || Is Intents leading? | Yes, among native swap rails with public data | {{m:rail_share_13w:pct0}} share over 13 weeks, down from {{m:rail_share_jun26:pct0}} in June || Who keeps the fee? | Mostly wallets and partners, less than before | NEAR kept {{m:capture_30d_pct:pct0}} of gross fees in 30 days, {{m:capture_all_time_pct:pct0}} all time; partners, wallets and solvers kept the rest || Does it reach the token? | Partly, by choice, not by rule | {{m:revenue_wallets_near:nearm}} held in two wallets, burn plus revenue equalled {{m:offset_30d_pct:pct0}} of issuance in {{m:window_month_name:text}} at best || Can the take rise? | Inconclusive | Intervals do not rule out a 25% loss of volume against rivals || What is priced in? | {{model:implied_multiple_low}} to {{model:implied_multiple}} today's volume | {{m:price:usd2}} depends on what you pay for the chain || What is it worth? | {{model:weighted}} on our weights, sensitive to them | Bear {{model:bear}}, base {{model:base}}, bull {{model:bull}}. {{model:weighted_bull_30}} on a 30% bull weight. Market {{m:price:usd2}} |The table above, the memo, the live dashboard and the submission text all come from this one snapshot. `python3 run.py` pulls fresh data and moves the dashboard; only `pipeline/freeze.py` issues a new memo. Kill rules T6 and A5 were added on 2026-11-12 after review and graded on this same snapshot; the ledger records when each row entered.## Try itYou need Python 3.9 or newer. No install, no keys, no network for steps 1 to 4.| Do | See ||---|---|| `git clone https://code.swiftbotlab.workers.dev/near-toll-audit.git && cd near-toll-audit && python3 run.py --offline` | `snapshots verified: N ok, 0 bad`, then every step at `exit 0` and every test `ok`, in under a minute || `python3 -m http.server -d docs 8000`, then open http://localhost:8000 | The same dashboard, built from the snapshots on your disk || In `thesis/scenarios.json`, set the `base` case `cagr` to `{{model:implied_cagr_raw}}`, then run `python3 pipeline/analyze.py && python3 pipeline/model.py` | `"base"` comes out at about {{m:price:usd2}}, the market price: this is the reverse DCF || Change one byte in any file in `raw/latest/`, then run `python3 run.py --offline` | The run stops with `HASH MISMATCH` || Change any number in `THESIS.md`, then run `python3 pipeline/verify_claims.py` | `MISMATCH THESIS.md`, because the memo is rendered from frozen metrics || Open the dashboard, go to **Valuation**, drag **Volume growth a year** | Value per NEAR, the reverse DCF and the heatmap update at once || Open the dashboard, go to **Kill list** | Eleven criteria with dates and thresholds, each graded by code || `python3 run.py` | A live refresh from every keyless source, about eight minutes |## How the fee numbers fitAll from revenue.near.org, so the differences are windows, not sources. NEAR's 30-day split covers the 30 days to the pull on {{m:market_as_of:text}}, not calendar {{m:window_month_name:text}}, which is why it differs from the monthly series.| Number | Value | Window and formula ||---|---|---|| Gross fee | {{m:gross_bps_30d:bps1}}, or {{m:per100_gross:usd3}} per $100 | {{m:window_month_name:text}}: gross fees / volume || NEAR's share of gross fees | {{m:capture_30d_pct:pct1}} | NEAR's own 30-day split (front end + partners + quote improvement) || Reaches NEAR per $100 | {{m:per100_captured:usd3}} ({{m:per100_captured_bps:bps2}}) | {{m:per100_gross:usd3}} x {{m:capture_30d_pct:pct1}} || Captured rate, one month | {{m:net_bps_30d:bps2}}, or {{m:capture_month_pct:pct1}} of the gross fee | {{m:window_month_name:text}}: revenue {{m:rev_30d:usd}} / volume || Captured rate, three months (kill row T3) | {{m:net_bps_90d:bps2}} | last three full months: revenue {{m:rev_90d:usd}} / volume || Revenue a year, run rate (used for the {{m:near_multiple:x0}} market-cap multiple) | {{m:rev_run_rate:usd}} | {{m:window_month_name:text}} x 12 || Revenue a year, annualised (kill row A2) | {{m:rev_annualised:usd}} | last three full months x 4 |## What is different here- **A pricing-power test.** A toll road is worth what it can charge, so we tried to measure that, with rival rails as controls and every lasting change in a partner's posted fee from swap data. The result is inconclusive, and the memo says so.- **Swap-level data.** The Intents Explorer gives each swap's partner, stated fees and dollars in and out. We sample one full day a week with a seeded draw.- **BigQuery across the full chain history.** Exact mint and burn from block headers, signer cohorts, funder concentration and gas by contract.- **An independent check on volume.** We rebuild flows from raw token events instead of repeating a dashboard, and report the range that leaves for user demand.- **Every number traces back.** Raw pulls carry a date and sha256. The memo is rendered from frozen metrics, so a typed number fails a test.## How it works```fetch_public.py  keyless APIs ──────┐fetch_chain.py   NEAR RPC ──────────┤run_bq.py        BigQuery SQL ──────┼─> raw/ (date + sha256) ─> analyze.py ─> metrics.json ─┬─> model.py ─> model.jsonfetch_explorer.py swap sample ──────┘                                       charts.json   ├─> grade.py ─> ledger/grades.jsonl                                                                                           └─> build.py ─> docs/ (static site)````.github/workflows/refresh.yml` can rerun this every six hours on a runner. The public copy is a static build, and its header and footer name the snapshot dates. If a source fails, its last good snapshot stays and the page footer names it.## Data sources| Source | Key | Used for ||---|---|---|| NEAR RPC, FastNEAR, archival RPC | None | Protocol parameters, validators, wallets, contract views || [NEAR BigQuery public dataset](https://docs.near.org/data-infrastructure/big-query) | Free Google account | Headers, signers, cohorts, funders, gas, token flows || [NEAR Intents Explorer API](https://docs.near-intents.org/integration/distribution-channels/1click-api/explorer/introduction) | Free read-only JWT | Swap-level volume, partners, fees, user cost || DefiLlama | None | Intents volume and fees, rival rails, chains, stablecoins, comps || revenue.near.org | None | The official claims we test || CoinGecko, Coinbase | None | Prices, market caps, a price cross-check || NearBlocks | None | Long daily series || GitHub API | None | Core repo activity || nrretf.com | None | ETF holdings |To refresh the keyed sources, set `GOOGLE_APPLICATION_CREDENTIALS` and run `python3 run.py --bq`, or set `INTENTS_JWT` and run `python3 pipeline/fetch_explorer.py`, about four hours, then `python3 run.py --offline --explorer`. Swap rows stay out of git because of size. Aggregates and a sample manifest are committed, and the seeded sampling lets anyone draw the same swaps.## Repo map| Path | What ||---|---|| `run.py` | The one command || `pipeline/` | Fetchers, SQL, analysis, model, grader, site build || `raw/` | Snapshots with dates and sha256 || `thesis/` | Scenarios, kill criteria, memo template, frozen metrics || `ledger/grades.jsonl` | Hash-chained grading history. Public git history is what makes a rewrite visible || `docs/` | The published site || `tests/` | Parity between the Python and browser models, invariants, tamper tests |## AI toolsThe code, SQL and first drafts of the memo were written with Claude Code (Anthropic's coding assistant) under our direction. The questions, data choices, kill thresholds and conclusions are ours. Every number is computed by the code in this repo from the committed snapshots, `pipeline/verify_claims.py` fails if the memo carries a hand-typed number, and the tests in `tests/` run in the one command above. Nothing in the pipeline calls an AI model.## LibrariesPython standard library for everything except a live BigQuery refresh, which uses `cryptography` 50.0.2 to sign the Google login. Node runs only the model parity test, and that test is skipped if Node is missing. The site uses no third-party scripts, and its charts are hand-written SVG.## Hackathon disclosureAll code here was written inside the hackathon window, in this new repo, with no earlier baseline. This team's other NEAR HACKATHON project is [Duly](https://code.swiftbotlab.workers.dev/duly), pay-by-link invoices that settle on NEAR. The two are independent.## LicenseMIT.