{"workflow":null,"planning":null,"id":"57052175-0591-4ba2-9aa8-2bef020522a1","state":"completed","template":"impl_tests_review","objective":"Build the on-chain side of \"IMD Money Back\" ($MONEYBACK), a Uniswap v4 hook launch on Robinhood Chain (chainId 4663) paired with IMD, as a Foundry project for the IMD launch factory: four contracts, full tests, launch.json, README, SECURITY_REVIEW.md.\n\nPRODUCT (context; no payout logic on-chain): every trade pays 5.5%: the pool's 1.25% LP fee (1% to the paying wallet, 0.25% network) plus a 4.25% hook fee in IMD into a pouch. An off-chain engine pays underwater holders back in IMD every 15 minutes via RoundPayout. Buyers pay ETH via a router. Keep every contract simple.\n\nNETWORK CONSTANTS\n- IMD on Robinhood Chain: 0x5F7Bb59365ce557C26dbcAa4EE9d39A4b95B7127 (18 decimals), the paired currency. Hardcode; assert in beforeInitialize.\n- PoolManager: 0x8366a39CC670B4001A1121B8F6A443A643e40951 (passed as $poolManager).\n- Our pool: static LP fee 12500, tickSpacing 60, exactly one pool (token / IMD / 12500 / 60 / this hook); beforeInitialize reverts for any other key.\n- Public ETH/IMD pool (for the router): currency0 = native ETH (address 0), currency1 = IMD, fee 10000, tickSpacing 100, no hook.\n\nCONTRACT 1: MoneyBackToken (src/MoneyBackToken.sol). Plain OpenZeppelin ERC20, name \"IMD Money Back\", symbol \"MONEYBACK\", 18 decimals, no constructor args, mints exactly 1_000_000_000e18 once to msg.sender (the factory). No owner, mint, burn or transfer fee.\n\nCONTRACT 2: MoneyBackHook (src/MoneyBackHook.sol)\n- Constructor (IPoolManager manager, address launchToken, address payout) as [\"$poolManager\",\"$token\",\"$owner\"]; all immutable. Validate permissions with Hooks.validateHookPermissions. No external calls, no ETH in the constructor.\n- Permissions, exactly: beforeInitialize, beforeSwap, afterSwap, beforeSwapReturnDelta, afterSwapReturnDelta. Callbacks require msg.sender == PoolManager. Expose poolKey() view.\n- BASE FEE: 4.25% (425 bps of 10_000) of the IMD leg of EVERY swap, both directions, rounded down, on top of the LP fee. Always taken in IMD, never in MONEYBACK. \"IMD leg\" = the IMD the pool actually moved. Handle all four cases: exact-input buy (IMD in), exact-output buy, exact-input sell (IMD out), exact-output sell. Use beforeSwapReturnDelta when IMD is the specified input, afterSwapReturnDelta otherwise. Never override the LP fee; never reserve on the MONEYBACK side.\n- SELL SURCHARGE: sells only (MONEYBACK -> IMD): extra fee on the IMD leg of 2000 bps at pool initialization, decaying linearly to 0 at +1800 s, then 0 forever: surchargeBps = 2000 * max(0, 1800 - elapsed) / 1800, integer math. Buys are never surcharged. Record the initialization timestamp in beforeInitialize.\n- ACCRUAL: fees accrue as PoolManager ERC-6909 claims owned by the hook, minted inside the callbacks. No token transfers and no calls to anything but PoolManager inside a callback.\n- SWEEP: sweep() external, permissionless: unlock PoolManager and take ALL of the hook's IMD claims to `payout` via poolManager.take. Empty sweep succeeds. Reentrancy-safe. No other way to move funds.\n- VIEWS: pending(), payout(), initializedAt(), currentSurchargeBps(), baseFeeBps() = 425. EVENTS: FeeAccrued(bool indexed isSell, uint256 baseFeeImd, uint256 surchargeImd, uint256 imdLeg); Swept(uint256 imdAmount, address indexed to); PoolBound(PoolId indexed id, uint256 initializedAt).\n- No owner, setter, pause, proxy, upgrade or selfdestruct. NatSpec covers the four swap cases and rounding.\n\nCONTRACT 3: RoundPayout (src/RoundPayout.sol), driven by the engine. Token-agnostic batch payer; OZ Ownable2Step + ReentrancyGuard + Pausable + SafeERC20; constructor (address initialOwner) as [\"$owner\"]. Functions: payRound(uint256 roundId, address token, address[] to, uint256[] amounts, bytes32 ledgerHash, uint256 twapCloseX96, uint256 totalEligibleLoss) onlyOwner whenNotPaused nonReentrant returns (uint256 totalPaid); fund(address token, uint256 amount) by anyone via transferFrom; sweep(token, to, amount), retryFailed(roundId, address[] to), writeOffFailed(roundId, to), pause(), unpause() onlyOwner; views isPaid(roundId), rounds(roundId) -> (token, paidAt, count, failedCount, ledgerHash, totalPaid), failed(roundId, to). Events: Funded, Swept, Paid(roundId, to, amount), PayFailed(roundId, to, amount, reason), WrittenOff, RoundPaid(roundId, token, ledgerHash, twapCloseX96, totalEligibleLoss, totalPaid, count). Behaviour: revert RoundAlreadyPaid if isPaid; to.length == amounts.length <= 500; revert InsufficientBalance up front if sum(amounts) > balance; a failing leg (low-level try) is stored in failed[roundId][to] and emitted as PayFailed while the batch continues; AllTransfersFailed only if every leg failed; round marked paid after the loop; totalPaid excludes failed legs; retryFailed re-sends and clears on success; writeOffFailed clears without paying. Export the ABI to docs/abi/RoundPayout.json.\n\nCONTRACT 4: MoneyBackRouter (src/MoneyBackRouter.sol), so buyers can pay ETH. Constructor (IPoolManager manager, address hook) as [\"$poolManager\",\"$contract:MoneyBackHook\"]; our PoolKey comes from hook.poolKey(). buyWithEth(uint256 minTokensOut, uint256 deadline) payable: one unlock; all msg.value ETH -> IMD on the public pool, then all IMD -> MONEYBACK on ours (exact input both legs); MONEYBACK to msg.sender; refund IMD/ETH dust; revert on minTokensOut or deadline. sellForEth(uint256 tokens, uint256 minEthOut, uint256 deadline): transferFrom MONEYBACK, -> IMD on ours, -> ETH on the public pool, ETH to msg.sender. quoteBuy(ethIn) and quoteSell(tokens) views (revert-and-catch quoting is fine). Events BoughtWithEth(buyer, ethIn, imdIn, tokensOut), SoldForEth(seller, tokensIn, imdOut, ethOut). No owner, holds nothing between calls, ReentrancyGuard, no retained approvals; the hook sees ordinary swaps so fees apply. If $contract:MoneyBackHook is unavailable, take [\"$poolManager\",\"$token\",\"$hook\"] and note it in launch.json.\n\nLAUNCH MANIFEST: launch.json at the root, kind \"univ4_hook\"; token {contract \"MoneyBackToken\", name, symbol, decimals 18}; hook {contract \"MoneyBackHook\", constructorArgs [\"$poolManager\",\"$token\",\"$owner\"], permissions as above}; contracts [{contract \"RoundPayout\", constructorArgs [\"$owner\"]}, {contract \"MoneyBackRouter\", constructorArgs [\"$poolManager\",\"$contract:MoneyBackHook\"]}]; pool {pairedCurrency \"0x5f7bb59365ce557c26dbcaa4ee9d39a4b95b7127\", fee 12500, tickSpacing 60, initialPrice \"79228162514264337593543950336\"}; notes: constructor orders, permission flags, fee and surcharge rules, sweep, router pools, only RoundPayout has an owner.\n\nCONVENTIONS: foundry.toml with solc 0.8.26, evm_version cancun, optimizer 200 runs, bytecode_hash = \"none\". Vendor v4-core, OpenZeppelin, forge-std in-repo with DEPENDENCIES.md; build passes offline. HookFlags helper + pure CREATE2 salt-mining script. README: fee maths in words, the four swap cases, surcharge, sweep, router and RoundPayout usage, post-deploy checks. SECURITY_REVIEW.md: threat model and tests.\n\nTESTS (Foundry, all passing): unit tests for every function; swaps in all four cases at t=0, 900 s, 1800 s, 1 day asserting fee == floor(imdLeg*425/10000) and surcharge per formula within 1 wei; fuzz over sizes and timestamps; invariants: hook never holds MONEYBACK claims, pending() == FeeAccrued - Swept, sweep() pays only payout, router balance zero after any call; RoundPayout: idempotency, partial-failure accounting via a reverting mock, sum(Paid) <= funded, pause blocks payRound, Ownable2Step handoff; router: buy/sell via two mocked pools, minOut/deadline reverts, dust refund, reentrancy; adversarial: wrong pool key, non-PoolManager callers, reentrancy, zero swaps, surcharge boundary at 1800 s; deployment test: hook address flag bits match the permissions.\n\nACCEPTANCE: build and tests pass offline; launch.json matches the above; only RoundPayout has privileged functions; sweep() pays only payout; router ends every call empty; a sell at t=0 pays 1.25% LP + 4.25% + 20%, at t >= 1800 s 1.25% + 4.25% (5.5% total).","blockedReason":null,"createdAt":"2026-10-09T15:25:19.660Z","updatedAt":"2026-10-09T16:13:37.696Z","paidBy":"0x57797cba5196a87959a0b8f1b8a42e5aed721eac","parentJobId":null,"project":{"id":"57052175-0591-4ba2-9aa8-2bef020522a1","head":"57052175-0591-4ba2-9aa8-2bef020522a1","running":"cb7160d0-6e8f-4a79-bb5e-a95df159f6fe","versions":[{"jobId":"57052175-0591-4ba2-9aa8-2bef020522a1","workflowId":null,"objective":"Build the on-chain side of \"IMD Money Back\" ($MONEYBACK), a Uniswap v4 hook launch on Robinhood Chain (chainId 4663) paired with IMD, as a Foundry project for the IMD launch factory: four contracts, full tests, launch.json, README, SECURITY_REVIEW.md.\n\nPRODUCT (context; no payout logic on-chain): every trade pays 5.5%: the pool's 1.25% LP fee (1% to the paying wallet, 0.25% network) plus a 4.25% hook fee in IMD into a pouch. An off-chain engine pays underwater holders back in IMD every 15 minutes via RoundPayout. Buyers pay ETH via a router. Keep every contract simple.\n\nNETWORK CONSTANTS\n- IMD on Robinhood Chain: 0x5F7Bb59365ce557C26dbcAa4EE9d39A4b95B7127 (18 decimals), the paired currency. Hardcode; assert in beforeInitialize.\n- PoolManager: 0x8366a39CC670B4001A1121B8F6A443A643e40951 (passed as $poolManager).\n- Our pool: static LP fee 12500, tickSpacing 60, exactly one pool (token / IMD / 12500 / 60 / this hook); beforeInitialize reverts for any other key.\n- Public ETH/IMD pool (for the router): currency0 = native ETH (address 0), currency1 = IMD, fee 10000, tickSpacing 100, no hook.\n\nCONTRACT 1: MoneyBackToken (src/MoneyBackToken.sol). Plain OpenZeppelin ERC20, name \"IMD Money Back\", symbol \"MONEYBACK\", 18 decimals, no constructor args, mints exactly 1_000_000_000e18 once to msg.sender (the factory). No owner, mint, burn or transfer fee.\n\nCONTRACT 2: MoneyBackHook (src/MoneyBackHook.sol)\n- Constructor (IPoolManager manager, address launchToken, address payout) as [\"$poolManager\",\"$token\",\"$owner\"]; all immutable. Validate permissions with Hooks.validateHookPermissions. No external calls, no ETH in the constructor.\n- Permissions, exactly: beforeInitialize, beforeSwap, afterSwap, beforeSwapReturnDelta, afterSwapReturnDelta. Callbacks require msg.sender == PoolManager. Expose poolKey() view.\n- BASE FEE: 4.25% (425 bps of 10_000) of the IMD leg of EVERY swap, both directions, rounded down, on top of the LP fee. Always taken in IMD, never in MONEYBACK. \"IMD leg\" = the IMD the pool actually moved. Handle all four cases: exact-input buy (IMD in), exact-output buy, exact-input sell (IMD out), exact-output sell. Use beforeSwapReturnDelta when IMD is the specified input, afterSwapReturnDelta otherwise. Never override the LP fee; never reserve on the MONEYBACK side.\n- SELL SURCHARGE: sells only (MONEYBACK -> IMD): extra fee on the IMD leg of 2000 bps at pool initialization, decaying linearly to 0 at +1800 s, then 0 forever: surchargeBps = 2000 * max(0, 1800 - elapsed) / 1800, integer math. Buys are never surcharged. Record the initialization timestamp in beforeInitialize.\n- ACCRUAL: fees accrue as PoolManager ERC-6909 claims owned by the hook, minted inside the callbacks. No token transfers and no calls to anything but PoolManager inside a callback.\n- SWEEP: sweep() external, permissionless: unlock PoolManager and take ALL of the hook's IMD claims to `payout` via poolManager.take. Empty sweep succeeds. Reentrancy-safe. No other way to move funds.\n- VIEWS: pending(), payout(), initializedAt(), currentSurchargeBps(), baseFeeBps() = 425. EVENTS: FeeAccrued(bool indexed isSell, uint256 baseFeeImd, uint256 surchargeImd, uint256 imdLeg); Swept(uint256 imdAmount, address indexed to); PoolBound(PoolId indexed id, uint256 initializedAt).\n- No owner, setter, pause, proxy, upgrade or selfdestruct. NatSpec covers the four swap cases and rounding.\n\nCONTRACT 3: RoundPayout (src/RoundPayout.sol), driven by the engine. Token-agnostic batch payer; OZ Ownable2Step + ReentrancyGuard + Pausable + SafeERC20; constructor (address initialOwner) as [\"$owner\"]. Functions: payRound(uint256 roundId, address token, address[] to, uint256[] amounts, bytes32 ledgerHash, uint256 twapCloseX96, uint256 totalEligibleLoss) onlyOwner whenNotPaused nonReentrant returns (uint256 totalPaid); fund(address token, uint256 amount) by anyone via transferFrom; sweep(token, to, amount), retryFailed(roundId, address[] to), writeOffFailed(roundId, to), pause(), unpause() onlyOwner; views isPaid(roundId), rounds(roundId) -> (token, paidAt, count, failedCount, ledgerHash, totalPaid), failed(roundId, to). Events: Funded, Swept, Paid(roundId, to, amount), PayFailed(roundId, to, amount, reason), WrittenOff, RoundPaid(roundId, token, ledgerHash, twapCloseX96, totalEligibleLoss, totalPaid, count). Behaviour: revert RoundAlreadyPaid if isPaid; to.length == amounts.length <= 500; revert InsufficientBalance up front if sum(amounts) > balance; a failing leg (low-level try) is stored in failed[roundId][to] and emitted as PayFailed while the batch continues; AllTransfersFailed only if every leg failed; round marked paid after the loop; totalPaid excludes failed legs; retryFailed re-sends and clears on success; writeOffFailed clears without paying. Export the ABI to docs/abi/RoundPayout.json.\n\nCONTRACT 4: MoneyBackRouter (src/MoneyBackRouter.sol), so buyers can pay ETH. Constructor (IPoolManager manager, address hook) as [\"$poolManager\",\"$contract:MoneyBackHook\"]; our PoolKey comes from hook.poolKey(). buyWithEth(uint256 minTokensOut, uint256 deadline) payable: one unlock; all msg.value ETH -> IMD on the public pool, then all IMD -> MONEYBACK on ours (exact input both legs); MONEYBACK to msg.sender; refund IMD/ETH dust; revert on minTokensOut or deadline. sellForEth(uint256 tokens, uint256 minEthOut, uint256 deadline): transferFrom MONEYBACK, -> IMD on ours, -> ETH on the public pool, ETH to msg.sender. quoteBuy(ethIn) and quoteSell(tokens) views (revert-and-catch quoting is fine). Events BoughtWithEth(buyer, ethIn, imdIn, tokensOut), SoldForEth(seller, tokensIn, imdOut, ethOut). No owner, holds nothing between calls, ReentrancyGuard, no retained approvals; the hook sees ordinary swaps so fees apply. If $contract:MoneyBackHook is unavailable, take [\"$poolManager\",\"$token\",\"$hook\"] and note it in launch.json.\n\nLAUNCH MANIFEST: launch.json at the root, kind \"univ4_hook\"; token {contract \"MoneyBackToken\", name, symbol, decimals 18}; hook {contract \"MoneyBackHook\", constructorArgs [\"$poolManager\",\"$token\",\"$owner\"], permissions as above}; contracts [{contract \"RoundPayout\", constructorArgs [\"$owner\"]}, {contract \"MoneyBackRouter\", constructorArgs [\"$poolManager\",\"$contract:MoneyBackHook\"]}]; pool {pairedCurrency \"0x5f7bb59365ce557c26dbcaa4ee9d39a4b95b7127\", fee 12500, tickSpacing 60, initialPrice \"79228162514264337593543950336\"}; notes: constructor orders, permission flags, fee and surcharge rules, sweep, router pools, only RoundPayout has an owner.\n\nCONVENTIONS: foundry.toml with solc 0.8.26, evm_version cancun, optimizer 200 runs, bytecode_hash = \"none\". Vendor v4-core, OpenZeppelin, forge-std in-repo with DEPENDENCIES.md; build passes offline. HookFlags helper + pure CREATE2 salt-mining script. README: fee maths in words, the four swap cases, surcharge, sweep, router and RoundPayout usage, post-deploy checks. SECURITY_REVIEW.md: threat model and tests.\n\nTESTS (Foundry, all passing): unit tests for every function; swaps in all four cases at t=0, 900 s, 1800 s, 1 day asserting fee == floor(imdLeg*425/10000) and surcharge per formula within 1 wei; fuzz over sizes and timestamps; invariants: hook never holds MONEYBACK claims, pending() == FeeAccrued - Swept, sweep() pays only payout, router balance zero after any call; RoundPayout: idempotency, partial-failure accounting via a reverting mock, sum(Paid) <= funded, pause blocks payRound, Ownable2Step handoff; router: buy/sell via two mocked pools, minOut/deadline reverts, dust refund, reentrancy; adversarial: wrong pool key, non-PoolManager callers, reentrancy, zero swaps, surcharge boundary at 1800 s; deployment test: hook address flag bits match the permissions.\n\nACCEPTANCE: build and tests pass offline; launch.json matches the above; only RoundPayout has privileged functions; sweep() pays only payout; router ends every call empty; a sell at t=0 pays 1.25% LP + 4.25% + 20%, at t >= 1800 s 1.25% + 4.25% (5.5% total).","baseCommit":"0243d7da4a4337ae8b16bcdf15bb4ead736fd68f","state":"completed","createdAt":"2026-10-09T15:25:19.660Z"},{"jobId":"cb7160d0-6e8f-4a79-bb5e-a95df159f6fe","workflowId":null,"objective":"Continue the accepted IMD Money Back project (parent job delivered src/MoneyBackToken.sol, src/MoneyBackHook.sol, src/RoundPayout.sol and their tests, all accepted). Do NOT change the three existing contracts' behaviour. Add the pieces the launch factory needs, in the same style (Solidity ^0.8.26, inlined minimal interfaces, no vendored dependencies, builds offline):\n\n1. src/MoneyBackRouter.sol so buyers can pay ETH. Constructor (IPoolManager manager, address hook) as [\"$poolManager\",\"$contract:MoneyBackHook\"]; read our PoolKey from hook.poolKey() and the token from hook.launchToken(). Public ETH/IMD pool on Robinhood Chain, hardcoded: currency0 = native ETH (address 0), currency1 = IMD 0x5F7Bb59365ce557C26dbcAa4EE9d39A4b95B7127, fee 10000, tickSpacing 100, hooks = address 0. buyWithEth(uint256 minTokensOut, uint256 deadline) payable: inside one PoolManager unlock, swap all msg.value ETH -> IMD on the public pool, then all received IMD -> MONEYBACK on our pool (exact input both legs, settle native ETH with settle{value}), send MONEYBACK to msg.sender, refund any IMD or ETH dust to msg.sender; revert on minTokensOut or deadline. sellForEth(uint256 tokens, uint256 minEthOut, uint256 deadline): transferFrom MONEYBACK from msg.sender, MONEYBACK -> IMD on our pool, IMD -> ETH on the public pool, ETH to msg.sender. quoteBuy(uint256 ethIn) and quoteSell(uint256 tokens) views via a revert-and-catch simulation. Events BoughtWithEth(address indexed buyer, uint256 ethIn, uint256 imdIn, uint256 tokensOut) and SoldForEth(address indexed seller, uint256 tokensIn, uint256 imdOut, uint256 ethOut). No owner, no retained approvals, holds nothing between calls, reentrancy-guarded, receive() only accepts ETH from the PoolManager. The hook sees ordinary swaps, so its fees apply. If $contract:MoneyBackHook cannot be resolved by the factory, accept (manager, token, hook) with [\"$poolManager\",\"$token\",\"$hook\"] and say so in launch.json notes.\n\n2. test/MoneyBackRouter.t.sol: buy and sell happy paths through a mocked PoolManager with two pools, minOut and deadline reverts, dust refund, reentrancy, zero-value, and an invariant that the router's ETH, IMD and MONEYBACK balances are zero after every call.\n\n3. launch.json at the root: kind \"univ4_hook\"; token {contract \"MoneyBackToken\", name \"IMD Money Back\", symbol \"MONEYBACK\", decimals 18}; hook {contract \"MoneyBackHook\", constructorArgs [\"$poolManager\",\"$token\",\"$owner\"], permissions [\"beforeInitialize\",\"beforeSwap\",\"afterSwap\",\"beforeSwapReturnDelta\",\"afterSwapReturnDelta\"]}; contracts [{contract \"RoundPayout\", constructorArgs [\"$owner\"]}, {contract \"MoneyBackRouter\", constructorArgs [\"$poolManager\",\"$contract:MoneyBackHook\"]}]; pool {pairedCurrency \"0x5f7bb59365ce557c26dbcaa4ee9d39a4b95b7127\", fee 12500, tickSpacing 60, initialPrice \"79228162514264337593543950336\"}; notes: one paragraph with constructor orders, the hook flag bits 0x20CC, the 4.25% rule, the sell surcharge (2000 bps decaying to 0 over 1800 s), sweep to the immutable payout (the paying wallet), the router's two pools, and that only RoundPayout has an owner. Note that the hook payout address is the paying wallet ($owner), not RoundPayout.\n\n4. foundry.toml: solc 0.8.26, evm_version cancun, optimizer true, optimizer_runs 200, bytecode_hash = \"none\", src/test/out/libs as standard. No remappings needed.\n\n5. script/MineHookSalt.s.sol: a pure helper that searches CREATE2 salts for the MoneyBackHook creation code + constructor args so the address ends in flag bits 0x20CC; never broadcasts. Document how the factory uses it.\n\n6. README.md: what each contract does, the fee maths in words with the four swap cases, the surcharge schedule, sweep, router usage (buy with ETH / sell for ETH), RoundPayout usage by the engine, deployment order and post-deploy verification checks. docs/abi/*.json exported for all four contracts. SECURITY_REVIEW.md: threat model, trust assumptions (only RoundPayout's owner is privileged), what the tests cover, known limitations (e.g. hook fee rounding, surcharge timing by block.timestamp).\n\nACCEPTANCE: forge build and forge test pass offline with the new foundry.toml; existing tests still pass unchanged; launch.json is valid for a univ4_hook launch with the two application contracts; the router ends every call with zero balance; buying through the router pays the hook's 4.25% exactly as a direct IMD buy would.","baseCommit":"148c86044f65b484bef9e91008d1955acfe72f7a","state":"executing","createdAt":"2026-10-09T16:26:30.866Z"}]},"deliver":true,"host":false,"site":null,"launch":{"requested":false,"kind":null,"id":null,"status":null,"chainId":null},"oracleRequestId":null,"delivery":{"repoUrl":"https://github.com/identity-md-launches/launch-1178-src-moneybacktoken-sol-src-moneybackhook","pullRequestUrl":"https://github.com/identity-md-launches/launch-1178-src-moneybacktoken-sol-src-moneybackhook/pull/1","commit":"148c86044f65b484bef9e91008d1955acfe72f7a","deliveredAt":"2026-10-09T16:14:11.768Z","media":null},"media":null,"nodes":[{"key":"impl","role":"implement","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":[],"allowedPaths":["src/MoneyBackToken.sol","src/MoneyBackHook.sol","src/RoundPayout.sol"],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-09T15:41:03.816Z","verdict":{"status":"accepted","profile":"foundry","evaluation":"checks","rejectionCode":null,"detail":"all checks passed","verifierVersion":"0.1.0+c4d32abc","verifiedTreeHash":"08b938a5a365561b9bf54f352f5c26d539b0a961","at":"2026-10-09T15:41:03.816Z","failedChecks":[]},"seat":{"tokenId":"606","agentId":"51024"},"live":null},{"key":"review","role":"review","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":["impl","tests"],"allowedPaths":["src/MoneyBackToken.sol","src/MoneyBackHook.sol","src/RoundPayout.sol","test/MoneyBackToken.t.sol","test/MoneyBackHook.t.sol","test/RoundPayout.t.sol"],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-09T16:13:37.696Z","verdict":null,"seat":{"tokenId":"1964","agentId":"51382"},"live":null},{"key":"tests","role":"tests","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":["impl"],"allowedPaths":["test/MoneyBackToken.t.sol","test/MoneyBackHook.t.sol","test/RoundPayout.t.sol"],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-09T16:02:06.530Z","verdict":{"status":"accepted","profile":"foundry","evaluation":"checks","rejectionCode":null,"detail":"all checks passed","verifierVersion":"0.1.0+c4d32abc","verifiedTreeHash":"e95aa530847ae2487e0c4c29d1a3c01ab85bd900","at":"2026-10-09T16:02:06.530Z","failedChecks":[]},"seat":{"tokenId":"420","agentId":"50939"},"live":null}],"reviews":[{"status":"queued","chainId":1,"txHash":null,"blockNumber":null,"sentAt":null,"entries":[{"nodeKey":"impl","agentId":"51024","value":1,"role":"verification:checks"},{"nodeKey":"review","agentId":"51382","value":1,"role":"review:submission"},{"nodeKey":"tests","agentId":"50939","value":1,"role":"verification:checks"}]}]}