feat(thorchain): mainnet Migrate19to20 store migration

Summary

Fills the mainnet Migrate19to20 store migration (consensus version 19 → 20). It runs four independent steps, each inside its own cache context so a state drift in one step logs and skips only that step and never applies it partially — the other three still run.

  1. Bond slash reversal. Credit 0.53258717 BTC back to the BTC pool, debit the corresponding 56,773.63556220 RUNE, move that RUNE Asgard → Reserve, then refund 113,547.27112439 RUNE to the 218 affected bond providers (20 nodes). Pre-flight checks the Reserve covers the total; the per-address amounts are pinned in migration_data.go and sum-checked in a test.
  2. Low-synth-pool retirement. Reclaim to the module and burn the entire synth supply of seven pools whose synth share is under ~1% (BSC.USDC, BSC.USDT, ETH.LUSD, ETH.USDP, ETH.WBTC, ETH.XRUNE, ETH.YFI); the pools' synth units are cleared so freed backing accrues to their LPs. Nothing is paid to holders. All seven have zero savers depth.
  3. LP donations + treasury repayment (carried from the base commits): donate the BSC.USDC / BSC.USDT / BASE.ETH Secured Ops LP positions and repay the treasury 247,622.29462483 RUNE for their value at h28,076,056 (bound to the donations, 1000 bps tolerance).
  4. ETH.THOR pool restore. Donate the Secured Ops ETH.THOR LP; credit the unaccounted Asgard-held surplus (3,959,373.5995 THOR) into the pool paired with Reserve RUNE at the pinned reference THOR/USD price; cap the one later LP entrant to the asset it contributed (so the donated + surplus value accrues to the earlier LPs); and repay the treasury the position's 163,344.81856806 RUNE capital. The surplus credit is solvency-guarded (it excludes asset backing trade and secured accounts, and skips if the live state has drifted), and the RUNE pairing is bounded by a ±30% sanity band on the live DollarsPerRune.

Ships guarded

mainnetDonationSpecComplete is false, so Migrate19to20 logs and SKIPS (returns nil, applies nothing) as this MR stands — the guard test covers both states. The module version still advances to 20, so a release shipped with the flag still false would drop the migration permanently (it would then need a new 20->21 migration). The amounts above are pinned from a state snapshot; they must be re-pinned at the release cut and the flag flipped to true then.

Pinned decisions

  • Low-synth burn = RETIRE (not compensate). The entire in-scope synth supply of the 7 low-utilization pools is reclaimed and burned, uncompensated; the amount is bounded (live utilization ≤1% AND a per-pool pinned supply ceiling), currently ~$7.9k, mostly ETH.WBTC synth. Pools that drift beyond either bound are skipped for a re-pin.
  • ETH.THOR restore price band = 10% (WIDE). The live pre-credit pool THOR/USD price is bounded ±10% of the pinned reference (two-sided); wider than the 1% capital tripwires so a normal THOR move between the re-pin and the upgrade does not skip the whole restore. ethThorPinnedUsdTor must be re-pinned to market at the cut, not left at the snapshot price.
  • Surplus guard = canonical calculateNetworkSolvency. The ETH.THOR surplus credit and the donation pairings are bounded by the live network-solvency amount (nets pool, trade/secured, queued/streaming swaps, deficits, scheduled outbounds). It refuses to run mid-churn, so the upgrade height must be scheduled off a churn boundary or the ETH.THOR restore soft-skips.
  • Slash reversal is solvency-gated too. The 0.53 BTC credited back into the BTC pool is now held to the same unaccounted-BTC check as every other credit: if the active vaults don't hold that BTC free (or mid-churn), the slash refund soft-skips — the 218 RUNE refunds only pay when the reversed BTC is actually there.
  • Launch plan: set HaltSigningTRON, HaltSigningZEC (step 5) and HaltSigningSOL (step 7) at a height ≤ the upgrade height. Steps 5/6/7 enforce the signing halt at run time, not merely document it: if the halt is unset when the upgrade block executes, the step soft-skips and its refund is dropped permanently (a 20→21 migration). The halt needn't run for weeks — it can be voted in shortly before the cut and lifted after the upgrade block. HALTSIGNINGTRON is currently 0 on mainnet (h28,226,576), so this belongs on the release checklist.

Tests

-tags mainnet: slash-refund sum, ETH.THOR happy-path / insolvency-reject / post-entrant cap, and low-synth burn all pass. Default and mocknet builds are green. The migration steps add zero new failures to the full -tags mainnet package run (the 30 failures there are pre-existing on develop — the package's normal test tag is mocknet).

Edited by Itzamna

Merge request reports

Loading
Loading