{"assessments":[],"deployments":[],"fuzz":[],"identity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"interpretation":"Records acceptance and evidence. Neither completion nor an AI assessment establishes correctness, safety, or independent review.","jobId":"866ee181-443c-44e8-9e77-f04fb7a369f9","kind":"skill:build-contract-project","nodes":[{"acceptedSubmissionHash":"16f5f1b9ff555e6fe3c577fbd8a6df374e8137fe591b335b630ec7a3d6be126a","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"6b8d2c2ebd3301cff2be8edb1e1cc6ba65c858c02fe7247be81722b969842265","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"6b8d2c2ebd3301cff2be8edb1e1cc6ba65c858c02fe7247be81722b969842265","skillId":"build-contract-project","state":"accepted"}],"objective":"Correct the existing TEST-ONLY DAEMON prototype. Continue in the same repository. Code-only work: do not deploy, launch a token, spend real funds or modify https://imdfamily.com.\n\n1. ETH HOOK FEE\nThe intended pool is DAEMON/ETH. Replace the current DAEMON-side charge with a fixed 1% charge on the ETH side of buys and sells. Forward all collected hook ETH to the NFT treasury. Update treasury support for ETH purchases. Test both token orders, swap directions, exact-input/output, rounding, settlement and forwarding. Keep hook fees separate from factory pool fees.\n\n2. ALLOCATION\nPreserve 1 billion DAEMON: 83% liquidity, 10% fixed IMD swarm, 4% game rewards, 1% development, 2% founder. Founder allocation is unlocked: no vesting or cliff. Verify that the actual factory sends the 7% remainder to the distribution receiver, which splits it 4:1:2. No extra minting, burns or pool-liquidity withdrawals.\n\n3. POOL FEES TO GAME REWARDS\nInspect the actual IMD factory fee contracts and verified source. Implement and test a supported mechanism forwarding the entire creator/payer fee share to GameRewards. Do not invent a recipient setter or assume remainderTo controls fees. Document any required payer authorization, manual forwarding or unsupported automation.\n\n4. PROTECTED TREASURIES\nRemove unrestricted token, ETH and NFT withdrawals from NFT and game-reward treasuries. Restrict purchases to allowlisted collections, marketplaces and payment assets, with spending caps, deadlines, safe approvals and verified NFT delivery. Execute purchases outside swap callbacks. Prevent administrators from bypassing restrictions through recipient or role changes.\n\nReward payouts must follow documented, season-bound allocations with duplicate-claim protection. Exclude founder NFT #222 from prizes. Define authorization for NFT prize transfers. Any emergency recovery must be narrowly scoped and documented. These restrictions must not lock the separate founder allocation.\n\n5. VERIFICATION AND DELIVERY\nAdd regression tests proving ETH reaches the NFT treasury, supported creator-fee forwarding works, allocations total 100%, unauthorized withdrawals fail and duplicate rewards are rejected.\n\nDeliver corrected source, updated ABIs, reproducible test results, security assumptions and a completed/blocked checklist. Do not claim a real agent match, final share cards or live website integration was completed by this contract task.","parentJobId":"b7c7b00e-ed24-46ec-8c25-bd13bb850109","planHash":"37a262ca1bc8daf7b328d7d03f1450b8b1d6927badc8503ec8b48d7c53ab2ab0","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"b7c7b00e-ed24-46ec-8c25-bd13bb850109","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-1456-daemon"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"51434","feedbackHash":"7c3dd91f3cdd2b4880ff665be2d0f8f75f55fec6442f087767564c31bd760c07","nodeKey":"build_contract_project","submissionHash":"16f5f1b9ff555e6fe3c577fbd8a6df374e8137fe591b335b630ec7a3d6be126a","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"007e358c650ea4be6f46ea72532cf37051ab85c48bddf38b69eb95bd7fc19758","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"b3b083c5e472c8ab30429a1243dff0657b38c7904c42ac24e4a6d8d046742348","device":"87f02002d6a2b915","findings":[],"hash":"16f5f1b9ff555e6fe3c577fbd8a6df374e8137fe591b335b630ec7a3d6be126a","nodeId":"4ea430f3-47f6-4b44-b3a7-5349a08b7fec","outcome":"completed","summary":"Implemented the ETH fee correction, verified factory routing, protected treasuries and duplicate-protected season rewards. Updated source, ABIs, tests and [handoff documentation](README.md).\n\nChecks pass: `forge build`, `forge test` (**92 passed**), and `forge fmt --check`.\n\nPayer authorization remains required for fee assignment. Single-season limitations and security assumptions are documented. Nothing was deployed; the website was unchanged.","treeHash":"0a255ace94d46c6957c9ecb93016ade5b3dee4d1","usage":{"cachedInputTokens":3964928,"inputTokens":158781,"model":"gpt-6-astra","outputTokens":47950,"runtime":"codex","turns":9,"wallClockMs":1365428}}],"verification":[{"checks":[{"durationMs":4406,"exitCode":0,"name":"build","output":"Compiling 116 files with Solc 0.8.26\nSolc 0.8.26 finished in 4.22s\nCompiler run successful!\nwarning[missing-events-access-control]: `owner` is changed without an event but is used for access control\n    ╭▸ src/DaemonHook.sol:142:9\n    │\n142 │         owner = msg.sender;\n    │         ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-events-access-control]: `owner` is changed without an event but is used for access control\n   ╭▸ src/DistributionReceiver.sol:68:9\n   │\n68 │         owner = msg.sender;\n   │         ━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-events-access-control]: `pendingOwner` is changed without an event but is used for access control\n    ╭▸ src/DaemonHook.sol:143:9\n    │\n143 │         pendingOwner = address(0);\n    │         ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-events-access-control]: `pendingOwner` is changed without an event but is used for access control\n   ╭▸ src/DistributionReceiver.sol:69:9\n   │\n69 │         pendingOwner = address(0);\n   │         ━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-events-arithmetic]: `queueHead` is changed without an event but is used in arithmetic\n    ╭▸ src/GameRewards.sol:332:30\n    │\n332 │             champion = queue[queueHead++];\n    │                              ━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-arithmetic\n\nwarning[missing-events-access-control]: `owner` is changed without an event but is used for access control\n    ╭▸ src/GameRewards.sol:176:9\n    │\n176 │         owner = msg.sender;\n    │         ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-events-access-control]: `pendingOwner` is changed without an event but is used for access control\n    ╭▸ src/GameRewards.sol:177:9\n    │\n177 │         pendingOwner = address(0);\n    │         ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-events-access-control]: `rewardAuthorizer` is changed without an event but is used for access control\n    ╭▸ src/GameRewards.sol:200:9\n    │\n200 │         rewardAuthorizer = authorizer;\n    │         ━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[solmate-safe-transfer-lib]: the `SafeTransferLib` from Solmate does not check that the token has code, so a transfer to a token-less address succeeds silently\n   ╭▸ src/DistributionReceiver.sol:98:9\n   │\n98 │         daemon.safeTransfer(gameRewards, game);\n   │         ━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/solmate-safe-transfer-lib\n\nwarning[solmate-safe-transfer-lib]: the `SafeTransferLib` from Solmate does not check that the token has code, so a transfer to a token-less address succeeds silently\n   ╭▸ src/DistributionReceiver.sol:99:9\n   │\n99 │         daemon.safeTransfer(development, dev);\n   │         ━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/solmate-safe-transfer-lib\n\nwarning[solmate-safe-transfer-lib]: the `SafeTransferLib` from Solmate does not check that the token has code, so a transfer to a token-less address succeeds silently\n    ╭▸ src/DistributionReceiver.sol:100:9\n    │\n100 │         daemon.safeTransfer(founder, found);\n    │         ━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/solmate-safe-transfer-lib\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/DaemonHook.sol:167:9\n    │\n167 │         poolManager.unlock(abi.encode(amount));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/DaemonHook.sol:177:9\n    │\n177 │         emit FeesForwarded(treasury, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/DaemonHook.sol:213:25\n    │\n213 │         if (magnitude > uint256(uint128(type(int128).max)) / 101 * 100) revert AmountTooLarge();\n    │                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/DaemonHook.sol:212:42\n    │\n212 │         uint256 magnitude = exactInput ? uint256(-params.amountSpecified) : uint256(params.amountSpecified);\n    │                                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/DaemonHook.sol:212:77\n    │\n212 │         uint256 magnitude = exactInput ? uint256(-params.amountSpecified) : uint256(params.amountSpecified);\n    │                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/DaemonHook.sol:213:25\n    │\n213 │         if (magnitude > uint256(uint128(type(int128).max)) / 101 * 100) revert AmountTooLarge();\n    │                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/DaemonHook.sol:213:33\n    │\n213 │         if (magnitude > uint256(uint128(type(int128).max)) / 101 * 100) revert AmountTooLarge();\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/DaemonHook.sol:219:63\n    │\n219 │         return (IHooks.beforeSwap.selector, toBeforeSwapDelta(int128(uint128(fee)), 0), 0);\n    │                                                               ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/DaemonHook.sol:219:70\n    │\n219 │         return (IHooks.beforeSwap.selector, toBeforeSwapDelta(int128(uint128(fee)), 0), 0);\n    │                                                                      ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[missing-events-access-control]: `owner` is changed without an event but is used for access control\n    ╭▸ src/NFTTreasury.sol:112:9\n    │\n112 │         owner = msg.sender;\n    │         ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-events-access-control]: `pendingOwner` is changed without an event but is used for access control\n    ╭▸ src/NFTTreasury.sol:113:9\n    │\n113 │         pendingOwner = address(0);\n    │         ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/DaemonHook.sol:234:46\n    │\n234 │             uint256 requested = exactInput ? uint256(-params.amountSpecified) : uint256(params.amountSpecified);\n    │                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/DaemonHook.sol:234:81\n    │\n234 │             uint256 requested = exactInput ? uint256(-params.amountSpecified) : uint256(params.amountSpecified);\n    │                                                                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/DaemonHook.sol:237:45\n    │\n237 │             int256 expected = exactInput ? -int256(requested - feeBefore) : int256(requested + feeBefore);\n    │                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/DaemonHook.sol:237:77\n    │\n237 │             int256 expected = exactInput ? -int256(requested - feeBefore) : int256(requested + feeBefore);\n    │                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/DaemonHook.sol:246:37\n    │\n246 │             unspecifiedAmount < 0 ? uint256(-int256(unspecifiedAmount)) : uint256(uint128(unspecifiedAmount));\n    │                                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/DaemonHook.sol:246:75\n    │\n246 │             unspecifiedAmount < 0 ? uint256(-int256(unspecifiedAmount)) : uint256(uint128(unspecifiedAmount));\n    │                                                                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/DaemonHook.sol:246:83\n    │\n246 │             unspecifiedAmount < 0 ? uint256(-int256(unspecifiedAmount)) : uint256(uint128(unspecifiedAmount));\n    │                                                                                   ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/DaemonHook.sol:251:44\n    │\n251 │         return (IHooks.afterSwap.selector, int128(uint128(fee)));\n    │                                            ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/DaemonHook.sol:251:51\n    │\n251 │         return (IHooks.afterSwap.selector, int128(uint128(fee)));\n    │                                                   ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/NFTTreasury.sol:154:25\n    │\n154 │     function sealPolicy(address game, IPoolManager manager) external onlyOwner unsealed {\n    │                         ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[arbitrary-send-eth]: ETH is sent to a user-controlled destination; restrict the destination or the caller\n    ╭▸ src/NFTTreasury.sol:201:9\n    │\n201 │         IMarketplace(marketplace).buy{value: asset == address(0) ? price : 0}(collection, tokenId, asset, price);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/arbitrary-send-eth\n\nwarning[reentrancy-balance]: external call can be reentered before a stale contract balance is checked\n    ╭▸ src/NFTTreasury.sol:201:9\n    │\n201 │         IMarketplace(marketplace).buy{value: asset == address(0) ? price : 0}(collection, tokenId, asset, price);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-balance\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/NFTTreasury.sol:181:13\n    │\n181 │         if (block.timestamp > deadline || deadline > block.timestamp + 1 days) revert Expired();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/NFTTreasury.sol:181:43\n    │\n181 │         if (block.timestamp > deadline || deadline > block.timestamp + 1 days) revert Expired();\n    │                                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/NFTTreasury.sol:188:13\n    │\n188 │         if (block.timestamp >= p.dayStart + 1 days) {\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/NFTTreasury.sol:212:9\n    │\n212 │         emit Purchased(marketplace, collection, tokenId, asset, charged);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[solmate-safe-transfer-lib]: the `SafeTransferLib` from Solmate does not check that the token has code, so a transfer to a token-less address succeeds silently\n    ╭▸ src/NFTTreasury.sol:198:13\n    │\n198 │             ERC20(asset).safeApprove(marketplace, 0);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/solmate-safe-transfer-lib\n\nwarning[solmate-safe-transfer-lib]: the `SafeTransferLib` from Solmate does not check that the token has code, so a transfer to a token-less address succeeds silently\n    ╭▸ src/NFTTreasury.sol:199:13\n    │\n199 │             ERC20(asset).safeApprove(marketplace, price);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/solmate-safe-transfer-lib\n\nwarning[solmate-safe-transfer-lib]: the `SafeTransferLib` from Solmate does not check that the token has code, so a transfer to a token-less address succeeds silently\n    ╭▸ src/NFTTreasury.sol:202:34\n    │\n202 │         if (asset != address(0)) ERC20(asset).safeApprove(marketplace, 0);\n    │                                  ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/solmate-safe-transfer-lib\n\nwarning[reentrancy-no-eth]: external call can be reentered before `locked` is updated\n    ╭▸ src/NFTTreasury.sol:220:9\n    │\n220 │         IERC721Minimal(collection).safeTransferFrom(address(this), recipient, tokenId);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/NFTTreasury.sol:224:9\n    │\n224 │         emit PrizeDelivered(collection, tokenId, recipient);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/GameRewards.sol:215:13\n    │\n215 │         if (start <= block.timestamp) revert SeasonInPast();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/GameRewards.sol:251:53\n    │\n251 │         (PoolKey memory key,,, address requester) = feeFactory.positionOf(feeLaunchNumber);\n    │                                                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/GameRewards.sol:261:36\n    │\n261 │         return seasonStart != 0 && block.timestamp >= seasonStart && block.timestamp < seasonStart + SEASON_LENGTH;\n    │                                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/GameRewards.sol:261:70\n    │\n261 │         return seasonStart != 0 && block.timestamp >= seasonStart && block.timestamp < seasonStart + SEASON_LENGTH;\n    │                                                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/DaemonHook.sol:259:9\n    │\n259 │         emit FeeCharged(key.toId(), zeroForOne, exactInput, fee);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/GameRewards.sol:377:13\n    │\n377 │             tokens += a.tokenAmount;\n    │             ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/GameRewards.sol:378:13\n    │\n378 │             eth += a.ethAmount;\n    │             ━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/GameRewards.sol:373:19\n    │\n373 │                 ++nfts;\n    │                   ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/GameRewards.sol:349:13\n    │\n349 │         if (block.timestamp < seasonStart + SEASON_LENGTH || block.timestamp > claimDeadline) {\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/GameRewards.sol:349:62\n    │\n349 │         if (block.timestamp < seasonStart + SEASON_LENGTH || block.timestamp > claimDeadline) {\n    │                                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/GameRewards.sol:372:21\n    │\n372 │                 if (IERC721Minimal(a.collection).ownerOf(a.prizeTokenId) != custodian) revert InvalidAllocation();\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/GameRewards.sol:361:42\n    │\n361 │             if (a.nftId == EXCLUDED_NFT) revert ExcludedFromPrizes(a.nftId);\n    │                                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/GameRewards.sol:363:63\n    │\n363 │             if (!agent.registered || agent.officialWins == 0) revert IneligibleWinner();\n    │                                                               ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/GameRewards.sol:364:63\n    │\n364 │             if (allocations[a.nftId].recipient != address(0)) revert DuplicateAllocation();\n    │                                                               ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/GameRewards.sol:365:87\n    │\n365 │             if (a.tokenAmount == 0 && a.ethAmount == 0 && a.collection == address(0)) revert InvalidAllocation();\n    │                                                                                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/GameRewards.sol:367:53\n    │\n367 │                 if (a.prizeTokenId == EXCLUDED_NFT) revert ExcludedFromPrizes(a.prizeTokenId);\n    │                                                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/GameRewards.sol:369:44\n    │\n369 │                 if (allocatedNFTs[nftKey]) revert DuplicateAllocation();\n    │                                            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/GameRewards.sol:372:88\n    │\n372 │                 if (IERC721Minimal(a.collection).ownerOf(a.prizeTokenId) != custodian) revert InvalidAllocation();\n    │                                                                                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/GameRewards.sol:375:17\n    │\n375 │                 revert InvalidAllocation();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[arbitrary-send-eth]: ETH is sent to a user-controlled destination; restrict the destination or the caller\n    ╭▸ src/GameRewards.sol:401:30\n    │\n401 │         if (a.ethAmount > 0) SafeTransferLib.safeTransferETH(a.recipient, a.ethAmount);\n    │                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/arbitrary-send-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `locked` is updated\n    ╭▸ src/GameRewards.sol:404:17\n    │\n404 │                 nftTreasury.deliverPrize(a.collection, a.prizeTokenId, a.recipient);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `locked` is updated\n    ╭▸ src/GameRewards.sol:406:17\n    │\n406 │                 IERC721Minimal(a.collection).safeTransferFrom(address(this), a.recipient, a.prizeTokenId);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/GameRewards.sol:392:13\n    │\n392 │         if (block.timestamp < seasonStart + SEASON_LENGTH || block.timestamp > claimDeadline) {\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/GameRewards.sol:392:62\n    │\n392 │         if (block.timestamp < seasonStart + SEASON_LENGTH || block.timestamp > claimDeadline) {\n    │                                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/GameRewards.sol:410:9\n    │\n410 │         emit RewardClaimed(nftId, a.recipient, a.tokenAmount, a.ethAmount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[solmate-safe-transfer-lib]: the `SafeTransferLib` from Solmate does not check that the token has code, so a transfer to a token-less address succeeds silently\n    ╭▸ src/GameRewards.sol:400:32\n    │\n400 │         if (a.tokenAmount > 0) daemon.safeTransfer(a.recipient, a.tokenAmount);\n    │                                ━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/solmate-safe-transfer-lib\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/GameRewards.t.sol:150:25\n    │\n150 │         uint256 start = block.timestamp + 1 days;\n    │                         ━━━━━━━━━━━━━━━\n    ‡\n157 │         vm.warp(start);\n    │         ────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/GameRewards.t.sol:187:25\n    │\n187 │         uint256 start = block.timestamp + 1 days;\n    │                         ━━━━━━━━━━━━━━━\n    ‡\n190 │         vm.warp(start);\n    │         ────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/GameRewards.t.sol:332:23\n    │\n332 │         uint256 end = block.timestamp;\n    │                       ━━━━━━━━━━━━━━━\n333 │         vm.warp(end - 1);\n    │         ──────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/GameRewards.t.sol:389:25\n    │\n389 │         uint256 start = block.timestamp + 1 days;\n    │                         ━━━━━━━━━━━━━━━\n    ‡\n392 │         vm.warp(start);\n    │         ────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/NFTTreasury.t.sol:56:74\n   │\n56 │         treasury.buyNFT(address(market), address(nft), id, asset, price, block.timestamp + 5 minutes);\n   │                                                                          ━━━━━━━━━━━━━━━\n   ‡\n94 │         vm.warp(block.timestamp + 1 days);\n   │         ───────────────────────────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/NFTTreasury.t.sol:94:17\n   │\n94 │         vm.warp(block.timestamp + 1 days);\n   │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/NFTTreasury.t.sol:56:74\n   │\n56 │         treasury.buyNFT(address(market), address(nft), id, asset, price, block.timestamp + 5 minutes);\n   │                                                                          ━━━━━━━━━━━━━━━\n   ‡\n96 │         vm.warp(block.timestamp + 1 days);\n   │         ───────────────────────────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/NFTTreasury.t.sol:96:17\n   │\n96 │         vm.warp(block.timestamp + 1 days);\n   │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\n","passed":true},{"durationMs":1071,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 5 tests for test/DaemonToken.t.sol:DaemonTokenTest\n[PASS] test_metadataAndSupply() (gas: 46400)\n[PASS] test_noMintOrBurnPath() (gas: 387115)\n[PASS] test_productionAllocationSumsToSupply() (gas: 9160)\n[PASS] test_runtimeHasNoDelegatecallOrSelfdestruct() (gas: 650167)\n[PASS] test_transferMovesExactAmount() (gas: 83222)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 3.05ms (2.30ms CPU time)\n\nRan 27 tests for test/GameRewards.t.sol:GameRewardsTest\n[PASS] test_NFTPrizeFromTreasuryAuthorizedOnlyByPublishedClaim() (gas: 2100573)\n[PASS] test_NFTPrizeHeldByGame() (gas: 1985685)\n[PASS] test_claimWindowAndPublicationTiming() (gas: 904498)\n[PASS] test_drawReturnsBothToQueueAndEndsStreaks() (gas: 476150)\n[PASS] test_duplicateAllocationsAndOverBudgetRevertAtomically() (gas: 1162633)\n[PASS] test_failedReceiverRollsBackEveryAssetAndCanRetryWithoutDuplicate() (gas: 3020642)\n[PASS] test_founderNFT222ExcludedEvenWithOfficialWin() (gas: 744065)\n[PASS] test_identityTransferCannotRedirectSnapshotRecipient() (gas: 1038598)\n[PASS] test_noMatchInProgress() (gas: 218572)\n[PASS] test_officialSeasonIsFourWeeksAndTestScoresAreExcluded() (gas: 996421)\n[PASS] test_oneWalletOneNft() (gas: 311660)\n[PASS] test_onlyArbiterReportsAndOnlySeatedAgents() (gas: 570596)\n[PASS] test_onlyOfficialWinnersCanReceiveAllocations() (gas: 822101)\n[PASS] test_ownerCannotPublishOrChangeRolesAndBudgets() (gas: 1006121)\n[PASS] test_ownershipChangeCannotRewriteSeasonRolesOrRecipients() (gas: 1171471)\n[PASS] test_prizeNFT222ExcludedAndNoArbitraryTransfer() (gas: 1664881)\n[PASS] test_prizesInactiveDuringTrial() (gas: 44414)\n[PASS] test_receivesCreatorETHWithoutWithdrawalPath() (gas: 40191)\n[PASS] test_registerRequiresConfiguredNft() (gas: 34994)\n[PASS] test_registerRequiresNftOwnership() (gas: 40393)\n[PASS] test_removedWithdrawalsAndArbitraryAwardFailEvenForOwner() (gas: 104979)\n[PASS] test_sameNFTCannotBeAllocatedToTwoWinners() (gas: 2053092)\n[PASS] test_seasonStartMustBeInTheFuture() (gas: 38076)\n[PASS] test_seasonTokenAndETHClaimAndDuplicateProtection() (gas: 1024430)\n[PASS] test_unsetFeeSourceAndUnauthorizedAdmin() (gas: 118600)\n[PASS] test_winnerStaysLoserLeavesNextIsSeated() (gas: 693284)\n[PASS] test_zeroAgentCannotCorruptSeatSentinel() (gas: 88781)\nSuite result: ok. 27 passed; 0 failed; 0 skipped; finished in 3.07ms (9.40ms CPU time)\n\nRan 15 tests for test/NFTTreasury.t.sol:NFTTreasuryTest\n[PASS] test_allThreeAllowlists() (gas: 151965)\n[PASS] test_buyBlockedWhilePoolManagerUnlocked() (gas: 118282)\n[PASS] test_cannotPayAgainForNFTAlreadyInCustody() (gas: 327044)\n[PASS] test_dailyAndLifetimeCapsAreIndependentByAsset() (gas: 815866)\n[PASS] test_disableAndPauseOnlyRestrict() (gas: 161342)\n[PASS] test_nativePurchase() (gas: 241225)\n[PASS] test_nativeRefundCountsActualSpend() (gas: 299762)\n[PASS] test_noSpendingBeforeSealing() (gas: 46311)\n[PASS] test_nonDeliveryRevertsETHAndTokenPayment() (gas: 469805)\n[PASS] test_overchargeRevertsBothPaymentTypes() (gas: 379933)\n[PASS] test_ownerCannotExpandPolicyOrRedirectAfterTransfer() (gas: 318091)\n[PASS] test_reentrantMarketplaceCannotSpendTwice() (gas: 957045)\n[PASS] test_removedWithdrawalsFailForOwnerAndStranger() (gas: 153825)\n[PASS] test_strangerAndDeadlineAndPerPurchaseChecks() (gas: 185805)\n[PASS] test_tokenPurchaseAndExactClearedApproval() (gas: 292938)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 3.09ms (4.56ms CPU time)\n\nRan 6 tests for test/DistributionReceiver.t.sol:DistributionReceiverTest\n[PASS] testFuzz_conservesEveryWei(uint256) (runs: 64, μ: 344875, ~: 347079)\n[PASS] test_onlyOwnerSetsRecipientsAndRejectsZero() (gas: 70306)\n[PASS] test_partialTransfersDistributeSeparately() (gas: 489710)\n[PASS] test_revertsUntilConfigured() (gas: 100632)\n[PASS] test_revertsWithNothingToDistribute() (gas: 144317)\n[PASS] test_splitsTheSevenPercentRemainder() (gas: 388387)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 6.46ms (6.36ms CPU time)\n\nRan 7 tests for test/FactoryIntegration.t.sol:FactoryIntegrationTest\n[PASS] test_actualFactoryAllocatesExactly83_10_7AndReceiver4_1_2() (gas: 366808)\n[PASS] test_assignmentIrreversibleFromGameAndOwnerCannotReplaceSource() (gas: 124011)\n[PASS] test_distributionRecipientsCannotBeChanged() (gas: 42265)\n[PASS] test_entireCreatorShareToGameAndHookETHToNFTTreasury() (gas: 1089200)\n[PASS] test_failedPayerPaymentStaysOwedToOldPayerAfterAssignment() (gas: 1206226)\n[PASS] test_oldPaidShareMustBeForwardedByPayerManually() (gas: 960661)\n[PASS] test_requiresActualPayerAuthorizationNotRemainderReceiverOrAdmin() (gas: 962337)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 6.54ms (3.59ms CPU time)\n\nRan 20 tests for test/DaemonHook.t.sol:DaemonHookTest\n[PASS] testFuzz_buyRounding(uint96) (runs: 64, μ: 231661, ~: 231515)\n[PASS] testFuzz_sellRounding(uint96) (runs: 64, μ: 225342, ~: 228487)\n[PASS] test_buyExactInputETH() (gas: 240462)\n[PASS] test_buyExactOutputDaemon() (gas: 256047)\n[PASS] test_dust99WeiChargesZeroAnd100ChargesOne() (gas: 381501)\n[PASS] test_failedForwardPreservesClaimsAndSwapsRemainLive() (gas: 621195)\n[PASS] test_forwardAllETHAndPreserveLiquidityAndTokens() (gas: 612247)\n[PASS] test_insufficientETHSettlementRollsBackFeeClaims() (gas: 236699)\n[PASS] test_lpFeesRemainIndependent() (gas: 273596)\n[PASS] test_nativeTokenOnlySeedOnEmptyManager() (gas: 26069257)\n[PASS] test_nonNativePoolRejected() (gas: 25879765)\n[PASS] test_onlyFactoryOnePoolAndCallbackAuthentication() (gas: 25323012)\n[PASS] test_ownerCannotRedirectFeesAfterSetup() (gas: 200165)\n[PASS] test_permissionsAndBounds() (gas: 92121)\n[PASS] test_reverseNativeOrderRejectedByRealPoolManager() (gas: 25076794)\n[PASS] test_sellExactInputDaemon() (gas: 242960)\n[PASS] test_sellExactOutputETH() (gas: 224275)\n[PASS] test_specifiedETHPartialFillRevertsWithoutCharging() (gas: 200200)\n[PASS] test_unconfiguredForwardAndEmptyClaims() (gas: 118310)\n[PASS] test_unspecifiedETHPartialFillChargesOnlyActualOutput() (gas: 248005)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 51.99ms (122.30ms CPU time)\n\nRan 3 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_broadcastEntryRefusesPublicChains() (gas: 7578585)\n[PASS] test_deployRejectsZeroConfig() (gas: 7578501)\n[PASS] test_deployWiresEverythingAndFactoryCanOpenThePool() (gas: 195994360)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 88.07ms (88.14ms CPU time)\n\nRan 9 tests for test/DaemonHook.t.sol:HookOrderMatrixTest\n[PASS] testFuzz_bothOrdersDirectionsAndExactModes(bool,bool,bool,uint64) (runs: 64, μ: 17514756, ~: 17525355)\n[PASS] test_matrixETH0BuyExactInput() (gas: 17525765)\n[PASS] test_matrixETH0BuyExactOutput() (gas: 17524968)\n[PASS] test_matrixETH0SellExactInput() (gas: 17525664)\n[PASS] test_matrixETH0SellExactOutput() (gas: 17524883)\n[PASS] test_matrixETH1BuyExactInput() (gas: 17525853)\n[PASS] test_matrixETH1BuyExactOutput() (gas: 17524983)\n[PASS] test_matrixETH1SellExactInput() (gas: 17525709)\n[PASS] test_matrixETH1SellExactOutput() (gas: 17524932)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 933.30ms (1.10s CPU time)\n\nRan 8 test suites in 934.13ms (1.10s CPU time): 92 tests passed, 0 failed, 0 skipped (92 total tests)\n","passed":true},{"durationMs":86,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"DaemonHook.acceptOwnership()\",\"DaemonHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"DaemonHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"DaemonHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"DaemonHook.forwardFees()\",\"DaemonHook.setTreasury(address)\",\"DaemonHook.transferOwnership(address)\",\"DaemonHook.unlockCallback(bytes)\",\"DaemonToken.approve(address,uint256)\",\"DaemonToken.permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\",\"DaemonToken.transfer(address,uint256)\",\"DaemonToken.transferFrom(address,address,uint256)\",\"DistributionReceiver.acceptOwnership()\",\"DistributionReceiver.distribute()\",\"DistributionReceiver.setRecipients(address,address,address)\",\"DistributionReceiver.transferOwnership(address)\",\"GameRewards.acceptOwnership()\",\"GameRewards.claimReward(uint256)\",\"GameRewards.collectCreatorFees()\",\"GameRewards.configureSeason(uint256,uint256,uint256,uint256,uint256,bytes32)\",\"GameRewards.publishAllocations((uint256,uint256,uint256,address,uint256,bool)[],bytes32)\",\"GameRewards.receive()\",\"GameRewards.register(uint256)\",\"GameRewards.reportResult(uint256,uint256,bool)\",\"GameRewards.setArbiter(address)\",\"GameRewards.setFeeSource(address,uint64)\",\"GameRewards.setIdentityNft(address)\",\"GameRewards.setRewardAuthority(address,address)\",\"GameRewards.transferOwnership(address)\",\"NFTTreasury.acceptOwnership()\",\"NFTTreasury.buyNFT(address,address,uint256,address,uint256,uint256)\",\"NFTTreasury.deliverPrize(address,uint256,address)\",\"NFTTreasury.disablePayment(address)\",\"NFTTreasury.receive()\",\"NFTTreasury.sealPolicy(address,address)\",\"NFTTreasury.setAssetPolicy(address,uint256,uint256,uint256)\",\"NFTTreasury.setCollection(address,bool)\",\"NFTTreasury.setMarketplace(address,bool)\",\"NFTTreasury.setOperator(address,bool)\",\"NFTTreasury.setPaused(bool)\",\"NFTTreasury.transferOwnership(address)\"],\"files\":{\".gitignore\":4,\"README.md\":168,\"abi/DaemonHook.json\":1352,\"abi/DaemonToken.json\":317,\"abi/Deploy.json\":238,\"abi/DistributionReceiver.json\":384,\"abi/GameRewards.json\":1305,\"abi/HookFlags.json\":1,\"abi/ICreatorFeeFactory.json\":147,\"abi/NFTTreasury.json\":824,\"docs/FACTORY.md\":109,\"docs/SEASON.md\":84,\"docs/SECURITY.md\":117,\"docs/factory-source.json\":153,\"docs/launch-fees-source.json\":45,\"docs/validation/RESULTS.md\":62,\"docs/validation/build.txt\":734,\"docs/validation/contract-sizes.json\":37,\"docs/validation/fmt.txt\":0,\"docs/validation/test.txt\":119,\"docs/verified-sources.json\":113,\"foundry.toml\":24,\"remappings.txt\":3,\"script/Deploy.s.sol\":94,\"scripts/export_abis.py\":25,\"scripts/verify_sources.py\":29,\"src/DaemonHook.sol\":329,\"src/DaemonToken.sol\":18,\"src/DistributionReceiver.sol\":103,\"src/GameRewards.sol\":416,\"src/HookFlags.sol\":36,\"src/ICreatorFeeFactory.sol\":18,\"src/NFTTreasury.sol\":234,\"test/DaemonHook.t.sol\":362,\"test/DaemonToken.t.sol\":78,\"test/Deploy.t.sol\":79,\"test/DistributionReceiver.t.sol\":98,\"test/FactoryIntegration.t.sol\":241,\"test/GameRewards.t.sol\":487,\"test/NFTTreasury.t.sol\":268,\"test/mocks/MockERC20.sol\":15,\"test/mocks/MockERC721.sol\":17,\"test/mocks/MockMarketplace.sol\":59,\"test/utils/Fixture.sol\":126,\"test/utils/HookDeployer.sol\":34,\"test/verified/HookFlags.sol\":45,\"test/verified/LaunchFactory.sol\":357,\"test/verified/LaunchFees.sol\":73,\"test/verified/LaunchRegistry.sol\":107,\"test/verified/MerkleDistributor.sol\":170,\"test/verified/PoolFees.sol\":214,\"test/verified/openzeppelin/LICENSE\":22,\"test/verified/openzeppelin/access/Ownable.sol\":100,\"test/verified/openzeppelin/access/Ownable2Step.sol\":67,\"test/verified/openzeppelin/interfaces/IERC1363.sol\":86,\"test/verified/openzeppelin/interfaces/IERC165.sol\":6,\"test/verified/openzeppelin/interfaces/IERC20.sol\":6,\"test/verified/openzeppelin/interfaces/IERC20Metadata.sol\":6,\"test/verified/openzeppelin/token/ERC20/IERC20.sol\":79,\"test/verified/openzeppelin/token/ERC20/extensions/IERC20Metadata.sol\":26,\"test/verified/openzeppelin/token/ERC20/utils/SafeERC20.sol\":285,\"test/verified/openzeppelin/utils/Context.sol\":28,\"test/verified/openzeppelin/utils/ReentrancyGuard.sol\":119,\"test/verified/openzeppelin/utils/StorageSlot.sol\":143,\"test/verified/openzeppelin/utils/cryptography/Hashes.sol\":31,\"test/verified/openzeppelin/utils/cryptography/MerkleProof.sol\":505,\"test/verified/openzeppelin/utils/introspection/IERC165.sol\":25},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":2310,"exitCode":0,"name":"slither","output":"[high/medium] reentrancy-eth at src/NFTTreasury.sol:169: Reentrancy in NFTTreasury.buyNFT(address,address,uint256,address,uint256,uint256) (src/NFTTreasury.sol#169-213):\n[medium/medium] divide-before-multiply at src/DaemonHook.sol:199: DaemonHook.beforeSwap(address,PoolKey,SwapParams,bytes) (src/DaemonHook.sol#199-220) performs a multiplication on the result of a division:\n[medium/high] incorrect-equality at src/DistributionReceiver.sol:88: DistributionReceiver.distribute() (src/DistributionReceiver.sol#88-102) uses a dangerous strict equality:\n[medium/medium] uninitialized-local at src/GameRewards.sol:356: GameRewards.publishAllocations(GameRewards.Allocation[],bytes32).tokens (src/GameRewards.sol#356) is a local variable never initialized\n[medium/medium] uninitialized-local at src/GameRewards.sol:358: GameRewards.publishAllocations(GameRewards.Allocation[],bytes32).nfts (src/GameRewards.sol#358) is a local variable never initialized\n[medium/medium] uninitialized-local at src/GameRewards.sol:357: GameRewards.publishAllocations(GameRewards.Allocation[],bytes32).eth (src/GameRewards.sol#357) is a local variable never initialized\n[medium/medium] unused-return at src/DaemonHook.sol:163: DaemonHook.forwardFees() (src/DaemonHook.sol#163-168) ignores return value by poolManager.unlock(abi.encode(amount)) (src/DaemonHook.sol#167)\n[medium/medium] unused-return at src/GameRewards.sol:249: GameRewards.collectCreatorFees() (src/GameRewards.sol#249-256) ignores return value by (key,None,None,requester) = feeFactory.positionOf(feeLaunchNumber) (src/GameRewards.sol#251)\n[low/medium] calls-loop at src/GameRewards.sol:346: GameRewards.publishAllocations(GameRewards.Allocation[],bytes32) (src/GameRewards.sol#346-387) has external calls inside a loop: IERC721Minimal(a.collection).ownerOf(a.prizeTokenId) != custodian (src/GameRewards.sol#372)\n[low/medium] reentrancy-benign at src/NFTTreasury.sol:169: Reentrancy in NFTTreasury.buyNFT(address,address,uint256,address,uint256,uint256) (src/NFTTreasury.sol#169-213):\n[low/medium] reentrancy-benign at src/DaemonHook.sol:256: Reentrancy in DaemonHook._chargeFee(PoolKey,bool,bool,uint256) (src/DaemonHook.sol#256-260):\n[low/medium] reentrancy-benign at src/DaemonHook.sol:171: Reentrancy in DaemonHook.unlockCallback(bytes) (src/DaemonHook.sol#171-179):\n[low/medium] reentrancy-events at src/DaemonHook.sol:171: Reentrancy in DaemonHook.unlockCallback(bytes) (src/DaemonHook.sol#171-179):\n[low/medium] reentrancy-events at src/DaemonHook.sol:256: Reentrancy in DaemonHook._chargeFee(PoolKey,bool,bool,uint256) (src/DaemonHook.sol#256-260):\n[low/medium] timestamp at src/GameRewards.sol:346: GameRewards.publishAllocations(GameRewards.Allocation[],bytes32) (src/GameRewards.sol#346-387) uses timestamp for comparisons\n[low/medium] timestamp at src/GameRewards.sol:206: GameRewards.configureSeason(uint256,uint256,uint256,uint256,uint256,bytes32) (src/GameRewards.sol#206-236) uses timestamp for comparisons\n[low/medium] timestamp at src/NFTTreasury.sol:169: NFTTreasury.buyNFT(address,address,uint256,address,uint256,uint256) (src/NFTTreasury.sol#169-213) uses timestamp for comparisons\n[low/medium] timestamp at src/GameRewards.sol:260: GameRewards.isOfficial() (src/GameRewards.sol#260-262) uses timestamp for comparisons\n[low/medium] timestamp at src/GameRewards.sol:390: GameRewards.claimReward(uint256) (src/GameRewards.sol#390-411) uses timestamp for comparisons","passed":true},{"durationMs":552,"exitCode":0,"name":"aderyn","output":"[high] contract-locks-ether at src/GameRewards.sol:20: Contract locks Ether without a withdraw function (2 places)\n[high] reentrancy-state-change at src/DaemonHook.sol:174: Reentrancy: State change after external call (10 places)\n[low] centralization-risk at src/DaemonHook.sol:133: Centralization Risk (18 places)\n[low] costly-loop at src/GameRewards.sol:359: Costly operations inside loop\n[low] division-before-multiplication at src/DaemonHook.sol:213: Incorrect Order of Division and Multiplication\n[low] internal-function-used-once at src/HookFlags.sol:28: Internal Function Used Only Once\n[low] large-numeric-literal at src/DaemonHook.sol:27: Large Numeric Literal\n[low] literal-instead-of-constant at src/DaemonHook.sol:213: Literal Instead of Constant (6 places)\n[low] require-revert-in-loop at src/GameRewards.sol:359: Loop Contains `require`/`revert`\n[low] solmate-safe-transfer-lib at src/DistributionReceiver.sol:5: Solmate's SafeTransferLib (3 places)\n[low] state-change-without-event at src/GameRewards.sol:249: State Change Without Event\n[low] unchecked-return at src/DaemonHook.sol:167: Unchecked Return\n[low] uninitialized-local-variable at src/GameRewards.sol:358: Uninitialized Local Variable (2 places)","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"16f5f1b9ff555e6fe3c577fbd8a6df374e8137fe591b335b630ec7a3d6be126a","verifiedTreeHash":"0a255ace94d46c6957c9ecb93016ade5b3dee4d1","verifierVersion":"0.1.0+7ff5db2c"}]}