test(pm): replay test — settlement zero-sum vs known exploit classes (t16) - #153
Merged
Conversation
…(t16)
Adds tests/pm/replay/t16_settlement_exploit_classes.cpp, which LINKS the real
libraries/chain/pm/parimutuel.cpp settlement math (no chain build required — see
tests/pm/replay/README.md) and asserts the documented zero-sum identity
Σ winner_payout + oracle_take + creator_take + lp_bonus
== Σ winner.amount + losers_sum + forfeit_pool + uncovered
across adversarial-but-REACHABLE inputs mapped to known DeFi/AMM exploit classes:
A. oracle resolves to a non-participated outcome (empty winners) → whole pool to LP
B. extreme negative forfeit_pool (heavy leverage-profit residual) → clamped to 0 and
reported as `uncovered` (F1), never the uint64 wrap/mint (B3 surface)
C. dust winner weight vs a large pool → rounding remainder routes to LP, no mint/loss
D. max time_penalty → profit fully penalised to LP; payout == principal, never below
E. distribute_lp: Σ shares == bonus for skewed principal/time mixes
F. 300k-case randomized fuzz over the reachable input space
The test encodes the function's real contract: every on-chain winner has weight > 0
(pm_place_bet asserts tokens_out > 0), so the total_weight==0 branch is reached only with
an EMPTY winners vector — which the settle_market caller iterates in lockstep with
winner_bets, so there is no out-of-bounds. All checks pass, fuzz violations = 0.
Registered in tests/pm/replay/build.sh `linked` list. Built + run green with g++.
# Conflicts: # tests/pm/replay/build.sh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a replay test that links the real settlement math (
libraries/chain/pm/parimutuel.cpp) and asserts the documented zero-sum identity holds against adversarial inputs drawn from known DeFi/AMM/prediction-market exploit classes. No chain build required — it compiles justparimutuel.cpp+ an fc-uint128 shim (seetests/pm/replay/README.md), so it runs in seconds and cannot OOM.The invariant checked on every case:
LP principal is returned 1:1 by the caller and cancels;
uncovered(F1) sits on the input side as the shortfall the caller charges to LP principal — so the identity holds unconditionally and nothing is ever minted.Exploit classes probed
lp_bonus, conserved. (self-oracle abuse)forfeit_pool(heavy leverage-profit residual, tested down to −9×10¹⁵) → clamped to 0 and reported asuncovered, never the uint64 wrap/mint. (B3/F1 surface)time_penalty→ profit fully penalised to LP; payout == principal, never below.distribute_lp: Σ shares == bonus for skewed principal/time mixes.Contract note
The test encodes the function's real contract: every on-chain winner has
weight > 0(pm_place_betassertstokens_out > 0), so thetotal_weight == 0branch is reached only with an empty winners vector — whichsettle_market's caller iterates in lockstep withwinner_bets, so there is no out-of-bounds on the emptywinner_payout. (My first draft fed weight-0 "winners" and flagged false positives; characterizing this contract is what the exercise surfaced — the math itself is correct.)Verification
Built and run green with
g++:Registered in
tests/pm/replay/build.shlinkedlist. Existing linked cases (t10/t14/t15) still build + pass — no regression.