Simulations: EcoStrategy audit scenarios A–E (shark vs believer modeling) #161

Closed
opened 2026-05-05 08:53:00 +00:00 by PlasticDigits · 7 comments
PlasticDigits commented 2026-05-05 08:53:00 +00:00 (Migrated from gitlab.com)

Context

Track simulation / scenario work from EcoStrategy audit (audits/audit_ecostrategy_1777969776.md): validate shark-vs-shark vs early believers.

Scenarios

A — Early believers vs late no-referral sharks (no WarBow for early cohort).

B — Controlled referral cluster + optional presale beneficiary (+15% CHARM).

C — WarBow predator swarm vs early BP leader (steals, UTC rollover, guard, revenge, bypass).

D — Final-window MEV + flag ordering (same-block races).

E — Rabbit + launch anchor settlement + FeeRouter vs receiveFee (links H-01 / vault).

Deliverables

  • Extend simulations/timecurve_sim/ or add simulations/ecostrategy/ with strategy agents; full WarBow PvP (not toy steal in monte carlo).
  • Reproducible command + summary report (JSON or markdown).

Acceptance criteria

  • Scenarios A–C reproducible via documented command.
  • Explicit list of onchain constants mirrored vs approximated.

References

  • simulations/README.md, simulations/timecurve_sim/model.py, monte_carlo.py
## Context Track **simulation / scenario** work from EcoStrategy audit (`audits/audit_ecostrategy_1777969776.md`): validate shark-vs-shark vs early believers. ## Scenarios **A** — Early believers vs late no-referral sharks (no WarBow for early cohort). **B** — Controlled referral cluster + optional presale beneficiary (+15% CHARM). **C** — WarBow predator swarm vs early BP leader (steals, UTC rollover, guard, revenge, bypass). **D** — Final-window MEV + flag ordering (same-block races). **E** — Rabbit + launch anchor settlement + FeeRouter vs `receiveFee` (links H-01 / vault). ## Deliverables - Extend `simulations/timecurve_sim/` or add `simulations/ecostrategy/` with strategy agents; full WarBow PvP (not toy steal in monte carlo). - Reproducible command + summary report (JSON or markdown). ## Acceptance criteria - Scenarios A–C reproducible via documented command. - Explicit list of onchain constants mirrored vs approximated. ## References - `simulations/README.md`, `simulations/timecurve_sim/model.py`, `monte_carlo.py`
PlasticDigits commented 2026-05-05 09:10:38 +00:00 (Migrated from gitlab.com)

mentioned in commit 1b7371ae78

mentioned in commit 1b7371ae78c8038d3ffd9e49eca660cb76f07f0e
PlasticDigits commented 2026-05-05 09:11:59 +00:00 (Migrated from gitlab.com)

Implemented (main @ 1b7371a)

EcoStrategy GitLab #161 deliverable: simulations/ecostrategy/ with reproducible scenarios A–C, WarBowWorld aligned to `TimeCurve` warbowSteal / warbowRevenge / warbowActivateGuard (2× rule, 10%/1% drains with guard, UTC-day steal caps, 24h per-(victim,stealer) revenge window). Monte Carlo toy `pvp_steal_prob` remains documented as non-authoritative; see `INV-SIM-161` in `docs/testing/invariants-and-business-logic.md`.

  • `docs/testing/invariants-and-business-logic.md` — EcoStrategy section + test map
  • `simulations/README.md` — CLI commands
  • `skills/README.md` — EcoStrategy scenarios (modeling entry) for third-party agents
  • `docs/testing/strategy.md` — Stage 1 simulations mention

cc @brouie — please sanity-check the modeling assumptions vs your EcoStrategy audit expectations.

Verification checklist

  1. `cd simulations && PYTHONPATH=. python3 -m unittest discover -s tests -v` — includes `test_ecostrategy.py`.
  2. `PYTHONPATH=. python3 -m ecostrategy --scenario all --seed 42 --out output/ecostrategy_report.json` — JSON lists mirrored_from_contract vs approximations.
  3. Spot-check scenario A (`warbow_steals` > 0 after shark phase), B (`gini_charm_weight` reflects 1.25× cluster stack), C (`warbow_steals` / optional `warbow_revenges`).
  4. Confirm `ecostrategy/constants.py` mirrors `TimeCurve` WarBow BPS / caps you care about for audit narrative.

Issue left open per maintainer workflow — scenarios D/E (MEV ordering, FeeRouter→Rabbit booking) remain future work.

## Implemented (main @ 1b7371a) EcoStrategy **GitLab #161** deliverable: **`simulations/ecostrategy/`** with reproducible scenarios **A–C**, **`WarBowWorld`** aligned to \`TimeCurve\` **warbowSteal / warbowRevenge / warbowActivateGuard** (2× rule, 10%/1% drains with guard, UTC-day steal caps, 24h per-(victim,stealer) revenge window). Monte Carlo **toy** \`pvp_steal_prob\` remains documented as non-authoritative; see **\`INV-SIM-161\`** in \`docs/testing/invariants-and-business-logic.md\`. ### Docs / cross-links - \`docs/testing/invariants-and-business-logic.md\` — EcoStrategy section + test map - \`simulations/README.md\` — CLI commands - \`skills/README.md\` — **EcoStrategy scenarios (modeling entry)** for third-party agents - \`docs/testing/strategy.md\` — Stage 1 simulations mention cc @brouie — please sanity-check the modeling assumptions vs your EcoStrategy audit expectations. ### Verification checklist 1. \`cd simulations && PYTHONPATH=. python3 -m unittest discover -s tests -v\` — includes \`test_ecostrategy.py\`. 2. \`PYTHONPATH=. python3 -m ecostrategy --scenario all --seed 42 --out output/ecostrategy_report.json\` — JSON lists **mirrored_from_contract** vs **approximations**. 3. Spot-check **scenario A** (\`warbow_steals\` > 0 after shark phase), **B** (\`gini_charm_weight\` reflects 1.25× cluster stack), **C** (\`warbow_steals\` / optional \`warbow_revenges\`). 4. Confirm \`ecostrategy/constants.py\` mirrors \`TimeCurve\` WarBow BPS / caps you care about for audit narrative. Issue left **open** per maintainer workflow — scenarios **D/E** (MEV ordering, FeeRouter→Rabbit booking) remain future work.
Brouie commented 2026-05-06 03:29:38 +00:00 (Migrated from gitlab.com)

@PlasticDigits — verification on `390f9be` (D + E shipped). picking this up since the original 5/05 checklist only covered A–C.

ran the full unittest suite — 34/34 pass in 0.42s. five new tests landing for the D + E surface (`fee_router_five_shares` sum invariant, BPS weight validation, scenario D ordering metrics, scenario E receiveFee Burrow coverage delta, scenario C `warbow_flags_planted` assertion).

ran `PYTHONPATH=. python3 -m ecostrategy --scenario all --seed 42 --out output/ecostrategy_report.json`. all 5 scenarios complete. report has `mirrored_from_contract` (11 entries) and `approximations` (7 entries) — transparency table populated.

scenario D — paired buy-first vs pvp-first branches in a 3600s final window, same seed/pop/horizon. produced different BP leaders (idx 113 buy-first vs 210 pvp-first, `ordering_bp_leader_idx_match=0`) and the steal/revenge counts diverge sharply (`steals_abs_delta=2334`, `revenges_abs_delta=810`, flags relatively stable at `abs_delta=30`). that's the MEV ordering signal i'd expect — when buys fire first the BP economy churns through the window so steals fire freely, when pvp fires first against an early state there's nothing to steal yet.

scenario E — five-sink split sums correctly to gross (15562.59 + 20750.12 + 10375.06 + 0 + 5187.53 ≈ 51875.30 routed). Rabbit slice = 5187.53 = exactly 10% of gross, matches the canonical (3000/4000/2000/0/1000) BPS. inside the Rabbit slice: 4150.02 protocol-booked via receiveFee + 1037.51 burned, which is the 80/20 from `DEFAULT_PROTOCOL_REVENUE_BURN_SHARE_WAD = 0.2e18` in constants. the audit-relevant signal: `burrow_coverage_delta_receive_minus_direct = 0.0022` (positive) — receiveFee booking does cover Burrow incrementally over the direct-sink baseline. that's the H-01 narrative.

cross-checked the canonical five-sink weights — `FEE_SINK_WEIGHTS_BPS_DEFAULT = (3000, 4000, 2000, 0, 1000)` in `ecostrategy/constants.py` matches the contract test fixtures verbatim (`FeeRouter.t.sol:32`, `:99`, `:107`, `AccessControlZeroAdmin.t.sol:44`, `FeeRouterInvariant.t.sol:61`). launch anchor 1275/1000 in constants matches `f76454c` from #158. burn share 0.2 WAD matches the docstring.

A–C numbers stayed sane post-refactor: A 30 steals (early-believer cohort no-WarBow context), B 0 steals (no PvP phase, highest gini 0.387 from the 1.25× cluster stack), C 2354 steals. D buy-first 2356 lines up tightly with C — same WarBow engine on both code paths, sanity check passed.

two notes worth flagging — neither blockers:

  • `fee_router_five_shares` uses python float division for the first 4 sinks; on-chain Solidity uses integer floor in `FeeMath.bpsShare`. the helper docstring acknowledges "scenario-only" so this is by design, just want it on the record.
  • `DEFAULT_PROTOCOL_REVENUE_BURN_SHARE_WAD` is marked "illustrative only" in the constants comment — the absolute Burrow coverage delta will scale with whatever WAD ships at ops time. flagging in case the audit narrative wants the deployed value pinned in the report.

D + E look good. ready for close on your side once you're happy.

@PlasticDigits — verification on \`390f9be\` (D + E shipped). picking this up since the original 5/05 checklist only covered A–C. ran the full unittest suite — 34/34 pass in 0.42s. five new tests landing for the D + E surface (\`fee_router_five_shares\` sum invariant, BPS weight validation, scenario D ordering metrics, scenario E receiveFee Burrow coverage delta, scenario C \`warbow_flags_planted\` assertion). ran \`PYTHONPATH=. python3 -m ecostrategy --scenario all --seed 42 --out output/ecostrategy_report.json\`. all 5 scenarios complete. report has \`mirrored_from_contract\` (11 entries) and \`approximations\` (7 entries) — transparency table populated. scenario D — paired buy-first vs pvp-first branches in a 3600s final window, same seed/pop/horizon. produced different BP leaders (idx 113 buy-first vs 210 pvp-first, \`ordering_bp_leader_idx_match=0\`) and the steal/revenge counts diverge sharply (\`steals_abs_delta=2334\`, \`revenges_abs_delta=810\`, flags relatively stable at \`abs_delta=30\`). that's the MEV ordering signal i'd expect — when buys fire first the BP economy churns through the window so steals fire freely, when pvp fires first against an early state there's nothing to steal yet. scenario E — five-sink split sums correctly to gross (15562.59 + 20750.12 + 10375.06 + 0 + 5187.53 ≈ 51875.30 routed). Rabbit slice = 5187.53 = exactly 10% of gross, matches the canonical (3000/4000/2000/0/1000) BPS. inside the Rabbit slice: 4150.02 protocol-booked via receiveFee + 1037.51 burned, which is the 80/20 from \`DEFAULT_PROTOCOL_REVENUE_BURN_SHARE_WAD = 0.2e18\` in constants. the audit-relevant signal: \`burrow_coverage_delta_receive_minus_direct = 0.0022\` (positive) — receiveFee booking does cover Burrow incrementally over the direct-sink baseline. that's the H-01 narrative. cross-checked the canonical five-sink weights — \`FEE_SINK_WEIGHTS_BPS_DEFAULT = (3000, 4000, 2000, 0, 1000)\` in \`ecostrategy/constants.py\` matches the contract test fixtures verbatim (\`FeeRouter.t.sol:32\`, \`:99\`, \`:107\`, \`AccessControlZeroAdmin.t.sol:44\`, \`FeeRouterInvariant.t.sol:61\`). launch anchor 1275/1000 in constants matches \`f76454c\` from #158. burn share 0.2 WAD matches the docstring. A–C numbers stayed sane post-refactor: A 30 steals (early-believer cohort no-WarBow context), B 0 steals (no PvP phase, highest gini 0.387 from the 1.25× cluster stack), C 2354 steals. D buy-first 2356 lines up tightly with C — same WarBow engine on both code paths, sanity check passed. two notes worth flagging — neither blockers: - \`fee_router_five_shares\` uses python float division for the first 4 sinks; on-chain Solidity uses integer floor in \`FeeMath.bpsShare\`. the helper docstring acknowledges "scenario-only" so this is by design, just want it on the record. - \`DEFAULT_PROTOCOL_REVENUE_BURN_SHARE_WAD\` is marked "illustrative only" in the constants comment — the absolute Burrow coverage delta will scale with whatever WAD ships at ops time. flagging in case the audit narrative wants the deployed value pinned in the report. D + E look good. ready for close on your side once you're happy.
Brouie commented 2026-05-06 03:59:18 +00:00 (Migrated from gitlab.com)

mentioned in issue #167

mentioned in issue #167
Brouie commented 2026-05-06 05:55:11 +00:00 (Migrated from gitlab.com)

mentioned in issue #169

mentioned in issue #169
Brouie commented 2026-05-06 05:55:49 +00:00 (Migrated from gitlab.com)

@PlasticDigits — heads up, found a real issue in scenario D after a follow-up review pass that I missed in my earlier PASS on 390f9be. filed separately as #169.

tldr: after_tick is built once at scenarios.py:448 and passed to both buy_first and pvp_first runs. the closure carries mutable nonlocal leader_guarded state — after buy_first sets it to True, pvp_first cannot guard the leader at all. observable in the report I posted earlier: buy_first_warbow_guards: 1 vs pvp_first_warbow_guards: 0.

consequence on the metrics I cited as PASS evidence:

  • pvp_first runs the final window with an unguarded leader → steals apply 10% drain not 1% → pvp_first_warbow_steals and _revenges are inflated by guard-state pollution, not pure ordering effect
  • the ordering_*_abs_delta metrics still reflect a real ordering signal but with a guard-asymmetry contribution mixed in
  • ordering_bp_leader_idx_match=0 (different leaders emerged) survives as evidence of ordering-sensitive behavior, just not as cleanly attributable as I claimed

D + E remain interpretable as upper-bound ordering risk indicators, but D is not the clean A/B I described. apologies for the miss — the test suite at test_ecostrategy.py:94-99 does not assert guard parity between the two runs, which is what would have caught it. coverage gap noted in #169.

still happy with E + the A-C numbers + the FeeRouter five-sink invariants from the original PASS. just wanted to surface the D issue before close.

@PlasticDigits — heads up, found a real issue in scenario D after a follow-up review pass that I missed in my earlier PASS on `390f9be`. filed separately as #169. tldr: `after_tick` is built once at `scenarios.py:448` and passed to both buy_first and pvp_first runs. the closure carries mutable `nonlocal leader_guarded` state — after buy_first sets it to True, pvp_first cannot guard the leader at all. observable in the report I posted earlier: `buy_first_warbow_guards: 1` vs `pvp_first_warbow_guards: 0`. consequence on the metrics I cited as PASS evidence: - pvp_first runs the final window with an unguarded leader → steals apply 10% drain not 1% → `pvp_first_warbow_steals` and `_revenges` are inflated by guard-state pollution, not pure ordering effect - the `ordering_*_abs_delta` metrics still reflect a real ordering signal but with a guard-asymmetry contribution mixed in - `ordering_bp_leader_idx_match=0` (different leaders emerged) survives as evidence of ordering-sensitive behavior, just not as cleanly attributable as I claimed D + E remain interpretable as upper-bound ordering risk indicators, but D is not the clean A/B I described. apologies for the miss — the test suite at `test_ecostrategy.py:94-99` does not assert guard parity between the two runs, which is what would have caught it. coverage gap noted in #169. still happy with E + the A-C numbers + the FeeRouter five-sink invariants from the original PASS. just wanted to surface the D issue before close.
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-05-06 08:33:46 +00:00
PlasticDigits commented 2026-05-13 15:13:33 +00:00 (Migrated from gitlab.com)

mentioned in commit 13a1ccfea4

mentioned in commit 13a1ccfea46835b9945ea985e2ecfd6f2ceda681
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
code/yieldomega#161
No description provided.