{"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":"80dc62dc-0e0b-42ea-bc28-5128fc6eff2a","kind":"skill:build-contract-project","nodes":[{"acceptedSubmissionHash":"0226bcc687742fe2a63d10e74fbfd1b53ed84d0ec9b781133d7177e770660776","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":"Reports:\nv1: job b9e37680-814c-4f17-b4bc-68272b77304d\nhttps://api.imd.fun/artifacts/dfbd6842bdf572b684b09c4e56d150483da21ccc8dfb14d05fb01409c4441c0b\nhttps://github.com/Identity-md/research/tree/main/jobs/b9e37680-814c-4f17-b4bc-68272b77304d\nv2: job 10d225a6-92cb-4cde-9d4b-ec076b078f7d\nhttps://api.imd.fun/artifacts/cd34576baf9021fc2bd1d6f12da420599bc2bf0355465b7ab0796eabfe6be64a\nhttps://github.com/Identity-md/research/tree/main/jobs/10d225a6-92cb-4cde-9d4b-ec076b078f7d\nUse the fee splits, rarity and sim assumptions from these reports. If the v2 sim code is not in the repo, rebuild the model from the assumptions stated in report v2 and say so in the report.\n\nSwarm wallet: not known yet, the token is not launched. Make swarmWallet, heartbeatRecipient and token address constructor params. Use placeholder addresses in tests, deploy script reads them from env. Do not invent real addresses.\n\nAlso add item sets: 6 types GPU, ASIC, Power Supply, Cooling, Motherboard, Router (plus Room keys). Every item mines alone, room = 6 slots one per type. Set bonuses: all 6 in a room +25% hashrate, GPU+ASIC +10%, Power Supply+Cooling -15% electricity, Motherboard+Router -25% blackout damage, 3+ same rarity in a room +5/10/20% (Rare/Epic/Legendary). Total cap +40%, values in Params. Include in the sim.\n\nWho can call what: No owner. Swarm role (swarmWallet, constructor param) can only: change Params within hard bounds and max 10% step per 24h, submit grid event numbers, post herald letters. Team address can only change itself. Players: buy and open packs, place items, claim, spend, lock and unlock Generator, lobby, set referrer once, claim starter pack with merkle proof. Anyone: resolve pack and event randomness after the target block, donate tokens to RewardPool, trigger emission and inspection payout. Nobody can mint items outside PackSale and StarterClaim, withdraw pools or move user funds.\nUpgrades and pausing: Not upgradeable. Only PackSale can be paused, by the swarm role, auto-unpause after max 72h. Claims, unlocks and withdrawals can never be paused.","parentJobId":"21248c45-9e6e-4e68-bf90-de66eeac77cd","planHash":"3e6cdb18ca7a26667b38c29dd9c6c17f2995860cfedac0e7cfeda55e7b2c820b","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"21248c45-9e6e-4e68-bf90-de66eeac77cd","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-1269-reports-v1-job-b9e37680-814c-4f17-b4bc-6"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"51322","feedbackHash":"83631767a568a1b602ab5da6b326261a55bd3eee12986f5336c0082ee14d36a7","nodeKey":"build_contract_project","submissionHash":"0226bcc687742fe2a63d10e74fbfd1b53ed84d0ec9b781133d7177e770660776","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"6e4126bb3933fda8a4fd2507987b3cfd48006cc50da1985393482438e1538cf0","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"72488bc823eb36d410e8da780f5aa60acc39282fb0cf25f5260a9f8b3e23a9eb","device":"3ac34bfb544bbc10","findings":[],"hash":"0226bcc687742fe2a63d10e74fbfd1b53ed84d0ec9b781133d7177e770660776","nodeId":"f8c62fb4-9f67-411b-be4a-032edf1a2136","outcome":"completed","summary":"Implemented contracts, deployment scripts, tests, documentation, and the reconstructed v2 simulation. See [report.md](/home/identitymd6/.identitymd/work/80dc62dc-0e0b-42ea-bc28-5128fc6eff2a/f8c62fb4-9f67-411b-be4a-032edf1a2136/report.md).\n\n- Build, tests, and formatting checks pass.\n- 68 tests pass, including fresh offline verification.\n- Separate Robinhood fork smoke test passes.\n\nNothing deployed. Independent review remains outstanding.","treeHash":"3658ec084c9d16687c1b54cdcba4c5fbac0642c0","usage":{"cachedInputTokens":11213440,"inputTokens":368324,"model":"gpt-6-astra","outputTokens":157548,"runtime":"codex","turns":16,"wallClockMs":3860228}}],"verification":[{"checks":[{"durationMs":69708,"exitCode":0,"name":"build","output":"Compiling 123 files with Solc 0.8.26\nSolc 0.8.26 finished in 59.67s\nCompiler run successful!\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n   ╭▸ src/Generator.sol:37:9\n   │\n37 │         farm.refresh(msg.sender);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n   ╭▸ src/StarterClaim.sol:60:9\n   │\n60 │         farm.register(msg.sender);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n   ╭▸ src/StarterClaim.sol:57:20\n   │\n57 │             uint16(e * params.get(Params.Key.EpochHashBps) > 4000 ? 4000 : e * params.get(Params.Key.EpochHashBps)),\n   │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n   ╭▸ src/StarterClaim.sol:57:76\n   │\n57 │             uint16(e * params.get(Params.Key.EpochHashBps) > 4000 ? 4000 : e * params.get(Params.Key.EpochHashBps)),\n   │                                                                            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/PackSale.sol:59:16\n   │\n59 │         return block.timestamp < pausedUntil;\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/Generator.sol:38:9\n   │\n38 │         emit Locked(msg.sender, amount, unlockAt[msg.sender]);\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/StarterClaim.sol:46:13\n   │\n46 │         if (block.timestamp < launchTime + 48 hours || block.timestamp >= launchTime + 16 days) revert TooEarly();\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/StarterClaim.sol:46:56\n   │\n46 │         if (block.timestamp < launchTime + 48 hours || block.timestamp >= launchTime + 16 days) revert TooEarly();\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/StarterClaim.sol:57:20\n   │\n57 │             uint16(e * params.get(Params.Key.EpochHashBps) > 4000 ? 4000 : e * params.get(Params.Key.EpochHashBps)),\n   │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[incorrect-strict-equality]: dangerous strict equality check on an externally-influenced value\n   ╭▸ src/Generator.sol:36:13\n   │\n36 │         if (token.balanceOf(address(this)) - beforeBalance != amount) revert InvalidValue();\n   │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/incorrect-strict-equality\n\nwarning[encode-packed-collision]: `abi.encodePacked()` called with multiple dynamic type arguments; hash collisions possible\n   ╭▸ src/FarmItems.sol:36:29\n   │\n36 │           bytes memory json = abi.encodePacked(\n   │ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n37 │ ┃             '{\"name\":\"BLACKOUT ',\n38 │ ┃             rarities[rarity],\n39 │ ┃             \" \",\n   ‡ ┃\n52 │ ┃             '\"}]}'\n53 │ ┃         );\n   │ ┗━━━━━━━━━┛\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/encode-packed-collision\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/StarterClaim.sol:61:9\n   │\n61 │         emit StarterCommitted(tokenId, msg.sender, target);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n   ╭▸ src/Generator.sol:47:9\n   │\n47 │         farm.refresh(msg.sender);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/GridOperator.sol:87:13\n   │\n87 │             mean += lobbyValue(i);\n   │             ━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/StarterClaim.sol:55:13\n   │\n55 │             uint64(target),\n   │             ━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint64' 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/StarterClaim.sol:56:13\n   │\n56 │             uint8(e),\n   │             ━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint8' 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/StarterClaim.sol:57:13\n   │\n57 │             uint16(e * params.get(Params.Key.EpochHashBps) > 4000 ? 4000 : e * params.get(Params.Key.EpochHashBps)),\n   │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint16' 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[require-revert-in-loop]: `require` or `revert` inside a loop\n   ╭▸ src/GridOperator.sol:79:21\n   │\n79 │         if (d >= 8) revert InvalidValue();\n   │                     ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/PackSale.sol:70:25\n   │\n70 │         if (paused() || block.timestamp < pauseAgainAfter) revert TooEarly();\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/Generator.sol:44:13\n   │\n44 │         if (block.timestamp < unlockAt[msg.sender]) revert TooEarly();\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/PackSale.sol:77:13\n   │\n77 │         if (block.timestamp < launchTime) return 0;\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/PackSale.sol:79:16\n   │\n79 │         return t < 12 hours ? 3 : t < 24 hours ? 6 : t < 48 hours ? 10 : 20;\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/PackSale.sol:79:35\n   │\n79 │         return t < 12 hours ? 3 : t < 24 hours ? 6 : t < 48 hours ? 10 : 20;\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/PackSale.sol:79:54\n   │\n79 │         return t < 12 hours ? 3 : t < 24 hours ? 6 : t < 48 hours ? 10 : 20;\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/Generator.sol:49:9\n   │\n49 │         emit Unlocked(msg.sender, amount);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n   ╭▸ src/StarterClaim.sol:78:13\n   │\n78 │             items.mint(c.player, ids[i]);\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/PackSale.sol:83:13\n   │\n83 │         if (block.timestamp < launchTime) return 0;\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/PackSale.sol:85:16\n   │\n85 │         return t < 6 hours ? 75 : t < 24 hours ? 150 : t < 48 hours ? 300 : type(uint256).max;\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/PackSale.sol:85:35\n   │\n85 │         return t < 6 hours ? 75 : t < 24 hours ? 150 : t < 48 hours ? 300 : type(uint256).max;\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/PackSale.sol:85:56\n   │\n85 │         return t < 6 hours ? 75 : t < 24 hours ? 150 : t < 48 hours ? 300 : type(uint256).max;\n   │                                                        ━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[calls-loop]: external call inside a loop\n   ╭▸ src/StarterClaim.sol:78:13\n   │\n78 │             items.mint(c.player, ids[i]);\n   │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/GridOperator.sol:95:13\n   │\n95 │         if (block.timestamp < launchTime || msg.value == 0) revert InvalidValue();\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/StarterClaim.sol:80:9\n   │\n80 │         emit StarterResolved(tokenId, expired, ids);\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/PackSale.sol:90:45\n   │\n90 │             if (boughtAt[player][i] != 0 && block.timestamp < uint256(boughtAt[player][i]) + 1 days) ++n;\n   │                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n   ╭▸ src/lib/ItemMath.sol:11:50\n   │\n11 │         if (kind > 6 || rarity > 3 || epoch > 4) revert InvalidValue();\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/lib/ItemMath.sol:27:27\n   │\n27 │         if (bonus > 4000) revert InvalidValue();\n   │                           ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/PackSale.sol:97:17\n   │\n97 │             if (hourBuckets[i].number + 24 >= hour) n += hourBuckets[i].count;\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/PackSale.sol:102:13\n    │\n102 │         if (block.timestamp < launchTime) return 0;\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/PackSale.sol:104:13\n    │\n104 │         if (e > 4) e = 4;\n    │             ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[missing-events-access-control]: `team` is changed without an event but is used for access control\n   ╭▸ src/FeeRouter.sol:96:9\n   │\n96 │         team = next;\n   │         ━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/PackSale.sol:124:17\n    │\n124 │             p = p * (10000 + premium) / 10000;\n    │                 ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/PackSale.sol:111:21\n    │\n111 │         uint256 e = block.timestamp < launchTime ? 0 : (block.timestamp - launchTime) / 7 days;\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/PackSale.sol:112:13\n    │\n112 │         if (e > 128) e = 128;\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/PackSale.sol:113:25\n    │\n113 │         for (uint256 i; i < e; ++i) {\n    │                         ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n   ╭▸ src/RewardPool.sol:35:14\n   │\n35 │         if (!IEmission(rewards).checkpoint(64)) revert CatchUpRequired();\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/RewardPool.sol:39:9\n   │\n39 │         emit Donated(msg.sender, amount);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[incorrect-strict-equality]: dangerous strict equality check on an externally-influenced value\n   ╭▸ src/RewardPool.sol:38:13\n   │\n38 │         if (token.balanceOf(address(this)) - beforeBalance != amount) revert InvalidValue();\n   │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/incorrect-strict-equality\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/PackSale.sol:155:9\n    │\n155 │         farm.register(player);\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/PackSale.sol:136:41\n    │\n136 │         if (tokenPackAt[player] != 0 && block.timestamp < tokenPackAt[player] + 1 days) revert TooEarly();\n    │                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n   ╭▸ src/lib/ItemMath.sol:18:73\n   │\n18 │         if (id >> BONUS_SHIFT > 4000 || id & (uint256(127) << 17) != 0) revert InvalidValue();\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/lib/ItemMath.sol:19:40\n   │\n19 │         if (plain == 0 || plain > 140) revert InvalidValue();\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/FarmItems.sol:61:68\n   │\n61 │                 if (starter && from != farmCore && to != farmCore) revert Unauthorized();\n   │                                                                    ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[encode-packed-collision]: `abi.encodePacked()` called with multiple dynamic type arguments; hash collisions possible\n   ╭▸ src/MarketFactory.sol:20:13\n   │\n20 │ ┏             abi.encodePacked(\n21 │ ┃                 type(V4Market).creationCode,\n22 │ ┃                 abi.encode(c.manager, c.token, c.params, c.fees, c.networkRecipient, uint24(0), c.tickSpacing)\n23 │ ┃             )\n   │ ┗━━━━━━━━━━━━━┛\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/encode-packed-collision\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/MarketFactory.sol:58:9\n   │\n58 │         emit MarketDeployed(address(market), salt);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/V4Market.sol:118:13\n    │\n118 │             emit PriceObserved(now_, price);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/V4Market.sol:131:9\n    │\n131 │         emit PriceObserved(now_, price);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/GridOperator.sol:109:9\n    │\n109 │         emit Lobbied(player, d, value, inTokens);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-eth]: uncapped ETH transfer can be reentered before `_status` is updated\n    ╭▸ src/FeeRouter.sol:103:22\n    │\n103 │         (bool ok,) = msg.sender.call{value: amount}(\"\");\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-eth\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/PackSale.sol:142:13\n    │\n142 │         if (block.timestamp < launchTime || paused()) revert TooEarly();\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/PackSale.sol:146:13\n    │\n146 │         if (h.number != hour) {\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/FeeRouter.sol:105:9\n    │\n105 │         emit Withdrawn(msg.sender, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/PackSale.sol:170:9\n    │\n170 │         emit PackCommitted(id, player, count, target, epoch());\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/PackSale.sol:147:24\n    │\n147 │             h.number = uint64(hour);\n    │                        ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' 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/PackSale.sol:151:20\n    │\n151 │         h.count += uint192(count);\n    │                    ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint192' 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/PackSale.sol:153:61\n    │\n153 │             boughtAt[player][walletCursor[player]++ % 20] = uint64(block.timestamp);\n    │                                                             ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' 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[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FeeRouter.sol:124:14\n    │\n124 │         if (!params.emission().checkpoint(64)) revert CatchUpRequired();\n    │              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/PackSale.sol:160:13\n    │\n160 │             uint64(target),\n    │             ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' 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/PackSale.sol:161:13\n    │\n161 │             uint8(count),\n    │             ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/PackSale.sol:162:13\n    │\n162 │             uint8(epoch()),\n    │             ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/PackSale.sol:163:13\n    │\n163 │ ┏             uint16(\n164 │ ┃                 epoch() * params.get(Params.Key.EpochHashBps) > 4000\n165 │ ┃                     ? 4000\n166 │ ┃                     : epoch() * params.get(Params.Key.EpochHashBps)\n167 │ ┃             ),\n    │ ┗━━━━━━━━━━━━━┛\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint16' 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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/FeeRouter.sol:116:29\n    │\n116 │         if (lastBuy != 0 && block.timestamp < lastBuy + 10 minutes) revert TooEarly();\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/FeeRouter.sol:129:9\n    │\n129 │         emit Bought(burn, ethAmount, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/PackSale.sol:177:9\n    │\n177 │         farm.chargeMerge(msg.sender, resultId);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/PackSale.sol:178:9\n    │\n178 │         items.burnForMerge(msg.sender, id);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/PackSale.sol:179:9\n    │\n179 │         items.mint(msg.sender, resultId);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/FeeRouter.sol:126:9\n    │\n126 │         market.buy{value: ethAmount}(minOut, recipient);\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/PackSale.sol:180:9\n    │\n180 │         emit Merged(msg.sender, id, resultId);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/PackSale.sol:197:13\n    │\n197 │             items.mint(c.player, ids[i]);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/PackSale.sol:199:9\n    │\n199 │         farm.paidPackOpened(c.player, c.count);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/PackSale.sol:197:13\n    │\n197 │             items.mint(c.player, ids[i]);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/PackSale.sol:200:9\n    │\n200 │         emit PackResolved(id, expired, ids);\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/GridOperator.sol:130:13\n    │\n130 │             block.timestamp < launchTime || tick != (block.timestamp - launchTime) / 12 hours\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/GridOperator.sol:130:45\n    │\n130 │             block.timestamp < launchTime || tick != (block.timestamp - launchTime) / 12 hours\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/GridOperator.sol:131:20\n    │\n131 │                 || block.timestamp >= launchTime + tick * 12 hours + 1 hours\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/GridOperator.sol:153:63\n    │\n153 │                 || (tick + 1 - lastBlackout[d]) * 12 hours >= params.get(Params.Key.BlackoutCooldownSeconds);\n    │                                                               ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n   ╭▸ src/GridOperator.sol:90:39\n   │\n90 │         uint256 penalty = Math.mulDiv(params.get(Params.Key.LobbyKBps), lobbyValue(d), mean);\n   │                                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n   ╭▸ src/GridOperator.sol:91:25\n   │\n91 │         return Math.max(params.get(Params.Key.LobbyMinWeight), 10000 * 10000 / (10000 + penalty));\n   │                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/GridOperator.sol:156:9\n    │\n156 │         emit EventSubmitted(tick, kind, e.target);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/GridOperator.sol:149:20\n    │\n149 │         e.target = uint64(ChainClock.number() + 2);\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' 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[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/V4Market.sol:125:38\n    │\n125 │             uint256 c = cumulative + (1e60 / lastPrice) * (minute * 60 - updatedAt);\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/V4Market.sol:128:23\n    │\n128 │         cumulative += (1e60 / lastPrice) * (now_ - updatedAt);\n    │                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/GridOperator.sol:164:14\n    │\n164 │         if (!emission.checkpoint(64)) revert CatchUpRequired();\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/V4Market.sol:123:13\n    │\n123 │         if (last >= 32 && first < last - 31) first = last - 31;\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/V4Market.sol:123:27\n    │\n123 │         if (last >= 32 && first < last - 31) first = last - 31;\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/V4Market.sol:124:38\n    │\n124 │         for (uint256 minute = first; minute <= last; ++minute) {\n    │                                      ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/V4Market.sol:126:53\n    │\n126 │             observations[minute % 32] = Observation(uint64(minute), c);\n    │                                                     ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' 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[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/GridOperator.sol:174:21\n    │\n174 │                     sum += e.weights[d];\n    │                     ━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/V4Market.sol:137:50\n    │\n137 │         if (ts >= updatedAt) return cumulative + (1e60 / lastPrice) * (ts - updatedAt);\n    │                                                  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/GridOperator.sol:166:43\n    │\n166 │         bool expired = h == bytes32(0) || block.timestamp >= launchTime + tick * 12 hours + 1 hours;\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/V4Market.sol:144:35\n    │\n144 │         if (initializedAt == 0 || block.timestamp < initializedAt + 31 minutes) revert NotConfigured();\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/GridOperator.sol:196:9\n    │\n196 │         emit EventResolved(tick, e.kind, e.first, e.second, expired);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/GridOperator.sol:182:39\n    │\n182 │ …                     e.first = uint8(d);\n    │                                 ━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/V4Market.sol:158:13\n    │\n158 │         if (a.period != p) {\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/V4Market.sol:164:13\n    │\n164 │         if (b.period != p) {\n    │             ━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/GridOperator.sol:190:27\n    │\n190 │                 e.first = uint8(seed % 8);\n    │                           ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/GridOperator.sol:191:28\n    │\n191 │                 e.second = uint8((uint256(e.first) + 1 + (seed / 8) % 7) % 8);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/V4Market.sol:160:24\n    │\n160 │             a.period = uint64(p);\n    │                        ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' 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/GridOperator.sol:195:24\n    │\n195 │         e.resolvedAt = uint64(block.timestamp);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' 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/V4Market.sol:166:24\n    │\n166 │             b.period = uint64(p);\n    │                        ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' 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/V4Market.sol:169:24\n    │\n169 │             a.sells += uint192(amount);\n    │                        ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint192' 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[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/GridOperator.sol:203:14\n    │\n203 │         if (!emission.checkpoint(64)) revert CatchUpRequired();\n    │              ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/V4Market.sol:170:24\n    │\n170 │             b.sells += uint192(amount);\n    │                        ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint192' 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/V4Market.sol:172:23\n    │\n172 │             a.buys += uint192(amount);\n    │                       ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint192' 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/V4Market.sol:173:23\n    │\n173 │             b.buys += uint192(amount);\n    │                       ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint192' 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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/GridOperator.sol:200:13\n    │\n200 │         if (block.timestamp < launchTime + tick * 12 hours + 1 hours) revert TooEarly();\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/GridOperator.sol:207:9\n    │\n207 │         emit EventResolved(tick, Kind.Calm, 0, 0, true);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/V4Market.sol:184:17\n    │\n184 │                 b += shortVolumes[i].buys;\n    │                 ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/V4Market.sol:183:17\n    │\n183 │                 s += shortVolumes[i].sells;\n    │                 ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/GridOperator.sol:205:24\n    │\n205 │         e.resolvedAt = uint64(block.timestamp);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' 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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/V4Market.sol:182:17\n    │\n182 │             if (uint256(shortVolumes[i].period) + 12 > current) {\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/V4Market.sol:192:17\n    │\n192 │             if (uint256(longVolumes[i].period) + 24 > current) {\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/GridOperator.sol:223:43\n    │\n223 │             if (bucket & 1 != 0) damage = damage * 7500 / 10000;\n    │                                           ━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/V4Market.sol:205:13\n    │\n205 │         if (average != 0 && price > average) dev = Math.min(1000, 10000 - Math.mulDiv(average, 10000, price));\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/V4Market.sol:204:13\n    │\n204 │         if (block.timestamp >= initializedAt + 31 minutes) average = twap();\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/V4Market.sol:210:27\n    │\n210 │         uint256 decayed = storedFeeWad > fall ? storedFeeWad - fall : 100 ether;\n    │                           ━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/V4Market.sol:224:25\n    │\n224 │         uint256 ethIn = uint256(-p.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/V4Market.sol:226:19\n    │\n226 │         if (fee > uint256(uint128(type(int128).max))) revert InvalidValue();\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/V4Market.sol:226:27\n    │\n226 │         if (fee > uint256(uint128(type(int128).max))) revert InvalidValue();\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/V4Market.sol:228:43\n    │\n228 │         return (this.beforeSwap.selector, int256(fee << 128), 0);\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[reentrancy-no-eth]: external call can be reentered before `get` is updated\n    ╭▸ src/Params.sol:141:14\n    │\n141 │         if (!emission.checkpoint(64)) revert CatchUpRequired();\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/Params.sol:135:13\n    │\n135 │         if (block.timestamp < lastChanged[key] + 1 days) revert TooEarly();\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/Params.sol:144:9\n    │\n144 │         emit ParamChanged(key, old, next);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/V4Market.sol:253:9\n    │\n253 │         emit SellFee(sender, output, bps, hour, day, dev);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/V4Market.sol:239:27\n    │\n239 │         int128 ethDelta = int128(delta >> 128);\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/V4Market.sol:242:28\n    │\n242 │             _record(false, uint256(-int256(ethDelta)));\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/V4Market.sol:246:26\n    │\n246 │         uint256 output = uint256(uint128(ethDelta));\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/V4Market.sol:246:34\n    │\n246 │         uint256 output = uint256(uint128(ethDelta));\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/V4Market.sol:254:42\n    │\n254 │         return (this.afterSwap.selector, int128(int256(base + excess + network)));\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/V4Market.sol:254:49\n    │\n254 │         return (this.afterSwap.selector, int128(int256(base + excess + network)));\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[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/V4Market.sol:270:31\n    │\n270 │         received = abi.decode(manager.unlock(abi.encode(msg.value, minOut, recipient)), (uint256));\n    │                               ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `initializedAt` is updated\n    ╭▸ src/V4Market.sol:282:24\n    │\n282 │         int256 delta = manager.swap(key(), SwapParams(true, -int256(input), 4295128740), \"\");\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/V4Market.sol:282:62\n    │\n282 │         int256 delta = manager.swap(key(), SwapParams(true, -int256(input), 4295128740), \"\");\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/V4Market.sol:284:27\n    │\n284 │         int128 ethDelta = int128(delta >> 128);\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/V4Market.sol:285:29\n    │\n285 │         int128 tokenDelta = int128(delta);\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/V4Market.sol:287:30\n    │\n287 │             ethDelta >= 0 || uint256(-int256(ethDelta)) != input || tokenDelta <= 0\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/V4Market.sol:288:20\n    │\n288 │                 || uint256(uint128(tokenDelta)) < minOut\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/V4Market.sol:288:28\n    │\n288 │                 || uint256(uint128(tokenDelta)) < minOut\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[unused-return]: return value of an external call is not used\n    ╭▸ src/V4Market.sol:292:9\n    │\n292 │         manager.settle{value: input}();\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/V4Market.sol:293:40\n    │\n293 │         manager.take(token, recipient, uint256(uint128(tokenDelta)));\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/V4Market.sol:293:48\n    │\n293 │         manager.take(token, recipient, uint256(uint128(tokenDelta)));\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/V4Market.sol:296:27\n    │\n296 │         return abi.encode(uint256(uint128(tokenDelta)));\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/V4Market.sol:296:35\n    │\n296 │         return abi.encode(uint256(uint128(tokenDelta)));\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[reentrancy-eth]: uncapped ETH transfer can be reentered before `_status` is updated\n    ╭▸ src/V4Market.sol:303:22\n    │\n303 │         (bool ok,) = networkRecipient.call{value: amount}(\"\");\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-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/V4Market.sol:305:9\n    │\n305 │         emit NetworkPaid(amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:248:14\n    │\n248 │         if (!rewards.checkpoint(64)) revert CatchUpRequired();\n    │              ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:283:9\n    │\n283 │         rewards.update(player, buckets, hashes, power);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:154:9\n    │\n154 │         items.safeTransferFrom(msg.sender, address(this), id, 1, \"\");\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/FarmCore.sol:156:9\n    │\n156 │         emit Placed(msg.sender, id, room, slot);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:175:9\n    │\n175 │         items.safeTransferFrom(address(this), msg.sender, id, 1, \"\");\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/FarmCore.sol:176:9\n    │\n176 │         emit Unplaced(msg.sender, id, room, slot);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:188:9\n    │\n188 │         items.safeTransferFrom(msg.sender, address(this), id, 1, \"\");\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/FarmCore.sol:190:9\n    │\n190 │         emit RoomKey(msg.sender, room, id, true);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:202:9\n    │\n202 │         items.safeTransferFrom(address(this), msg.sender, id, 1, \"\");\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/FarmCore.sol:203:9\n    │\n203 │         emit RoomKey(msg.sender, room, id, false);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/FarmCore.sol:199:40\n    │\n199 │             if (f.rooms[room][i] != 0) revert InvalidValue();\n    │                                        ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/FarmCore.sol:210:13\n    │\n210 │         h = ItemMath.baseHash(rarity) * (10000 + epochBonus) / 10000 * (10 + level) / 10;\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FarmCore.sol:222:15\n    │\n222 │             ++count;\n    │               ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FarmCore.sol:280:17\n    │\n280 │                 power += Math.mulDiv(powers[i], effective, raw);\n    │                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FarmCore.sol:258:13\n    │\n258 │             raw += s.hash;\n    │             ━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmCore.sol:228:38\n    │\n228 │         if (count == 6) s.bonusBps = params.get(Params.Key.FullSetBps);\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmCore.sol:229:75\n    │\n229 │         if (f.rooms[room][0] != 0 && f.rooms[room][1] != 0) s.bonusBps += params.get(Params.Key.ComputePairBps);\n    │                                                                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmCore.sol:231:45\n    │\n231 │         if (rarities[3] >= 3) s.bonusBps += params.get(Params.Key.LegendarySetBps);\n    │                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmCore.sol:232:50\n    │\n232 │         else if (rarities[2] >= 3) s.bonusBps += params.get(Params.Key.EpicSetBps);\n    │                                                  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmCore.sol:233:50\n    │\n233 │         else if (rarities[1] >= 3) s.bonusBps += params.get(Params.Key.RareSetBps);\n    │                                                  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmCore.sol:234:43\n    │\n234 │         s.bonusBps = Math.min(s.bonusBps, params.get(Params.Key.SetCapBps));\n    │                                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmCore.sol:236:75\n    │\n236 │         uint256 saving = f.rooms[room][2] != 0 && f.rooms[room][3] != 0 ? params.get(Params.Key.ElectricityPairBps) : 0;\n    │                                                                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/FarmCore.sol:284:9\n    │\n284 │         emit Refreshed(player, effective, power);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/FarmCore.sol:215:24\n    │\n215 │         if (room >= 4) revert InvalidValue();\n    │                        ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FarmCore.sol:259:29\n    │\n259 │             buckets[room] = uint8(district(player) * 16 + (s.heatProof ? 4 : 0) + (s.shield ? 2 : 0));\n    │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/FarmCore.sol:266:22\n    │\n266 │         buckets[4] = uint8(district(player) * 16);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:302:14\n    │\n302 │         if (!rewards.checkpoint(64) || !rewards.settle(msg.sender, 64)) revert CatchUpRequired();\n    │              ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:302:41\n    │\n302 │         if (!rewards.checkpoint(64) || !rewards.settle(msg.sender, 64)) revert CatchUpRequired();\n    │                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:317:9\n    │\n317 │         rewards.recordWalletSpend(msg.sender, cost);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:318:22\n    │\n318 │         if (repair_) rewards.repair(msg.sender, units);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:319:14\n    │\n319 │         else rewards.prepay(msg.sender, cost);\n    │              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[incorrect-strict-equality]: dangerous strict equality check on an externally-influenced value\n    ╭▸ src/FarmCore.sol:316:13\n    │\n316 │         if (token.balanceOf(burn) - beforeBalance != cost) revert InvalidValue();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/incorrect-strict-equality\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:325:14\n    │\n325 │         if (!rewards.checkpoint(64) || !rewards.settle(player, 64)) revert CatchUpRequired();\n    │              ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:325:41\n    │\n325 │         if (!rewards.checkpoint(64) || !rewards.settle(player, 64)) revert CatchUpRequired();\n    │                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:328:9\n    │\n328 │         rewards.spend(player, cost, 0);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/FarmCore.sol:328:9\n    │\n328 │         rewards.spend(player, cost, 0);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:332:14\n    │\n332 │         if (!rewards.checkpoint(64) || !rewards.settle(msg.sender, 64)) revert CatchUpRequired();\n    │              ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:332:41\n    │\n332 │         if (!rewards.checkpoint(64) || !rewards.settle(msg.sender, 64)) revert CatchUpRequired();\n    │                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:359:9\n    │\n359 │         rewards.spend(msg.sender, nominal, kind == SpendKind.TokenPack ? params.get(Params.Key.TokenRecycleBps) : 0);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:360:39\n    │\n360 │         if (kind == SpendKind.Repair) rewards.repair(msg.sender, units);\n    │                                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:361:44\n    │\n361 │         if (kind == SpendKind.Electricity) rewards.prepay(msg.sender, nominal);\n    │                                            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:365:13\n    │\n365 │             grid.tokenLobby(msg.sender, Math.mulDiv(nominal, 1 ether, tokensPerETH));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmCore.sol:367:42\n    │\n367 │         if (kind == SpendKind.TokenPack) packs.tokenPack(msg.sender);\n    │                                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/FarmCore.sol:342:27\n    │\n342 │                 nominal = nominal * 14 / 10;\n    │                           ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/FarmCore.sol:369:9\n    │\n369 │         emit Spent(msg.sender, kind, nominal);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/FarmCore.sol:359:9\n    │\n359 │         rewards.spend(msg.sender, nominal, kind == SpendKind.TokenPack ? params.get(Params.Key.TokenRecycleBps) : 0);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/FarmCore.sol:367:42\n    │\n367 │         if (kind == SpendKind.TokenPack) packs.tokenPack(msg.sender);\n    │                                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[missing-events-arithmetic]: `tickInspectionBps` is changed without an event but is used in arithmetic\n    ╭▸ src/FarmRewards.sol:132:17\n    │\n132 │                 tickInspectionBps = params.get(Params.Key.InspectionBps);\n    │                 ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-arithmetic\n\nwarning[missing-events-arithmetic]: `tickPoolCap` is changed without an event but is used in arithmetic\n    ╭▸ src/FarmRewards.sol:135:17\n    │\n135 │                 tickPoolCap = available * 500 / 20000;\n    │                 ━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-arithmetic\n\nwarning[missing-events-arithmetic]: `tickPoolBudget` is changed without an event but is used in arithmetic\n    ╭▸ src/FarmRewards.sol:137:17\n    │\n137 │                 tickPoolBudget = Math.min(wanted, tickPoolCap);\n    │                 ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-arithmetic\n\nwarning[missing-events-arithmetic]: `tickRedisBudget` is changed without an event but is used in arithmetic\n    ╭▸ src/FarmRewards.sol:138:17\n    │\n138 │                 tickRedisBudget = redistribution;\n    │                 ━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-arithmetic\n\nwarning[missing-events-arithmetic]: `lastCheckpoint` is changed without an event but is used in arithmetic\n    ╭▸ src/FarmRewards.sol:157:13\n    │\n157 │             lastCheckpoint = end;\n    │             ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-arithmetic\n\nwarning[missing-events-arithmetic]: `rpsEMA` is changed without an event but is used in arithmetic\n    ╭▸ src/FarmRewards.sol:168:41\n    │\n168 │                     if (totalHash != 0) rpsEMA = rpsEMA * 7 / 10 + Math.mulDiv(dayEmission, 1e18, totalHash) * 3 / 10;\n    │                                         ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-arithmetic\n\nwarning[missing-events-arithmetic]: `totalHash` is changed without an event but is used in arithmetic\n    ╭▸ src/FarmRewards.sol:339:13\n    │\n339 │             totalHash -= a.hashes[i];\n    │             ━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-arithmetic\n\nwarning[reentrancy-no-eth]: external call can be reentered before `lastCheckpoint` is updated\n    ╭▸ src/FarmRewards.sol:187:9\n    │\n187 │         pool.reserve(a.fresh);\n    │         ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `lastCheckpoint` is updated\n    ╭▸ src/FarmRewards.sol:189:13\n    │\n189 │             pool.recycle(a.fresh + a.reused - a.gross - a.referral - a.prize);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `lastCheckpoint` is updated\n    ╭▸ src/FarmRewards.sol:216:13\n    │\n216 │             pool.pay(burnVault, a.auditBurn);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `lastCheckpoint` is updated\n    ╭▸ src/FarmRewards.sol:217:13\n    │\n217 │             pool.recycle(a.miningAuditBurn * 500 / 10000);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FarmRewards.sol:122:28\n    │\n122 │         for (uint256 step; step < maxTicks && lastCheckpoint < block.timestamp; ++step) {\n    │                            ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FarmRewards.sol:147:41\n    │\n147 │                 if (bucketHash[b] != 0) weighted += bucketHash[b] * grid.weight(b, lastCheckpoint) / 10000;\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/FarmRewards.sol:121:13\n    │\n121 │         if (block.timestamp <= lastCheckpoint) return true;\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/FarmRewards.sol:122:47\n    │\n122 │         for (uint256 step; step < maxTicks && lastCheckpoint < block.timestamp; ++step) {\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/FarmRewards.sol:129:17\n    │\n129 │             if (end > block.timestamp) end = block.timestamp;\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/FarmRewards.sol:158:17\n    │\n158 │             if (end == launchTime + (tick + 1) * TICK) {\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/FarmRewards.sol:173:16\n    │\n173 │         return lastCheckpoint >= block.timestamp;\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmRewards.sol:126:49\n    │\n126 │                 inspectionMinHashInWeek[week] = params.get(Params.Key.InspectionMinHash);\n    │                                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmRewards.sol:131:37\n    │\n131 │                 uint256 available = pool.available();\n    │                                     ━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmRewards.sol:132:37\n    │\n132 │                 tickInspectionBps = params.get(Params.Key.InspectionBps);\n    │                                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmRewards.sol:134:33\n    │\n134 │                     available * params.get(Params.Key.EmissionBps) * (10500 + tickInspectionBps) / 200_000_000;\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmRewards.sol:147:69\n    │\n147 │                 if (bucketHash[b] != 0) weighted += bucketHash[b] * grid.weight(b, lastCheckpoint) / 10000;\n    │                                                                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmRewards.sol:178:65\n    │\n178 │             tickPoolCap - tickPoolUsed, tickPoolBudget * a.dt * grid.emissionBps(lastCheckpoint) / (TICK * 10000)\n    │                                                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmRewards.sol:187:9\n    │\n187 │         pool.reserve(a.fresh);\n    │         ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmRewards.sol:189:13\n    │\n189 │             pool.recycle(a.fresh + a.reused - a.gross - a.referral - a.prize);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmRewards.sol:203:51\n    │\n203 │                 uint256 weight_ = bucketHash[b] * grid.weight(b, lastCheckpoint);\n    │                                                   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmRewards.sol:206:43\n    │\n206 │                 uint256 penalty = 10000 - grid.rewardBps(b, lastCheckpoint);\n    │                                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmRewards.sol:216:13\n    │\n216 │             pool.pay(burnVault, a.auditBurn);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmRewards.sol:217:13\n    │\n217 │             pool.recycle(a.miningAuditBurn * 500 / 10000);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmRewards.sol:196:54\n    │\n196 │         powerAcc += Math.mulDiv(rpsEMA * 1e9, a.dt * params.get(Params.Key.TariffBps), 1 days * 10000);\n    │                                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/FarmRewards.sol:197:9\n    │\n197 │         emit Emission(a.tick, a.gross, a.gross + a.referral + a.prize);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/FarmRewards.sol:310:13\n    │\n310 │             emit Settled(player, gross, burn, net, day);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FarmRewards.sol:276:17\n    │\n276 │                 mining += Math.mulDiv(a.hashes[i], miningIndex - a.miningDebts[i], ACC);\n    │                 ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FarmRewards.sol:273:17\n    │\n273 │                 gross += Math.mulDiv(a.hashes[i], index - a.debts[i], ACC);\n    │                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FarmRewards.sol:264:25\n    │\n264 │         for (uint256 j; j < maxDays && a.cursor < lastCheckpoint; ++j) {\n    │                         ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmRewards.sol:301:31\n    │\n301 │             if (recycle != 0) pool.recycle(recycle);\n    │                               ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmRewards.sol:302:28\n    │\n302 │             if (burn != 0) pool.pay(burnVault, burn);\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/FarmRewards.sol:355:41\n    │\n355 │         if (amount > type(uint192).max) revert InvalidValue();\n    │                                         ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[reentrancy-no-eth]: external call can be reentered before `bucketHash` is updated\n    ╭▸ src/FarmRewards.sol:301:31\n    │\n301 │             if (recycle != 0) pool.recycle(recycle);\n    │                               ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `bucketHash` is updated\n    ╭▸ src/FarmRewards.sol:302:28\n    │\n302 │             if (burn != 0) pool.pay(burnVault, burn);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/FarmRewards.sol:326:9\n    │\n326 │         nonReentrant\n    │         ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/FarmRewards.sol:340:36\n    │\n340 │             if (buckets[i] >= 128) revert InvalidValue();\n    │                                    ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/FarmRewards.sol:358:27\n    │\n358 │         uint256 current = block.timestamp < launchTime ? 0 : (block.timestamp - launchTime) / 1 days;\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/FarmRewards.sol:359:13\n    │\n359 │         if (day + 16 <= current) {\n    │             ━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FarmRewards.sol:368:17\n    │\n368 │         v.day = uint64(day);\n    │                 ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' 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/FarmRewards.sol:369:21\n    │\n369 │         v.amount += uint192(amount);\n    │                     ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint192' 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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/FarmRewards.sol:378:17\n    │\n378 │             if (uint256(v.day) + 16 <= current) {\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/FarmRewards.sol:388:25\n    │\n388 │         uint256 first = current > 15 ? current - 15 : 0;\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/FarmRewards.sol:389:35\n    │\n389 │         for (uint256 day = first; day <= current && amount != 0; ++day) {\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/FarmRewards.sol:391:17\n    │\n391 │             if (v.day != day) continue;\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/FarmRewards.sol:397:31\n    │\n397 │                 uint256 age = block.timestamp > vintageEnd ? block.timestamp - vintageEnd : 0;\n    │                               ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmRewards.sol:405:25\n    │\n405 │         uint256 floor = params.get(Params.Key.TaxFloorBps);\n    │                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmRewards.sol:406:25\n    │\n406 │         uint256 start = params.get(Params.Key.TaxDay0Bps);\n    │                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FarmRewards.sol:407:24\n    │\n407 │         uint256 span = params.get(Params.Key.TaxDecaySeconds);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FarmRewards.sol:393:25\n    │\n393 │             v.amount -= uint192(used);\n    │                         ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint192' 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[reentrancy-no-eth]: external call can be reentered before `redistribution` is updated\n    ╭▸ src/FarmRewards.sol:301:31\n    │\n301 │             if (recycle != 0) pool.recycle(recycle);\n    │                               ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `redistribution` is updated\n    ╭▸ src/FarmRewards.sol:302:28\n    │\n302 │             if (burn != 0) pool.pay(burnVault, burn);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmRewards.sol:418:9\n    │\n418 │         pool.pay(msg.sender, net);\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/FarmRewards.sol:419:9\n    │\n419 │         emit Claimed(msg.sender, amount, tax);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `burnInWeek` is updated\n    ╭▸ src/FarmRewards.sol:434:28\n    │\n434 │         if (recycled != 0) pool.recycle(recycled);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `burnInWeek` is updated\n    ╭▸ src/FarmRewards.sol:435:26\n    │\n435 │         if (burned != 0) pool.pay(burnVault, burned);\n    │                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmRewards.sol:301:31\n    │\n301 │             if (recycle != 0) pool.recycle(recycle);\n    │                               ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmRewards.sol:302:28\n    │\n302 │             if (burn != 0) pool.pay(burnVault, burn);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/FarmRewards.sol:425:9\n    │\n425 │         nonReentrant\n    │         ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/FarmRewards.sol:437:9\n    │\n437 │         emit Spent(player, consumed, burned);\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/FarmRewards.sol:462:13\n    │\n462 │         if (block.timestamp < end || block.timestamp >= end + 1 days) revert TooEarly();\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/FarmRewards.sol:462:38\n    │\n462 │         if (block.timestamp < end || block.timestamp >= end + 1 days) revert TooEarly();\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/FarmRewards.sol:474:13\n    │\n474 │             emit InspectionCandidate(week, player, score);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/FarmRewards.sol:486:29\n    │\n486 │             if (prize != 0) pool.recycle(prize);\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/FarmRewards.sol:479:13\n    │\n479 │         if (block.timestamp < launchTime + (week + 1) * 7 days + 1 days) revert TooEarly();\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/FarmRewards.sol:490:9\n    │\n490 │         emit InspectionPaid(week, winner, prize);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\n","passed":true},{"durationMs":5254,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/fork/RobinhoodFork.t.sol:RobinhoodForkTest\n[SKIP] testForkArbSysAndHistoricalHash() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 156.66µs (69.28µs CPU time)\n\nRan 2 tests for test/Clock.t.sol:ClockTest\n[PASS] testLocalEvmFutureBlockAnd256BlockBoundary() (gas: 220367)\n[PASS] testRobinhoodUsesArbSysNotL1EstimateAndHandlesExpiry() (gas: 443925)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 417.50µs (260.26µs CPU time)\n\nRan 4 tests for test/Deployment.t.sol:DeploymentTest\n[PASS] testEmptyChainConstructorsDoNotCallDependencies() (gas: 13799)\n[PASS] testNoAdminMintOrPoolDrain() (gas: 161782)\n[PASS] testRejectInvalidConfiguration() (gas: 44406)\n[PASS] testWiringAndRuntimeLimits() (gas: 85651)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 3.31ms (1.04ms CPU time)\n\nRan 5 tests for test/ExtraBehavior.t.sol:ExtraBehaviorTest\n[PASS] testAllPoolSpendingUnderAuditRemainsBacked() (gas: 11583991)\n[PASS] testLongerTaxDecayCannotLoseAgedVintageOnRingRollover() (gas: 16109668)\n[PASS] testMergeMintsOnlyThroughPackSaleAndConsumesThreeWithFee() (gas: 5407673)\n[PASS] testPackBuybackBootstrapsMiningWithoutAnInitialDonation() (gas: 3316524)\n[PASS] testRedistributionIsFullyAddedAndNotTaxedForReferralAgain() (gas: 5441508)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 12.40ms (19.89ms CPU time)\n\nRan 2 tests for test/Factory.t.sol:FactoryTest\n[PASS] testFactoryInvalidSearchRange() (gas: 5114)\n[PASS] testHookFactoryFlagsImmutableConfigAndIdempotence() (gas: 5376033)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 12.45ms (10.45ms CPU time)\n\nRan 8 tests for test/Packs.t.sol:PacksTest\n[PASS] testBetaCapsAndExactRollingDay() (gas: 827562)\n[PASS] testExpiredPackCommonAndCommitEpochFixed() (gas: 21141145)\n[PASS] testGlobalBetaCap() (gas: 7324127)\n[PASS] testPackInvalidCountPaymentAndUnknownId() (gas: 240388)\n[PASS] testPaidPackRoutesFeesAndPermissionlessResolve() (gas: 1261825)\n[PASS] testPauseOnlySwarmBoundedAndCannotExtend() (gas: 1424722)\n[PASS] testStarterBecomesFullHashOnlyAfterPaidReveal() (gas: 1522668)\n[PASS] testStarterProofWindowExpiryAndSoulbound() (gas: 3518835)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 16.47ms (20.87ms CPU time)\n\nRan 6 tests for test/Market.t.sol:MarketTest\n[PASS] testBuyChargesOnlyBaseAndNetworkPullPayment() (gas: 279894)\n[PASS] testFuzzTotalFeeHardCap(uint96) (runs: 256, μ: 1879015, ~: 1886237)\nLogs:\n  Bound result 5308\n\n[PASS] testOnlyManagerCorrectPoolExactInputAndHookAddress() (gas: 112604)\n[PASS] testSingleDumpIncludesItselfAndFeeDecaysWithoutGriefReset() (gas: 16470509)\n[PASS] testTwapAveragesEthPriceAcrossUnequalPrices() (gas: 2434526)\n[PASS] testTwapWarmupAndFlashManipulationResistance() (gas: 1955052)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 24.51ms (31.75ms CPU time)\n\nRan 3 tests for test/V4Integration.t.sol:V4IntegrationTest\n[PASS] testRealV4BuyAndSingleSwapSellTaxConserveSettlement() (gas: 2244100)\n[PASS] testRealV4ManipulatedSpotCannotInstantlySetBuybackQuote() (gas: 1917469)\n[PASS] testRealV4SystemBuyUsesTwapAndOnlySystemFunds() (gas: 2290035)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 26.81ms (1.24ms CPU time)\n\nRan 7 tests for test/Adversarial.t.sol:AdversarialTest\n[PASS] testERC1155ReceiverCannotReenterResolution() (gas: 1365037)\n[PASS] testERC20CallbackCannotReenterClaimAndFailureRollsBackLiabilities() (gas: 3691777)\n[PASS] testEthWithdrawalReentrancyAndRecipientFailureIsolation() (gas: 655542)\n[PASS] testLongInactiveFarmCanBeRemovedAndRepairedFromWallet() (gas: 50106434)\n[PASS] testMintBonusIsFrozenAcrossParameterUpdatesAndDelayedResolve() (gas: 7306457)\n[PASS] testSupplyMetadataAndMintEditionRestrictions() (gas: 103431)\n[PASS] testSwarmCanResumeEventsAfterLongOutage() (gas: 2090627)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 98.47ms (43.80ms CPU time)\n\nRan 8 tests for test/Rooms.t.sol:RoomsTest\n[PASS] testAllSixMineAlone() (gas: 2996847)\n[PASS] testDirectUntrackedDepositRejected() (gas: 126864)\n[PASS] testFullCommonSetAndPairs() (gas: 2995045)\n[PASS] testFuzzSetCap(uint8) (runs: 256, μ: 3028666, ~: 3044303)\nLogs:\n  Bound result 0\n\n[PASS] testPartialRarityBonusesAndNoCrossRoomSet() (gas: 2825834)\n[PASS] testRareEpicLegendarySetCap() (gas: 8169526)\n[PASS] testRoomKeyCannotLeaveOccupiedRoomAndCanReturn() (gas: 1253003)\n[PASS] testRoomSlotTypeOwnershipAndNoDoublePlacement() (gas: 2193391)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 107.78ms (123.36ms CPU time)\n\nRan 9 tests for test/Operations.t.sol:OperationsTest\n[PASS] testBlackoutRollingMaximumAndDistrictCooldown() (gas: 8725546)\n[PASS] testBuybackQuoteSlippageSpacingAndFailureAtomicity() (gas: 1308677)\n[PASS] testEveryParameterRejectsHardBoundAndExcessStep() (gas: 3647569)\n[PASS] testFeeSplitsEveryStreamAndPullRecipientRotation() (gas: 553343)\n[PASS] testFuzzParamCannotExceedTenPercent(uint16) (runs: 256, μ: 45923, ~: 45971)\nLogs:\n  Bound result 153\n\n[PASS] testGeneratorLockUnlockPrincipalAndPauseIsolation() (gas: 12223509)\n[PASS] testGridRoleFutureBlockExpiryAndHerald() (gas: 2606526)\n[PASS] testLobbyDecayFloorSnapshotAndCalmFallback() (gas: 3385368)\n[PASS] testParamsRoleStepBoundsAnd24Hours() (gas: 1834500)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 469.56ms (39.86ms CPU time)\n\nRan 13 tests for test/Rewards.t.sol:RewardsTest\n[PASS] testClaimsWithdrawalsAndItemExitDuringPause() (gas: 3749050)\n[PASS] testFIFOConsumesOldBeforeFresh() (gas: 10732823)\n[PASS] testFuzzConservation(uint96,uint32) (runs: 256, μ: 14635098, ~: 10994414)\nLogs:\n  Bound result 99999999000000000000006473\n  Bound result 2588418\n\n[PASS] testInspectionWindowWinnerPayoutAndNoDoublePay() (gas: 13595089)\n[PASS] testLongIdleCatchupIsPermissionlessAndBounded() (gas: 95456713)\n[PASS] testMiningClaimTaxAndConservation() (gas: 3447214)\n[PASS] testNoFreeUpgradeBeforeRewardsExist() (gas: 742564)\n[PASS] testOldRewardsKeepVintageWithoutDailyCalls() (gas: 9949561)\n[PASS] testReferralOnceNotSelfAndNoCyclesOrRetroactiveReferral() (gas: 4267506)\n[PASS] testRepairUpgradeAndTokenPackSpend() (gas: 7823990)\n[PASS] testReservedUnclaimedCannotBeEmittedAgain() (gas: 5248486)\n[PASS] testSpendingBonusBurnAndNoWithdrawalTax() (gas: 4547211)\n[PASS] testZeroHashDoesNotEmitAndDonationIsPermissionless() (gas: 1799756)\nSuite result: ok. 13 passed; 0 failed; 0 skipped; finished in 487.63ms (577.24ms CPU time)\n\nRan 1 test for test/Invariants.t.sol:InvariantsTest\n[PASS]\nInvariantsTest invariants:\n[PASS] invariantHashAndCustodyConserved\n[PASS] invariantTokensConservedAndPendingFullyBacked\n InvariantsTest invariants (runs: 128, calls: 8192, reverts: 0)\n\n╭----------------+-----------------+-------+---------+----------╮\n| Contract       | Selector        | Calls | Reverts | Discards |\n+===============================================================+\n| EconomyHandler | advance         | 1639  | 0       | 0        |\n|----------------+-----------------+-------+---------+----------|\n| EconomyHandler | claim           | 1664  | 0       | 0        |\n|----------------+-----------------+-------+---------+----------|\n| EconomyHandler | donate          | 1681  | 0       | 0        |\n|----------------+-----------------+-------+---------+----------|\n| EconomyHandler | placeOrWithdraw | 1611  | 0       | 0        |\n|----------------+-----------------+-------+---------+----------|\n| EconomyHandler | prepay          | 1597  | 0       | 0        |\n╰----------------+-----------------+-------+---------+----------╯\n\nLogs:\n  Bound result 65536\n  Bound result 10000\n  Bound result 4042\n  Bound result 5844\n  Bound result 953\n  Bound result 200\n  Bound result 13685\n  Bound result 2402\n  Bound result 3768\n  Bound result 150\n  Bound result 1361855929560191779023355\n  Bound result 600\n  Bound result 2767\n  Bound result 14493\n  Bound result 2779\n  Bound result 111903942\n  Bound result 4147\n  Bound result 4100\n  Bound result 139968\n  Bound result 13602\n  Bound result 200\n  Bound result 1034\n  Bound result 7598\n  Bound result 172800\n  Bound result 8028\n  Bound result 350\n  Bound result 1096477349\n  Bound result 5231\n  Bound result 16052\n  Bound result 6842269768458482323208733\n  Bound result 1300\n  Bound result 74478\n  Bound result 849\n  Bound result 60\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 5.13s (5.13s CPU time)\n\nRan 13 test suites in 5.14s (6.39s CPU time): 68 tests passed, 0 failed, 1 skipped (69 total tests)\n","passed":true},{"durationMs":90,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"FarmCore.chargeMerge(address,uint256)\",\"FarmCore.installRoom(uint256,uint256)\",\"FarmCore.paidPackOpened(address,uint256)\",\"FarmCore.payMaintenance(bool,uint256)\",\"FarmCore.place(uint256,uint256,uint256)\",\"FarmCore.refresh(address)\",\"FarmCore.register(address)\",\"FarmCore.removeRoom(uint256)\",\"FarmCore.setReferrer(address)\",\"FarmCore.spend(uint8,uint256,uint256,uint256)\",\"FarmCore.unplace(uint256,uint256)\",\"FarmItems.burnForMerge(address,uint256)\",\"FarmItems.mint(address,uint256)\",\"FarmItems.safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\",\"FarmItems.safeTransferFrom(address,address,uint256,uint256,bytes)\",\"FarmItems.setApprovalForAll(address,bool)\",\"FarmRewards.checkpoint(uint256)\",\"FarmRewards.claim(uint256)\",\"FarmRewards.finalizeInspection(uint256)\",\"FarmRewards.prepay(address,uint256)\",\"FarmRewards.recordWalletSpend(address,uint256)\",\"FarmRewards.repair(address,uint256)\",\"FarmRewards.setReferrer(address,address)\",\"FarmRewards.settle(address,uint256)\",\"FarmRewards.spend(address,uint256,uint256)\",\"FarmRewards.submitInspection(uint256,address)\",\"FarmRewards.update(address,uint8[5],uint256[5],uint256)\",\"FeeRouter.changeTeam(address)\",\"FeeRouter.depositBaseFee()\",\"FeeRouter.depositLobby()\",\"FeeRouter.depositPack()\",\"FeeRouter.depositSellTax()\",\"FeeRouter.executeBuys(bool,uint256,uint256)\",\"FeeRouter.receive()\",\"FeeRouter.withdraw()\",\"Generator.lock(uint256)\",\"Generator.unlock()\",\"GridOperator.calmTick(uint256)\",\"GridOperator.lobby()\",\"GridOperator.postHerald(bytes32,string)\",\"GridOperator.resolveEvent(uint256)\",\"GridOperator.submitEvent(uint256,uint8)\",\"GridOperator.tokenLobby(address,uint256)\",\"MarketFactory.deploy((address,address,address,address,address,int24),bytes32)\",\"PackSale.merge(uint256)\",\"PackSale.openPack(uint256)\",\"PackSale.pause(uint256)\",\"PackSale.resolve(uint256)\",\"PackSale.tokenPack(address)\",\"Params.set(uint8,uint256)\",\"RewardPool.donate(uint256)\",\"RewardPool.pay(address,uint256)\",\"RewardPool.recycle(uint256)\",\"RewardPool.reserve(uint256)\",\"StarterClaim.claim(uint256,bytes32[])\",\"StarterClaim.resolve(uint256)\",\"V4Market.afterInitialize(address,(address,address,uint24,int24,address),uint160,int24)\",\"V4Market.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"V4Market.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"V4Market.buy(uint256,address)\",\"V4Market.receive()\",\"V4Market.unlockCallback(bytes)\",\"V4Market.withdrawNetwork()\"],\"files\":{\".gitignore\":6,\"README.md\":108,\"artifacts/foundry-tests.txt\":178,\"artifacts/offline-tests.txt\":187,\"artifacts/offline-verification.json\":21,\"artifacts/robinhood-fork.txt\":7,\"artifacts/rpc-probe.json\":16,\"artifacts/runtime-sizes.json\":21,\"artifacts/simulation.md\":95,\"artifacts/verification.json\":110,\"docs/dependency-provenance.md\":9,\"docs/design.md\":120,\"docs/security-review.md\":29,\"docs/simulation-assumptions.md\":52,\"foundry.toml\":20,\"report.md\":75,\"script/Deploy.s.sol\":91,\"script/DeployMarket.s.sol\":25,\"sim/blackout_sim_v2.py\":509,\"src/BurnVault.sol\":5,\"src/FarmCore.sol\":394,\"src/FarmItems.sol\":66,\"src/FarmRewards.sol\":492,\"src/FeeRouter.sol\":131,\"src/Generator.sol\":51,\"src/GridOperator.sol\":240,\"src/MarketFactory.sol\":60,\"src/PackSale.sol\":202,\"src/Params.sol\":146,\"src/RewardPool.sol\":59,\"src/StarterClaim.sol\":82,\"src/V4Market.sol\":307,\"src/interfaces/IV4.sol\":25,\"src/interfaces/Interfaces.sol\":36,\"src/lib/ChainClock.sol\":22,\"src/lib/Errors.sol\":12,\"src/lib/ItemMath.sol\":49,\"test/Adversarial.t.sol\":164,\"test/Base.t.sol\":92,\"test/Clock.t.sol\":50,\"test/Deployment.t.sol\":56,\"test/ExtraBehavior.t.sol\":127,\"test/Factory.t.sol\":31,\"test/Invariants.t.sol\":110,\"test/Market.t.sol\":109,\"test/Operations.t.sol\":200,\"test/Packs.t.sol\":156,\"test/Rewards.t.sol\":228,\"test/Rooms.t.sol\":127,\"test/V4Integration.t.sol\":134,\"test/fork/RobinhoodFork.t.sol\":39,\"test/mocks/MockMarket.sol\":37,\"test/mocks/MockToken.sol\":38,\"test/mocks/MockV4Manager.sol\":64,\"test/python/test_merkle.py\":19,\"tools/starter_merkle.py\":72},\"excluded\":[\"vendor/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":24385,"exitCode":0,"name":"slither","output":"[high/medium] weak-prng at src/V4Market.sol:154: V4Market._record(bool,uint256) (src/V4Market.sol#154-175) uses a weak PRNG: \"b = longVolumes[p % 24] (src/V4Market.sol#163)\"\n[high/medium] weak-prng at src/V4Market.sol:154: V4Market._record(bool,uint256) (src/V4Market.sol#154-175) uses a weak PRNG: \"delete longVolumes[p % 24] (src/V4Market.sol#165)\"\n[high/medium] weak-prng at src/FarmRewards.sol:372: FarmRewards._consume(address,uint256,bool) (src/FarmRewards.sol#372-402) uses a weak PRNG: \"v_scope_0 = a.vintages[day % 16] (src/FarmRewards.sol#390)\"\n[high/medium] weak-prng at src/V4Market.sol:154: V4Market._record(bool,uint256) (src/V4Market.sol#154-175) uses a weak PRNG: \"delete shortVolumes[p % 12] (src/V4Market.sol#159)\"\n[high/medium] weak-prng at src/V4Market.sol:154: V4Market._record(bool,uint256) (src/V4Market.sol#154-175) uses a weak PRNG: \"a = shortVolumes[p % 12] (src/V4Market.sol#157)\"\n[high/medium] weak-prng at src/PackSale.sol:141: PackSale._commit(address,uint256) (src/PackSale.sol#141-171) uses a weak PRNG: \"h = hourBuckets[hour % 25] (src/PackSale.sol#145)\"\n[high/medium] weak-prng at src/V4Market.sol:134: V4Market._cumulativeAt(uint256) (src/V4Market.sol#134-141) uses a weak PRNG: \"o = observations[minute % 32] (src/V4Market.sol#138)\"\n[high/medium] weak-prng at src/FarmRewards.sol:354: FarmRewards._credit(address,uint256,uint256) (src/FarmRewards.sol#354-370) uses a weak PRNG: \"v = a.vintages[day % 16] (src/FarmRewards.sol#363)\"\n[high/medium] weak-prng at src/FarmRewards.sol:119: FarmRewards._checkpoint(uint256) (src/FarmRewards.sol#119-174) uses a weak PRNG: \"(tick + 1) % 2 == 0 (src/FarmRewards.sol#161)\"\n[high/medium] weak-prng at src/V4Market.sol:112: V4Market._observe(uint256) (src/V4Market.sol#112-132) uses a weak PRNG: \"observations[minute % 32] = Observation(uint64(minute),c) (src/V4Market.sol#126)\"\n[high/medium] incorrect-exp at vendor/openzeppelin/contracts/utils/math/Math.sol:123: Math.mulDiv(uint256,uint256,uint256) (vendor/openzeppelin/contracts/utils/math/Math.sol#123-202) has bitwise-xor operator ^ instead of the exponentiation operator **: \n[high/medium] reentrancy-balance at src/Generator.sol:29: Reentrancy in Generator.lock(uint256) (src/Generator.sol#29-39):\n[high/medium] reentrancy-balance at src/FeeRouter.sol:108: Reentrancy in FeeRouter.executeBuys(bool,uint256,uint256) (src/FeeRouter.sol#108-130):\n[high/medium] reentrancy-balance at src/FarmCore.sol:301: Reentrancy in FarmCore.payMaintenance(bool,uint256) (src/FarmCore.sol#301-321):\n[high/medium] reentrancy-balance at src/RewardPool.sol:33: Reentrancy in RewardPool.donate(uint256) (src/RewardPool.sol#33-40):\n[medium/medium] divide-before-multiply at vendor/openzeppelin/contracts/utils/Base64.sol:18: Base64.encode(bytes) (vendor/openzeppelin/contracts/utils/Base64.sol#18-94) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at src/V4Market.sol:134: V4Market._cumulativeAt(uint256) (src/V4Market.sol#134-141) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at vendor/openzeppelin/contracts/utils/math/Math.sol:123: Math.mulDiv(uint256,uint256,uint256) (vendor/openzeppelin/contracts/utils/math/Math.sol#123-202) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at src/FarmCore.sol:331: FarmCore.spend(FarmCore.SpendKind,uint256,uint256,uint256) (src/FarmCore.sol#331-370) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at vendor/openzeppelin/contracts/utils/math/Math.sol:123: Math.mulDiv(uint256,uint256,uint256) (vendor/openzeppelin/contracts/utils/math/Math.sol#123-202) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at src/StarterClaim.sol:45: StarterClaim.claim(uint256,bytes32[]) (src/StarterClaim.sol#45-62) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at vendor/openzeppelin/contracts/utils/math/Math.sol:123: Math.mulDiv(uint256,uint256,uint256) (vendor/openzeppelin/contracts/utils/math/Math.sol#123-202) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at src/V4Market.sol:112: V4Market._observe(uint256) (src/V4Market.sol#112-132) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at vendor/openzeppelin/contracts/utils/math/Math.sol:123: Math.mulDiv(uint256,uint256,uint256) (vendor/openzeppelin/contracts/utils/math/Math.sol#123-202) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at vendor/openzeppelin/contracts/utils/math/Math.sol:123: Math.mulDiv(uint256,uint256,uint256) (vendor/openzeppelin/contracts/utils/math/Math.sol#123-202) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at src/GridOperator.sol:210: GridOperator.weight(uint256,uint256) (src/GridOperator.sol#210-227) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at src/V4Market.sol:112: V4Market._observe(uint256) (src/V4Market.sol#112-132) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at vendor/openzeppelin/contracts/utils/math/Math.sol:123: Math.mulDiv(uint256,uint256,uint256) (vendor/openzeppelin/contracts/utils/math/Math.sol#123-202) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at src/FarmCore.sol:206: FarmCore.itemHash(address,uint256,uint256) (src/FarmCore.sol#206-212) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at vendor/openzeppelin/contracts/utils/math/Math.sol:123: Math.mulDiv(uint256,uint256,uint256) (vendor/openzeppelin/contracts/utils/math/Math.sol#123-202) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at vendor/openzeppelin/contracts/utils/math/Math.sol:123: Math.mulDiv(uint256,uint256,uint256) (vendor/openzeppelin/contracts/utils/math/Math.sol#123-202) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at src/StarterClaim.sol:45: StarterClaim.claim(uint256,bytes32[]) (src/StarterClaim.sol#45-62) performs a multiplication on the result of a division:\n[medium/high] incorrect-equality at src/FarmRewards.sol:119: FarmRewards._checkpoint(uint256) (src/FarmRewards.sol#119-174) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/FarmRewards.sol:260: FarmRewards._settle(address,uint256) (src/FarmRewards.sol#260-313) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/V4Market.sol:200: V4Market._sellFee(uint256) (src/V4Market.sol#200-214) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/V4Market.sol:112: V4Market._observe(uint256) (src/V4Market.sol#112-132) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/FarmRewards.sol:119: FarmRewards._checkpoint(uint256) (src/FarmRewards.sol#119-174) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/FarmRewards.sol:260: FarmRewards._settle(address,uint256) (src/FarmRewards.sol#260-313) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/V4Market.sol:143: V4Market.twap() (src/V4Market.sol#143-148) uses a dangerous strict equality:\n[medium/medium] reentrancy-no-eth at src/FarmRewards.sol:119: Reentrancy in FarmRewards._checkpoint(uint256) (src/FarmRewards.sol#119-174):\n[medium/medium] reentrancy-no-eth at src/FarmRewards.sol:323: Reentrancy in FarmRewards.update(address,uint8[5],uint256[5],uint256) (src/FarmRewards.sol#323-352):\n[medium/medium] reentrancy-no-eth at src/V4Market.sol:274: Reentrancy in V4Market.unlockCallback(bytes) (src/V4Market.sol#274-297):\n[medium/medium] reentrancy-no-eth at src/FarmRewards.sol:478: Reentrancy in FarmRewards.finalizeInspection(uint256) (src/FarmRewards.sol#478-491):\n[medium/medium] reentrancy-no-eth at src/GridOperator.sol:159: Reentrancy in GridOperator.resolveEvent(uint256) (src/GridOperator.sol#159-197):\n[medium/medium] reentrancy-no-eth at src/FarmRewards.sol:412: Reentrancy in FarmRewards.claim(uint256) (src/FarmRewards.sol#412-420):\n[medium/medium] reentrancy-no-eth at src/FarmRewards.sol:422: Reentrancy in FarmRewards.spend(address,uint256,uint256) (src/FarmRewards.sol#422-438):\n[medium/medium] reentrancy-no-eth at src/GridOperator.sol:199: Reentrancy in GridOperator.calmTick(uint256) (src/GridOperator.sol#199-208):\n[medium/medium] reentrancy-no-eth at src/FarmRewards.sol:422: Reentrancy in FarmRewards.spend(address,uint256,uint256) (src/FarmRewards.sol#422-438):\n[medium/medium] reentrancy-no-eth at src/FarmRewards.sol:260: Reentrancy in FarmRewards._settle(address,uint256) (src/FarmRewards.sol#260-313):\n[medium/medium] reentrancy-no-eth at src/Params.sol:130: Reentrancy in Params.set(Params.Key,uint256) (src/Params.sol#130-145):\n[medium/medium] uninitialized-local at src/GridOperator.sol:172: GridOperator.resolveEvent(uint256).sum (src/GridOperator.sol#172) is a local variable never initialized\n[medium/medium] uninitialized-local at src/GridOperator.sol:85: GridOperator.lobbyWeight(uint256).mean (src/GridOperator.sol#85) is a local variable never initialized\n[medium/medium] uninitialized-local at src/FarmCore.sol:250: FarmCore._refresh(address).hashes (src/FarmCore.sol#250) is a local variable never initialized\n[medium/medium] uninitialized-local at src/FarmRewards.sol:269: FarmRewards._settle(address,uint256).gross (src/FarmRewards.sol#269) is a local variable never initialized\n[medium/medium] uninitialized-local at src/V4Market.sol:202: V4Market._sellFee(uint256).average (src/V4Market.sol#202) is a local variable never initialized\n[medium/medium] uninitialized-local at src/FarmRewards.sol:150: FarmRewards._checkpoint(uint256).a (src/FarmRewards.sol#150) is a local variable never initialized\n[medium/medium] uninitialized-local at src/FarmCore.sol:253: FarmCore._refresh(address).power (src/FarmCore.sol#253) is a local variable never initialized\n[medium/medium] uninitialized-local at src/FarmCore.sol:252: FarmCore._refresh(address).raw (src/FarmCore.sol#252) is a local variable never initialized\n[medium/medium] uninitialized-local at src/FarmRewards.sol:145: FarmRewards._checkpoint(uint256).weighted (src/FarmRewards.sol#145) is a local variable never initialized\n[medium/medium] uninitialized-local at src/V4Market.sol:178: V4Market.imbalances().s (src/V4Market.sol#178) is a local variable never initialized\n[medium/medium] uninitialized-local at src/FarmRewards.sol:270: FarmRewards._settle(address,uint256).mining (src/FarmRewards.sol#270) is a local variable never initialized\n[medium/medium] uninitialized-local at src/V4Market.sol:179: V4Market.imbalances().b (src/V4Market.sol#179) is a local variable never initialized\n[medium/medium] uninitialized-local at src/StarterClaim.sol:72: StarterClaim.resolve(uint256).ids (src/StarterClaim.sol#72) is a local variable never initialized\n[medium/medium] uninitialized-local at src/FarmCore.sol:218: FarmCore.roomStats(address,uint256).rarities (src/FarmCore.sol#218) is a local variable never initialized\n[medium/medium] uninitialized-local at src/FarmCore.sol:217: FarmCore.roomStats(address,uint256).count (src/FarmCore.sol#217) is a local variable never initialized\n[medium/medium] unused-return at src/FarmCore.sol:136: FarmCore.place(uint256,uint256,uint256) (src/FarmCore.sol#136-157) ignores return value by (kind,None,None,None) = ItemMath.decode(id) (src/FarmCore.sol#139)\n[medium/medium] unused-return at src/FeeRouter.sol:108: FeeRouter.executeBuys(bool,uint256,uint256) (src/FeeRouter.sol#108-130) ignores return value by market.buy{value: ethAmount}(minOut,recipient) (src/FeeRouter.sol#126)\n[medium/medium] unused-return at src/FarmItems.sol:57: FarmItems._update(address,address,uint256[],uint256[]) (src/FarmItems.sol#57-65) ignores return value by (None,None,None,starter) = ItemMath.decode(ids[i]) (src/FarmItems.sol#60)\n[medium/medium] unused-return at src/FarmCore.sol:214: FarmCore.roomStats(address,uint256) (src/FarmCore.sol#214-239) ignores return value by (None,r,None,None) = ItemMath.decode(id) (src/FarmCore.sol#223)\n[medium/medium] unused-return at src/FarmCore.sol:331: FarmCore.spend(FarmCore.SpendKind,uint256,uint256,uint256) (src/FarmCore.sol#331-370) ignores return value by packs.tokenPack(msg.sender) (src/FarmCore.sol#367)\n[medium/medium] unused-return at src/V4Market.sol:274: V4Market.unlockCallback(bytes) (src/V4Market.sol#274-297) ignores return value by manager.settle{value: input}() (src/V4Market.sol#292)\n[medium/medium] unused-return at src/FarmCore.sol:323: FarmCore.chargeMerge(address,uint256) (src/FarmCore.sol#323-329) ignores return value by rewards.spend(player,cost,0) (src/FarmCore.sol#328)\n[medium/medium] unused-return at src/FarmCore.sol:331: FarmCore.spend(FarmCore.SpendKind,uint256,uint256,uint256) (src/FarmCore.sol#331-370) ignores return value by rewards.spend(msg.sender,nominal,params.get(Params.Key.TokenRecycleBps)) (src/FarmCore.sol#359)\n[medium/medium] unused-return at src/FarmItems.sol:21: FarmItems.mint(address,uint256) (src/FarmItems.sol#21-25) ignores return value by (None,None,None,starter) = ItemMath.decode(id) (src/FarmItems.sol#22)\n[medium/medium] unused-return at src/FarmCore.sol:179: FarmCore.installRoom(uint256,uint256) (src/FarmCore.sol#179-191) ignores return value by (kind,None,None,None) = ItemMath.decode(id) (src/FarmCore.sol#181)\n[medium/medium] unused-return at src/FarmCore.sol:206: FarmCore.itemHash(address,uint256,uint256) (src/FarmCore.sol#206-212) ignores return value by (kind,rarity,None,isStarter) = ItemMath.decode(id) (src/FarmCore.sol#207)\n[medium/medium] unused-return at src/FarmCore.sol:331: FarmCore.spend(FarmCore.SpendKind,uint256,uint256,uint256) (src/FarmCore.sol#331-370) ignores return value by rewards.spend(msg.sender,nominal,0) (src/FarmCore.sol#359)\n[low/medium] events-maths at src/FarmRewards.sol:323: FarmRewards.update(address,uint8[5],uint256[5],uint256) (src/FarmRewards.sol#323-352) should emit an event for: \n[low/medium] events-maths at src/V4Market.sol:274: V4Market.unlockCallback(bytes) (src/V4Market.sol#274-297) should emit an event for: \n[low/medium] calls-loop at src/StarterClaim.sol:64: StarterClaim.resolve(uint256) (src/StarterClaim.sol#64-81) has external calls inside a loop: items.mint(c.player,ids[i]) (src/StarterClaim.sol#78)\n[low/medium] calls-loop at src/FarmRewards.sol:119: FarmRewards._checkpoint(uint256) (src/FarmRewards.sol#119-174) has external calls inside a loop: tickInspectionBps = params.get(Params.Key.InspectionBps) (src/FarmRewards.sol#132)\n[low/medium] calls-loop at src/FarmCore.sol:214: FarmCore.roomStats(address,uint256) (src/FarmCore.sol#214-239) has external calls inside a loop: s.bonusBps = Math.min(s.bonusBps,params.get(Params.Key.SetCapBps)) (src/FarmCore.sol#234)\n[low/medium] calls-loop at src/FarmRewards.sol:119: FarmRewards._checkpoint(uint256) (src/FarmRewards.sol#119-174) has external calls inside a loop: tickInspectionBps = params.get(Params.Key.InspectionBps) (src/FarmRewards.sol#132)\n[low/medium] calls-loop at src/FarmRewards.sol:176: FarmRewards._accrue(FarmRewards.Allocation) (src/FarmRewards.sol#176-198) has external calls inside a loop: powerAcc += Math.mulDiv(rpsEMA * 1e9,a.dt * params.get(Params.Key.TariffBps),86400 * 10000) (src/FarmRewards.sol#196)\n[low/medium] calls-loop at src/FarmRewards.sol:176: FarmRewards._accrue(FarmRewards.Allocation) (src/FarmRewards.sol#176-198) has external calls inside a loop: powerAcc += Math.mulDiv(rpsEMA * 1e9,a.dt * params.get(Params.Key.TariffBps),86400 * 10000) (src/FarmRewards.sol#196)\n[low/medium] calls-loop at src/FarmCore.sol:214: FarmCore.roomStats(address,uint256) (src/FarmCore.sol#214-239) has external calls inside a loop: s.bonusBps += params.get(Params.Key.LegendarySetBps) (src/FarmCore.sol#231)\n[low/medium] c","passed":true},{"durationMs":877,"exitCode":0,"name":"aderyn","output":"[high] abi-encode-packed-hash-collision at src/FarmItems.sol:36: `abi.encodePacked()` Hash Collision (2 places)\n[high] contract-locks-ether at src/GridOperator.sol:11: Contract locks Ether without a withdraw function (2 places)\n[high] eth-send-unchecked-address at src/FarmCore.sol:301: ETH transferred without address checks (6 places)\n[high] reentrancy-state-change at src/FarmCore.sol:154: Reentrancy: State change after external call (20 places)\n[high] unprotected-initializer at src/FarmRewards.sol:234: Unprotected initializer (2 places)\n[high] unsafe-casting at src/PackSale.sol:160: Unsafe Casting of integers (2 places)\n[low] costly-loop at src/FarmRewards.sol:122: Costly operations inside loop (12 places)\n[low] division-before-multiplication at src/FarmCore.sol:210: Incorrect Order of Division and Multiplication\n[low] large-numeric-literal at src/FarmCore.sol:210: Large Numeric Literal (75 places)\n[low] literal-instead-of-constant at src/FarmCore.sol:87: Literal Instead of Constant (367 places)\n[low] local-variable-shadowing at src/V4Market.sol:36: Local Variable Shadows State Variable\n[low] non-reentrant-not-first at src/FarmRewards.sol:326: `nonReentrant` is Not the First Modifier (2 places)\n[low] require-revert-in-loop at src/FarmCore.sol:198: Loop Contains `require`/`revert` (18 places)\n[low] state-change-without-event at src/FarmCore.sol:323: State Change Without Event (4 places)\n[low] unchecked-return at src/FarmCore.sol:328: Unchecked Return (7 places)\n[low] uninitialized-local-variable at src/FarmCore.sol:198: Uninitialized Local Variable (21 places)","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"0226bcc687742fe2a63d10e74fbfd1b53ed84d0ec9b781133d7177e770660776","verifiedTreeHash":"3658ec084c9d16687c1b54cdcba4c5fbac0642c0","verifierVersion":"0.1.0+3f1208aa"}]}