feat(mm-bot): LVR AMM simulator integration#30
Open
Conversation
29 files from lvr_amm EVM contracts, Solana program, and test. PM-core contracts (DuelOutcomeOracle, GoldClob, fight_oracle, gold_clob_market) unchanged.
C-1: declare isDynamic as immutable state variable in LvrMarket C-2: add AccessControl + onlyRole(DEFAULT_ADMIN_ROLE) to setFeeConfig, 10% fee cap H-1: add minAmountOut slippage protection to all buy/sell functions H-2: add z-score bounds validation in SwapMath entry point H-3: add ReentrancyGuard (nonReentrant) to all Router buy/sell functions G-7: fix getPriceYes to use time-decayed liquidity matching _swap execution Also: market allowlist on Router callbacks, 6 exploit regression tests
Rewrites entire math.rs to use Q64.64 fixed-point (i128) arithmetic. Removes libm dependency entirely. - Polynomial erf approximation (Abramowitz & Stegun 7.1.28) - Taylor series exp(-x) with repeated squaring - Integer sqrt via Newton's method - Gaussian CDF/PDF from erf, not f64 stdlib - All public API unchanged (u64 scaled by 1e6) - 6 unit tests including symmetry and determinism verification Solana validators will now produce identical results regardless of hardware floating-point implementation.
…pplied fees (G-2, G-4, G-6) - Add AmmConfig PDA (singleton): authority, treasury, market_maker, fee_bps, config_frozen, paused - Add initialize_config, freeze_config, set_paused instructions - create_bet now reads fee_bps and treasury from AmmConfig, not caller inputs - Add pause guard on create_bet - Add error variants: InvalidAddress, FeeTooHigh, MarketPaused, ConfigFrozen - Removes per-market fee/treasury injection attack vector
Cherry-pick deploy-amm.ts and amm-test-helpers.ts from feat/amm-swap-fees, updated for hardened interfaces: - Router constructor now takes 4 params (mUSD, treasury, feeBps, admin) - Solana create_bet reads fee/treasury from AmmConfig PDA - Test helpers gain ensureAmmConfig() for protocol config setup
Thread AmmConfig PDA into Buy and Sell account contexts. Both instructions now check !amm_config.paused before executing, matching create_bet's existing pause guard and EVM Router parity.
EVM: settleFromOracle() reads DuelOutcomeOracle.getDuel() to resolve market from oracle state. Handles Resolved and Cancelled statuses. Solana: settle_bet accepts optional duel_state account from fight_oracle. Winner deserialized from oracle at known byte offsets rather than trusting caller side_won argument.
get_price now calls calc_liquidity for dynamic markets, matching the execution path in buy/sell. Prevents price read/execution divergence that could be exploited for arbitrage.
… export - Chain registry: add goldAmmMarketProgramId (Solana), goldAmmRouterAddress (EVM), amm feature flag - Solana app: wire AMM program ID into config.ts and programIds.ts with VITE env override - BSC app: wire goldAmmRouterAddress per chain into config.ts - Solana keeper: add GOLD_AMM_MARKET_PROGRAM_ID resolver - EVM: export hardened Router ABI as goldAmmRouterAbi.ts
Bump anchor-lang/anchor-spl 0.30.1→0.32.1 to match workspace, add lvr_amm to all 5 build config files (Cargo workspace, Anchor.toml, build-workspace.sh, sync-anchor-artifacts.mjs), and fix operator precedence bug in math.rs to_q function.
Full lifecycle AMM integration across Solana (lvr_amm) and EVM (Router/LvrMarket) chains, running in parallel with existing CLOB market-making. - Port Gaussian-CDF bonding curve math (Q64.64) to TypeScript bigint - Add AMM trade decision logic to mm-core (buildAmmTradeDecision) - Wire AMM runtimes (Solana + EVM) into CrossChainMarketMaker - Add AMM position storage (in-memory + postgres) - Extend simulator with SIM_MODE=clob|amm|both - Add 6 AMM adversarial scenarios (sandwich, reserve manipulation, stale price arb, slippage griefing, token drain, expiry race) - Extend chain registry with marketType and mUsdTokenAddress - Add AMM PDA helpers for lvr_amm program accounts - Generate and distribute lvr_amm IDL
Without this, AMM markets were silently dropped when the frontend filtered by marketType — the field was present on the raw candidate but not forwarded through normalizePredictionMarketLifecycleRecord().
- Use getMarketDetails() instead of individual reserve getters that don't exist on LvrMarket - Fix MarketState enum: RESOLVED is 4 not 3 (OPEN=0,CLOSED=1, PENDING=2,DISPUTED=3,RESOLVED=4) - Normalize WAD (1e18) token balances in exposure and inventory - Fix mUSD parseUnits from 6 to 18 decimals - Add lastStreamAtMs/lastOracleAtMs to AMM snapshot to prevent stale-stream circuit breaker trips - Read actual on-chain token balances after AMM trades
Standalone simulation that deploys Oracle, GoldClob, and LvrMarket contracts to a local anvil, opens a duel, and runs the market maker against both CLOB and AMM markets with real on-chain transactions. Includes nonce tracker with invalidation for mixed forge/ethers deploys and try/catch resilience for cross-market nonce conflicts.
…ntend Add SSE and HTTP endpoints that translate simulation state into the format the Vite+React betting frontend expects, so starting the sim dashboard drives the real UI (order book, fight overlay, trades). Endpoints added: - GET /api/config — contract addresses, RPC, chain info - GET /api/streaming/state/events — SSE with StreamingStateUpdate - GET /api/streaming/state — poll fallback - GET /api/streaming/duel-context — agent HP, phase, timing - GET /api/arena/prediction-markets/active — market lifecycle Also adds CORS headers and OPTIONS preflight handling on all /api/* routes for cross-origin frontend access.
Starts the simulation dashboard, waits for readiness, fetches deployed contract addresses from /api/config, writes .env.local for the EVM betting frontend, then starts the Vite dev server. Usage: ./scripts/sim-frontend.sh
JS BigInt has no overflow, so (a * b) >> 64n is exact. The old (a >> 32n) * (b >> 32n) approximation lost 32 bits per operand, producing materially different prices from the on-chain Rust math. Tightens test tolerance from ±1% to ±0.1%.
- EVM AMM: compute minAmountOut via estimateSlippage() with configurable maxSlippageBps (default 2%). All buyYes/buyNo/sellYes/sellNo now pass slippage-protected floor instead of 0. - EVM AMM: all trades + approvals routed through sendEvmTransaction() nonce tracker, preventing conflicts with concurrent CLOB transactions. - Solana AMM: read actual token balances via getTokenAccountBalance() after each trade, enabling maxPositionSize guard. Previously yesBalance/noBalance stayed at 0 forever. - Solana AMM snapshot: set lastStreamAtMs/lastOracleAtMs to Date.now() so circuit breaker doesn't treat all Solana AMM as permanently stale. - AmmMarketMakerConfig: add maxSlippageBps field (default 200 = 2%).
Add explicit CLOB_STATUS and AMM_STATUS constants with comments documenting the enum value difference (CLOB RESOLVED=3, AMM RESOLVED=4). Current sim uses GoldClob (CLOB) so runtime constants are unchanged, but the mapping is now visible for when AMM simulation is added.
C-8: Add redactUrl() utility to Solana keeper common.ts that strips api-key query parameters before logging. Prevents Helius API key exposure in error traces and diagnostics. M-12: BSC config now reads AVAX addresses from chain registry defaults (goldClobAddress, goldAmmRouterAddress, goldTokenAddress) instead of hardcoding empty strings.
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
SIM_MODE=clob|amm|bothand chain registry withmarketType+mUsdTokenAddressChanges
marketTypethrough lifecycle record normalizerAMM Fixes (local-sim debugging)
getMarketDetails()instead of non-existent individual reserve getterslastStreamAtMs/lastOracleAtMsto prevent stale-stream circuit breaker tripsGame API Endpoints Added
GET /api/configGET /api/streaming/state/eventsGET /api/streaming/stateGET /api/streaming/duel-contextGET /api/arena/prediction-markets/activeTest plan
<App>crash under investigation (pre-existing config/wagmi issue unrelated to new endpoints)