Feat/agent duels - #3
Open
dantol29 wants to merge 18 commits into
Open
Conversation
Note MockUSDC permit support: MockUSDC already extends ERC20Permit and exposes mint(address,uint256); reused as-is.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add bet(), betWithPermit(), and _bet() to DuelMarket with full parimutuel pool/stake accounting. betWithPermit uses best-effort try/catch permit to prevent front-run DoS. 5 new tests (TDD); full suite 12/12 passing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds resolve(uint256) — permissionless, nonReentrant. Snapshots navEnd, computes signed 1e18 PnL%, selects winner (0/1/2), transfers feeBps of the losing pool to feeRecipient when decisive (no fee on tie). Status set to Resolved, emits DuelResolved. 5 new tests cover A-wins, B-wins, tie-no-fee, TooEarly, WrongStatus. Full suite: 24/24 passing. No new compiler warnings. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace lint-suppressed int256 casts in resolve() with OZ SafeCast.toInt256 (reverts on genuine overflow instead of silently wrapping; no suppression comment needed). Strengthen test_resolve_tie_noFee to assert Resolved status, navEndA/B, and the DuelResolved(id, 2, ...) event. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add claim(uint256) — winner payout (stake + share of loserPool-fee), tie/void full refund, NothingToClaim for losers, AlreadyClaimed guard. 7 tests: winner-A, winner-B, loser, double-claim, void, tie, WrongStatus. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add test_claim_multipleWinnersProRata (exact floor-division payouts alice=165_333333, carol=82_666666; conservation dust=1 wei) and test_claim_voidNonParticipantReverts (non-staker reverts NothingToClaim). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Four fuzz scenarios (A wins / B wins / tie / multiple-winners) assert: - post-resolve market balance == totalPot - fee - all winner claims succeed without revert (solvency) - dust bounded by winner count (0-2 wei) - tie: zero fee, full refund, payouts sum to totalPot Reentrancy: MockReentrantUSDC fires onReceive() during safeTransfer; ReentrantClaimReceiver re-enters claim() and records the revert selector. Test asserts guard fires (ReentrancyGuardReentrantCall or AlreadyClaimed). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- multipleWinners: add explicit per-winner proportionality assertions (assertEq alice/carol payout == stake + stake*distributable/winnerPool) so the fuzz discriminates a wrong pro-rata formula. - tie: fuzz the shared end-nav in [1, 2*NAV_START] so gain/flat/loss are all exercised; both treasuries set to the same value keeps winner==2. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
F1: Add Duel.feeBpsSnapshot field set in resolve(); claim() now reads the snapshot instead of the live feeBps, ensuring the fee deducted from payouts always matches the fee already transferred out. F2: Wrap both IAgentTreasury.nav() calls in resolve() in try/catch; if either reverts, set status=Voided and emit DuelVoided so bettors can reclaim stakes via the existing void path in claim(). Add MockRevertingTreasury mock and two TDD tests (RED→GREEN). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add DeployDuelMarket.s.sol (mirrors DeployTreasuryFactory style, reads env USDC_ADDRESS/DUEL_FEE_RECIPIENT/DUEL_FEE_BPS/DUEL_OWNER) and extend dump-artifacts.mjs to include DuelMarket → web/src/lib/contracts/DuelMarket.ts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…state) Simplify per product decision: FEE_BPS is a compile-time constant (100 = 1%) and feeRecipient is immutable. Removes feeBps state, setFeeConfig, feeBpsSnapshot, MAX_FEE_BPS, FeeTooHigh, FeeConfigChanged. This ELIMINATES audit finding F1 (mutable-fee resolve/claim desync) by construction — no mutable fee state exists. Tests updated for 1% (40 pass incl. fuzz); deploy script drops DUEL_FEE_BPS. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…surface) Two pure-removal simplifications: - Drop betWithPermit: it only saved a bettor's first approve tx (every subsequent bet on an existing allowance was already one tx), which didn't justify the EIP-2612 signature verification + try/catch fallback surface. Betting is now approve + bet only. - Drop Ownable/paused/setFeeConfig: the contract is now fully immutable and permissionless post-deploy — no owner, no pause, no admin function. feeRecipient is set once in the constructor and is immutable. Constructor is now DuelMarket(usdc, feeRecipient) — no feeBps_/owner_ params. 258->225 lines, ABI 50->39 entries. 36/36 tests pass (4 permit/pause tests removed, rest unchanged). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
No description provided.