What run 20260829-224013 did, what it found, and the causal chain behind the dead referral economy — every number below is read from the run's own telemetry, state exports, and source code, not estimated.
It does not model TotoChain — it runs TotoChain. The production runtime executes under sp_io::TestExternalities: every agent action is a real signed extrinsic through RuntimeCall::dispatch, every fee is charged by the production PotentialCurrencyAdapter, and every on_initialize / on_finalize / on_idle hook runs in block order — 28,800 one-second blocks per simulated day.
What is modelled is the population: who acts, when, and how often. Ten thousand agents with research-calibrated personas, heavy-tailed activity weights, constant-hazard churn with resurrection, Bass-diffusion adoption, and a friendship overlay carrying an embedded paid-referral forest. The question the whole apparatus answers: does a chain launched from empty genesis ever reach a state where its own economy and governance are usable?
No transaction pool / CheckWeight. A day's activity lands in one block, so the run can say nothing about congestion or block capacity.
on_idle gets Weight::MAX. The deferred-reward sweeper runs at its full 1,000-edge/block cap instead of a real node's leftover weight. Queue behaviour (filling at boundaries, draining after) is real; per-block cost is a harness artifact. No economic quantity is affected.
30 months means two full 13-month supply cycles — no previous run had crossed a second boundary. New in this run: weekly per-account state exports from month 3 (4× the resolution of earlier runs), which is what finally separated composition effects from real balance decay, and localized the famous "month-6 collapse" to a 4-day window.
One insolvency check plus one skipped intent path kill the entire assembly economy. Everything downstream — single-piece collections, the dead trade market, floor-rate unlock payouts, and ultimately the fee death spiral — traces to this chain:
1 · Sponsor insolvency, off by exactly one ED. Sponsoring a referral stakes 32×ED and requires free ≥ stake + ED = 33×ED (can_fund_referral, simulation/tests/economic.rs:1557). A freshly onboarded user is seeded with exactly 32×ED. The graph model picks a social inviter at the configured paid-regime rate (R ≈ 0.95), but the affordability filter rejects ~81% of them, and onboarding falls back to a genesis validator as sponsor, round-robin (economic.rs:1637). Net realized user-referral rate: 1,635 / 10,000 = 0.16.
2 · Mid-life invitations never dispatch. Agents emitted 17,012 Intent::Refer over 30 months; the driver at economic.rs:4275 skips every one (sentinel invitee == u32::MAX, commented "until an explicit invite driver exists" — never written). exec_refer = 0 for the whole run, with zero failures: the extrinsic is never attempted, not attempted-and-failing.
3 · A sim gate keys on the wrong counter. market_possible checks refer_ok > 0 (economic.rs:3118, :3997) — but the piece multiplier reads DescendantCount (full active subtree, pallets/referral/src/lib.rs:619 → pallets/fractional-nft/src/lib.rs:563), which is non-zero for validators and 340 users. So the assembly-market sweep never ran even for the multi-piece collections that do exist — the run log shows "skipped (no referral yet)" on all 840 days.
The premise needs one correction: the distribution isn't capped at 3 — the report chart is visually crushed by the 1-piece bar. Of the 8,297 collections still live at day 840: 62.3% have 1 piece, 13.5% have 2, 3.2% have 3, and a real tail runs to 603 pieces. The 41 collections of 100+ pieces are all validator-minted (each validator sponsors ~760 users, and mint count = its active descendant count + 1) and hold 39.3% of all live pieces.
But the instinct was right where it matters: ~97% of users have zero active referrals — not because activation fails (all 10,000 onboarding referrals activated successfully) but because the referral edges nearly all point at validators (cause 1) and no new edges are ever created mid-life (cause 2). The 2–3-piece collections belong to the 340 users who managed to refer one or a few people.
| stage | count |
|---|---|
| users onboarded | 10,000 |
| on-chain referral edges created & activated | 10,000 |
| … referred by another user | 1,635 (16.4%) |
| … sponsored by a validator (fallback) | 8,365 (83.6%) |
mid-life Refer intents emitted | 17,012 |
| … dispatched on-chain | 0 |
| forest mean depth / max depth | 0.37 / 9 |
| quantity | pieces |
|---|---|
| minted via submissions | 84,294 |
| wildcard fills during unlock | 935 |
| burned by unlocks | 45,191 |
| live (users 40,016 + pool 22) | 40,038 |
| check: 45,191 + 40,038 | = 85,229 ✓ |
Wildcards first appear at month 17 and stay marginal (2.1% of claims) — with 1-piece collections, no gap ever needs filling.
Fees are paid from locked potential; potential decays by 1/28 daily; emission halves monthly and the cycle budget runs dry early. With the only conversion path paying the 0.0100% floor, users cannot rebuild spendable balance — so the chain progressively locks its own users out.
Emission halves monthly inside a 13-month cycle, so the back half of every cycle mints almost nothing while the daily 1/28 decay keeps draining accounts into the pool. At each boundary the cycle burn destroys the reward pool's burnable surplus — and sets exactly that amount as the next cycle's mint budget (CycleSupply := burned). It is a closed re-mint loop over the pool account; user balances are never touched by the boundary — they are already at dust from the decay.
Rate. Creation halves every month and is effectively zero by month 10–13 of each cycle; destruction never slows — every account loses potential/28 daily (~3.6%/day, burn.rs:119) plus fees on top. The chart above shows the crossover: from the second month of every cycle, more potential is recycled than created. From then on the population drains regardless of behaviour — 62.7% of accounts were at zero by day 364, before any boundary ran.
Shape. Creation is concentrated: the author mint goes to block producers and the descendant sweep flows down referral subtrees, so inflow depends on authorship and tree position. Destruction is uniform: every holder bleeds the same proportional 1/28 share. An ordinary user — no authorship, thin tree — has inflow ≈ 0 against outflow 3.6%/day: their equilibrium balance is zero by construction. This survives every sim-harness fix; it is rate math, not behaviour.
The aggregate loop is already symmetric (burned = next cycle's budget, below). The imbalance lives at the individual-account level and in time — so the fix is balancing the two flows (tie the decay rate to the emission schedule, give emission a per-account floor, or widen the 90/10 RecycleShare split), not making them literally one flow.
cycle_preserved = 0 actually means (clarified)The event field preserved is the pool's core (non-potential-sourced) surplus left above the 1,000-TOTO genesis floor after the burn (pallets/potential/src/lib.rs:829) — not user value. It reads 0 because everything above the floor was potential-sourced: the expected value for this run. The destroyed amount is not lost either — cycle-2's mint budget is exactly boundary-1's burn (1,936,381,861) and cycle-3's exactly boundary-2's (1,793,638,861). What empties users is the daily potential/28 decay plus the halving emission — 62.7% of accounts were at zero the day before the boundary ran.
The burn clamps to physical surplus with margin exactly 0, then zeroes the whole burnable tracker — silently consuming tracked-but-unbacked units (7.94×10²⁶ at boundary 1, 9.59×10²⁵ at boundary 2; the accumulated RP-2 drift). Deterministic, shrinking as the chain matures, and currently unreported by anything except this invariant.
BlockRewardShortfall fired 24,128,464 times across 24.19M blocks; distributions succeeded on 0.35% of blocks over the run and 0.08% in the final month. The author-reward channel that is supposed to seed collections contributes almost nothing — and because a shortfall reports through events rather than dispatch errors, every invariant stays green while the mechanism is dead. Root cause is the same early budget exhaustion shown above: schedule calibration, not tokenomics.
Adoption saturates at the 10,000 carrying capacity by month 22 — but activity peaks at months 7–10 and then declines monotonically, because the population that arrived can progressively no longer afford to act.
Whole-run totals: 51,408 NFT submissions (21,175 validator + 30,233 user) · 44,046 unlocks (41,624 validator + 2,422 user) · 15,650 handshakes initiated, 14,326 completed · 13,973 sells · 10,000 activations · 7,346 votes · 2,432 attestations · 818 trades — and exactly 1 DID created in 30 months.
Wall-clock cost tracks exactly one quantity: potential-lock writes from the deferred-reward sweeper in on_idle — at a near-constant 27.5–30.6 ns per lock across five regime transitions. No population statistic ever predicted it; the event registry had been counting it all along.
Weight::MAX the harness concentrates this work; a real node spreads the identical queue across many more blocks. Read it as sustained on_idle saturation after each boundary, not as a 5-hour block.Super-linear late-run cost: per-day wall-clock rose 22.8 → 93.0 s across the final 21 days at a fixed population — every phase scaling together points at per-day iteration over grow-only structures (51,409 collections; 160,156 overlay edges). Caps feasible run length well before 60 months.
Blind telemetry: trade_sites/trade_pairs only count the bootstrap sweep (818 real trades invisible to them); wildcards_live never catches the intra-block lifecycle. Wrong gate: market_possible keyed on refer_ok (see Result 1).
RULE-CHECKED findings are deterministic rules over the run JSON (cannot hallucinate); OPEN-ENDED findings come from an independent model reading the telemetry blind. Where they agree, two methods agree.
| severity | finding | chapter | first fired |
|---|---|---|---|
| CRITICAL | Referral graph never forms — exec_refer = 0 all 30 months; root cause of the findings below | open-ended | m06 |
| CRITICAL | Every unlock is (near-)single-piece; assembly economy structurally unreachable | rule-checked | m01 |
| CRITICAL | Trade market never executes a single market trade in 840 days (candidate set empty by construction) | open-ended | m30 framing |
| CRITICAL | fNFT block reward shortfall on ~99.7% of blocks; reward channel dead while invariants stay green | both | m01 |
| CRITICAL | Creation/destruction mismatch: emission halves monthly and concentrates at authors/subtrees, while decay runs constant (1/28-daily) and uniform — recycling exceeds creation from month 2 of every cycle, so ordinary users' equilibrium potential is zero (see Supply section) | synthesis (this report) | m02 |
| CRITICAL | Spendable TOTO zero for 78.4% of accounts; top-10 hold 88.9% of free balance | open-ended | m01 |
| CRITICAL | Reward-sweep queue saturates on_idle after each boundary (741 lock-writes/block vs cap 1,000) | rule-checked | m14 |
| CRITICAL | Sim: behaviour-phase cost grows 4× in 21 days at fixed population (grow-only structure iteration) | open-ended | m30 |
| WARNING | Fee blocking: 524,819 attempts, 20× successful actions, monotonically growing | both | m12 |
| WARNING | The cycle burn preserved nothing — cycle_preserved = 0 at both boundaries (clarified: preserved = pool core surplus, not user value — see Supply section) | rule-checked | m14 |
| WARNING | Vote reputation degenerates: 96.9% zero/negative; 98.2% of referenda rejected | both | m06 |
| WARNING | Forest never branches: 84% cold signups, mean depth 0.37 — tier-2 lineage multiplier removed | rule-checked | m03 |
| WARNING | Referral-activation reward shortfall on 538 of 10,000 activations (frozen once adoption ended) | rule-checked | m03 |
| WARNING | PotentialOperationFailed fired once (session-boundary op; events-only reporting) | rule-checked | m03 |
| WARNING | Sim: trade_sites counter blind to per-agent trades (telemetry defect, not economics) | rule-checked | m03 |
| INFO | RP-2 burnable-counter drift: peaks 78,355 (m13) / 8,589 (m26), reset by each cycle burn; clamp keeps supply safe | rule-checked | m01 (downgraded m30) |
| INFO | Unlock fund is 9.1% of pool; conversions run at the floor; outflow 5.8% of inflow | open-ended | m30 |
| INFO | Sim throughput spread 392.9× (45 blk/s at m14 vs 17,652 at m1) — describes the harness, not the chain | rule-checked | m03 |
Seed onboarded users with 33×ED+ (or lower the sponsor requirement) and resolve Refer intents to concrete overlay neighbours instead of skipping them (economic.rs:1637, :4275). This is the one change that makes the design's core loop — referrals → multi-piece collections → assembly market → Hill payouts — observable for the first time. Until then, the simulation has never actually tested it.
market_possible gate.Replace refer_ok > 0 with a DescendantCount-based check (economic.rs:3118, :3997). Cheap, and provably wrong today — multi-piece collections existed from month 3 while the market sweep skipped all 840 days.
This is the central protocol-level finding (the referral failures above are harness defects). Rate: emission halves monthly to ~zero by month 10–13 while the 1/28-daily decay never slows — recycling exceeds creation from the second month of every cycle. Distribution: creation flows to block authors and their referral subtrees; destruction hits every holder uniformly — so a non-authoring, tree-poor user's equilibrium potential is zero by construction. Fixing the sim harness improves spendable income but does not touch this. Options: tie the decay rate to the emission schedule (halve them together), give emission a per-account floor that survives the halving tail, or widen the RecycleShare 90/10 split toward the unlock fund. The aggregate cycle loop needs no change — it is already closed.
Resolved at code level: the boundary touches only the pool account and re-mints the burned amount as the next cycle's budget (CycleSupply := burned, lib.rs:822) — the aggregate loop is intended and closed. The remaining design questions are narrower: (a) individual balances are not preserved — a user's share of the next cycle depends on block authorship and referral-tree position, not prior holdings; is that reset intended? (b) the loop shrinks ~7.5% per cycle (2.10B → 1.936B → 1.794B) — exactly the value converted to permanent spendable; confirm that deflation profile is the plan. What zeroes ~63% of users by cycle end is not the boundary but the creation/destruction imbalance — the previous question.
The cycle budget exhausts by month 10–12, leaving the block-author reward channel dead on 99.7%+ of blocks and firing 24.1M shortfall events that nothing surfaces. If the halving cadence is fixed, the per-month fractions need rebalancing against the cycle cap.
consume_burnable.Both boundaries silently consumed unbacked burnable (margin exactly 0). Bounded and shrinking, but unbounded in code — only the I2b advisory reports it.
Half-saturation at 350 pieces / 7,000 referrals against an observed reality of 1–5-piece unlocks means every conversion pays the floor and holder timing behaviour is unobservable. Either the curve or the mint economics needs to move.
Agents vote 65% aye by configuration, yet 110 of 112 referenda failed — likely a support/approval-threshold interaction. Until referenda can pass, vote-reputation cannot differentiate voters and the penalty branch is unreachable.
2,432 attestations ran on a fixed schedule, but DID creation happened once. Either a sim gap or a dead feature path.
The paper states "no referral is ever activated" and "every collection is single-piece" — both false (10,000 activations; a multi-piece tail to 603). It conflates the exec_refer extrinsic counter with on-chain activation state. The corrected causal story is Result 1 above, fully evidenced.
Per-day cost quadrupled over the final three weeks at a fixed population. Profile the per-day iteration over collections/overlay edges; 60-month runs are infeasible until this is bounded.