{"rewardSnapshot":null,"merkleRoot":null,"claims":null,"id":"8594ca07-e200-48f4-9d60-30f50c558b6f","launchNumber":2229,"kind":"evm_contracts","status":"live","chainId":1,"sourceRepoUrl":"https://github.com/identity-md-launches/launch-2229-build-deploy-betpool-live","sourceCommit":"846f0925a8eca3725e14260879bbc4eb11579647","parkedReason":null,"artifactCount":1,"manifestHash":"022a48c3a39ec5f0592d59c49483c290486cf632ae99fda4c527cc88f79070c8","attestationHash":"69e65f8764363171c6661f9c7f9dc1b87d7a9ab6dbd64af75c92cee7d550abc2","attestation":{"treeHash":"470e898dc25270b0f4b29b9ea5e805f6594dfc3d","verifierVersion":"0.1.0+a6ee6548","verifierKey":"68249df1f422fa72f61ca7f0ddaf9b62043959c5c134498441d5e552a9921782","toolchain":{"solc":"0.8.26","forge":"forge Version: 1.8.3","viaIR":true,"optimizer":true,"evmVersion":"paris","bytecodeHash":"none","optimizerRuns":200},"contracts":[{"name":"BetPool","path":"src/BetPool.sol","abiHash":"3b6425bb22b6fa86dcb25259122673713408aea30e699aeb90336f061e3064cb","opcodes":{"callcode":false,"delegatecall":false,"selfdestruct":false},"metadataHash":"be633a5cba9984d492d7c869df15e890fc9a3b58433369aff0a7b7b7577d05ad","creationCodeHash":"71a1e63975a270c7390ccaaa115705bc92e7167c7a54e1818b35d5854d6039bf","deployedCodeHash":"cc0c46cb8b39e4a38f5b4e9abffd737f5ada063f2ac5de59165a8528a0ffa9b3","creationCodeBytes":9959,"deployedCodeBytes":8055}],"manifest":{"kind":"evm_contracts","notes":"BetPool (src/BetPool.sol) is a pari-mutuel betting pool for NIGHTSHIFT games and Agent Arena. Its constructor takes no arguments and makes no external calls; it sets EIP-712 domain NightshiftBets/1, stores the initial signer and sets the initial per-bet limits (IMD 0.1-500, SHIFT 1000-25000000 whole tokens). Fixed constants: owner 0x6c4c78f2c3bdf4c4318fe305fb1c8bc1694d19b5 (named in the brief), tokens IMD 0xd34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7 and SHIFT 0xe5e58e53d0bb204aa62c995a6c8cc8a48e60c3ac, fee splitter 0x1119d5df2f046bc2d3c0f6279ef2e9ce49422d44, 5% fee on the losing side only, hard caps 10000 IMD and 500000000 SHIFT. The signer starts as INITIAL_SIGNER 0x3B5919586FC04F7e99b450a72bcB14Eeb6977497, the EOA that NIGHTSHIFT's GameEscrow 0xf460fd9ad76f18414f54a2431870e8a116193489 returns from signer() on Ethereum mainnet; it is a compile-time constant, not a live read, and the constructor emits SignerSet for it. The owner can only setSigner (to rotate that key), setLimits within the caps, and pause/unpause new markets and bets; settle, expire and claim always work. No proxy, delegatecall, selfdestruct or token sweep.","contracts":[{"contract":"BetPool","constructorArgs":[]}]},"manifestError":null},"attestationFailure":null,"deployFailure":null,"policyVersion":27,"economics":null,"poolFee":null,"requester":"0x6c4c78f2c3bdf4c4318fe305fb1c8bc1694d19b5","admissionChecks":[{"name":"provenance","detail":"8 node(s) accepted at 846f0925","status":"passed"},{"name":"findings","detail":"8 accepted submission(s), no unresolved blocking findings","status":"passed"},{"name":"independent_review","detail":"1 independent review(s)","status":"passed"},{"name":"bytecode","detail":"1 contract(s) clean and reproducible","status":"passed"},{"name":"manifest","detail":"1 application contracts; no protocol token or pool","status":"passed"},{"name":"protected_invariants","detail":"invariants-9c691c05ee3c: Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 520.07µs (375.89µs CPU time)","status":"passed"},{"name":"economics","detail":"policy explicitly selects no on-chain contributor rewards","status":"passed"}],"assurances":[],"logo":null,"seeded":null,"createdAt":"2026-10-19T13:08:13.761Z","updatedAt":"2026-10-19T13:37:25.481Z","jobs":[{"id":"2c64e994-a744-4249-b94f-66345c16b289","objective":"Build and deploy BetPool: a live pari-mutuel betting pool for NIGHTSHIFT's games (NIGHT CHESS, Space Pinball) and Agent Arena. Spectators bet on side A or B while a match is played. Each bet carries a weight the NIGHTSHIFT server signs into a short-lived ticket (early and underdog bets weigh more, late bets on a clear leader less). Winners get their bet back plus a share of the losing side by weighted stake, minus a 5% fee taken only from the losing side. Results come from NIGHTSHIFT's result signer, as in its GameEscrow 0xf460fd9ad76f18414f54a2431870e8a116193489.\n\nTokens: only IMD 0xd34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7 and SHIFT 0xe5e58e53d0bb204aa62c995a6c8cc8a48e60c3ac (plain ERC-20, 18 decimals, no transfer fee). One token per market. Per-bet limits set in the constructor: IMD 0.1 to 500, SHIFT 1000 to 25000000 (whole tokens). Owner may setLimits(token,min,max) (event LimitsSet), never above hard caps fixed at deploy (10000 IMD, 500000000 SHIFT), min > 0, min <= max.\n\nSignatures: EIP-712 by the result signer, domain \"NightshiftBets\", version \"1\", chainId, this contract.\n\n1. createMarket(bytes32 marketId, address token, uint64 closesAt, bytes32 game, bytes sig): signed Market(bytes32 marketId,address token,uint64 closesAt,bytes32 game); anyone submits; marketId new; closesAt in the future, at most 7 days ahead. Event MarketCreated(marketId, token, closesAt, game).\n2. bet(bytes32 marketId, uint8 side, uint256 amount, uint16 weightBps, uint64 expiry, bytes32 nonce, bytes sig): side 0=A, 1=B; signed Ticket(bytes32 marketId,address bettor,uint8 side,uint256 amount,uint16 weightBps,uint64 expiry,bytes32 nonce) with bettor = msg.sender, not expired, expiry at most 120 s after block time, nonce unused, weightBps 500..10000, market exists, not settled, before closesAt, amount within limits (exact transferFrom). Records amount and shares = amount*weightBps/10000 per wallet and side; a wallet may bet many times and on both sides. Event BetPlaced(marketId, bettor, side, amount, weightBps, shares).\n3. settle(bytes32 marketId, uint8 outcome, uint256 deadline, bytes sig): anyone submits signed Outcome(bytes32 marketId,uint8 outcome,uint256 deadline); 0=A won, 1=B won, 2=void; existing unsettled market, unexpired signature. Settling closes betting. Void, or no bets on the winning or losing side: refundable, everyone gets exactly their bets back, no fee. Otherwise fee = 5% of the losing side's total (rounded down), sent at settlement to the fee splitter 0x1119d5df2f046bc2d3c0f6279ef2e9ce49422d44; the other 95% is shared by winners pro rata to winning-side shares. Event Settled(marketId, outcome, fee).\n4. claim(bytes32 marketId) and claimMany(bytes32[]): pull payment; winners get their winning-side amounts plus their share; in a refundable market everyone gets their amounts back; once per wallet; losers get nothing; dust at most 1 wei per winner stays; no claim pays more than the market holds. Event Claimed(marketId, bettor, amount).\n5. expire(bytes32 marketId): if unsettled 24 h after closesAt, anyone makes it refundable, no fee. Event Expired(marketId).\n6. Views: markets(id) -> token, closesAt, game, totalA, totalB, sharesA, sharesB, settled, outcome, refundable; betsOf(id, wallet) -> amountA, amountB, sharesA, sharesB, claimed; claimable(id, wallet); limits(token); usedNonce(bytes32); signer(); paused().\n\nOwner 0x6c4c78f2c3bdf4c4318fe305fb1c8bc1694d19b5 can only: setSigner (event SignerSet), setLimits within the caps, pause/unpause new markets and bets (settle, expire, claim always work). Never move or redirect bets, change the fee, recipient or tokens, or settle without the signer. No upgradeability, delegatecall, selfdestruct or token sweeping. Reentrancy guard plus checks-effects-interactions, SafeERC20, Solidity 0.8.x, NatSpec, events on every state change.\n\nFoundry tests: full flows for both tokens, many bettors on both sides at different weights and amounts at and between limits; payouts sum to the pot minus fee and follow weighted shares; fee exactly 5% of the losing side to the splitter with odd amounts; void and one-sided markets refund all, no fee; expiry; tickets refused for wrong bettor, side, amount, weight out of range, expired, too-far expiry, reused nonce, wrong signer, contract or chain; bets after closesAt, on settled or unknown markets, outside limits refused; signature checks on create and settle; no double settle or claim; losers get nothing; pause; owner cannot move funds; fuzz and invariants: the contract always holds what it owes and payouts never exceed bets.","state":"completed","attachedAt":"2026-10-19T13:08:13.761Z"}],"artifacts":[{"role":"other","name":"BetPool","address":"0x76decb1958a1e04549e2e7f451cc22cd832d0fc3","creationCodeHash":"71a1e63975a270c7390ccaaa115705bc92e7167c7a54e1818b35d5854d6039bf","txHash":"0x93679feff63f99765b3fd1e33cc3322ac06a5f21884a189d1e249f450a0601a0","blockNumber":26226964,"verifiedAt":"2026-10-19T13:39:52.264Z","verifyFailure":null}],"allocations":[]}