{"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":"541703af-3dab-49c2-8429-a3446ec748b5","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":null,"dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"b6503de65ad02f845827887c23da4c3b56ccc5df7a459db263bae6e549d92f7f","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"b6503de65ad02f845827887c23da4c3b56ccc5df7a459db263bae6e549d92f7f","skillId":"build-contract-project","state":"failed"},{"acceptedSubmissionHash":null,"dependsOn":["build_contract_project","write_foundry_tests"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"waiting"},{"acceptedSubmissionHash":null,"dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"73431852439ad3a343f3d2b7db1c43cd363b9f48f9bb51497374a0cf6d50b223","skillId":"write-foundry-tests","tools":[]},"key":"write_foundry_tests","kind":"code","role":"tests","skillHash":"73431852439ad3a343f3d2b7db1c43cd363b9f48f9bb51497374a0cf6d50b223","skillId":"write-foundry-tests","state":"waiting"}],"objective":"Token name: Work\nToken symbol: WORK\n\nRobinhood Chain 4663, Uniswap v4 hook launch paired with IMD (0x5f7bb59365ce557c26dbcaa4ee9d39a4b95b7127). B = 0xc9EAFE33A510a3a3d95A94c4f85AdaF6a3EA12a0 (EOA). Bounded owner changes emit events; every parameter has a view. Not upgradeable.\n\nDEPLOY SHAPE (launch.json deploys only a no-arg token and the hook): src/Work.sol = plain ERC-20 Work/WORK, 18 decimals, constructor() mints 1,000,000,000 to msg.sender, nothing else. src/WorkHook.sol constructor(IPoolManager manager, address token, address owner, int24 tickSpacing) creates WorkersNFT with new (passing token, owner, address(this) as hook), exposed as workers(). launch.json hook constructorArgs [\"$poolManager\",\"$token\",\"0xc9eafe33a510a3a3d95a94c4f85adaf6a3ea12a0\",\"60\"], pool fee 12500, tickSpacing 60. Hook initcode < 49,152 bytes, every runtime < 24,576. foundry.toml (REQUIRED, the launch attestation compiles with it; without it the hook creation code exceeds EIP-3860): optimizer true, runs 200, via_ir true, bytecode_hash \"none\", solc 0.8.26, cancun. No linked libraries (all library functions internal). Tests use vm.getBlockTimestamp()/vm.getBlockNumber().\n\n1) WorkHook: fee 0.75% on buys and sells (on top of the 1.25% pool fee), owner may set 0-8.75%. During the NFT mint 100% to B; after it ends stakerShareBps (default 10000, owner 9000-10000) goes to WorkersNFT stakers, rest to B; all to B if nothing staked. Keeps a 30-min TWAP for buybacks.\n\n2) WorkersNFT (ERC-721 \"Workers\", max 3,333). setCap lowers to >= minted, never up; endMint() ends minting forever; pause() stops minting and WORK accrual for at most 24 h, next pause needs 24 h unpaused; claims, activation, unstake, transfers and burns always work.\n- Mint by PoW: keccak256(abi.encode(DOMAIN, chainid, this, keccak256(abi.encode(anchorHash, prevWork)), msg.sender, nonce)) < target; anchor = ArbSys block hash <= 250 blocks old; 1 mint per block; retarget every 8 mints toward 10 s; target doubles after 300 s idle; starting difficulty and epoch-0 floor 12 bits, 9 epochs of 370 (+3), floor +1 bit per epoch, owner floor +-2.\n- Paid in IMD (transferFrom, no ETH): [0.25,0.5,0.75,1.25,1.75,2.5,3.25,4,5] IMD per epoch, never above 5; owner scales 0.5x-1x only.\n- id = pool[hash % remaining] (swap-and-pop, no reserves, no allowlist, no free or team mint). Overclocked if hash beats target by >= 4 bits: tokenURI baseURI+\"oc/\"+id+\".json\" else baseURI+id+\".json\"; baseURI ipfs://bafybeibmkvtnptsqztdvsm5sh3avormdnfyarbxpgdlcj6bmg37qchhqve/ (owner may update). ERC-4906 events. Standard OpenZeppelin-compatible ERC-721 approvals (approving the owner or self as operator must not revert). ERC-2981 5% to B, max 10%.\n\n3) Money in IMD, each mint: 65% stakers, 25% buyback balance, 10% B (no stakers: that 65% to buyback).\n- Staking: NFT escrowed in the contract 7/14/30 days = 1x/2x/4x, no early exit; claim IMD (mint share + hook fees) by weight, payouts capped at the reserve; unstake returns by plain transfer. Unstaked workers transfer normally (never blocked).\n- buyback(amount): anyone, amount <= 100 IMD and <= balance, once per 60 s, IMD->WORK in the pool with TWAP minimum output, WORK sent to 0x...dEaD; the protocol buyback pays no hook fee and allows 3% slippage below the TWAP quote.\n- Supply: 10% swarm, 70% pool, 20% to B; B deposits 100M WORK mining pool + 50M burn pool via fundPools().\n\n4) After the mint:\n- activate(id): one time, only while mining is open (reverts after releaseMiningRemainder), fee to B (default 0.15 IMD, owner 0-0.5), stays with the token.\n- Passive WORK, no hashing: 8 eras from mint end, era k lasts 7*2^k days and emits 12.5M, split among activated unburned workers (accumulator); claimWork(ids) by holder or staker; unclaimed moves with the token. WORK scheduled while paused or with no activated worker is carried and released at the next unpaused update. After all eras releaseMiningRemainder() (owner, not paused) sends the rest to B.\n- burn(id): unstaked worker for burnPool / minted (fixed at mint end); burned workers stop earning.\n\nSafety: sweep(token) to B for strays but never staker IMD, buyback balance, mining or burn pool. No minting outside PoW, no owner path to user funds.\n\nHook deploy (including the WorkersNFT it creates) must use < 12M gas. Hook tests must run against the real Uniswap v4-core PoolManager (vendored in lib/), not a mock that computes deltas itself.\n\nTests: Foundry incl. fuzz on work checks, retarget, id picking, splits, escrow, hook split, activation, accrual and carry, burn, buyback amount, pause scope, sweep limits; then an adversarial review.","parentJobId":null,"planHash":"03ed43a48ccc905679136f6b70a5f2f87220d0e39b2452db9e8685b4d7bba0fb","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"541703af-3dab-49c2-8429-a3446ec748b5","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-940-src-work-sol-src-workersnft-sol-src-work"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"51221","feedbackHash":"a86e7b619761fbd28c9851beeae94d850ce9aa7b7c22c04789e1f0ddb0aec904","nodeKey":"build_contract_project","submissionHash":"df7e129e26c5956a221ebdcc991359bc73d27a35372556fb004bcc251843ef1f","tag1":"verification:checks","tag2":"acceptance-v2","value":0},{"agentId":"51197","feedbackHash":"68afa8089eed5c2b5fb2b2193ded4ee16834da22106887320920ac608bb91d45","nodeKey":"build_contract_project","submissionHash":"9b8f0feddd2f5be8b2b2f181197bef50956b21d25bda9ba0a0d166986982d36d","tag1":"verification:checks","tag2":"acceptance-v2","value":0},{"agentId":"51180","feedbackHash":"7411ac670ea7da22340fa1122ec02bd8390a5ac6a5fe5259eed3bb316667393f","nodeKey":"build_contract_project","submissionHash":"5ecd309c56113627b95fbd473c964bedf7c5526a65347303982a97d25798e348","tag1":"verification:checks","tag2":"acceptance-v2","value":0}],"site":null,"snapshotHash":"8a0e3893890569e2d2ef5d01210282a1fa7c980e567c53d4881dd55283b660a7","state":"blocked","submissions":[{"artifacts":[],"attempt":3,"bundleHash":"1d6842e7916b36ca8c4eb2330b26b31592d5de90e2e37c50227844b5f85c0055","device":"fef70a876212b4f0","findings":[],"hash":"5ecd309c56113627b95fbd473c964bedf7c5526a65347303982a97d25798e348","nodeId":"fcea41fa-7e55-4c0f-b4d4-cf9e02c384f7","outcome":"completed","summary":"Implemented the contracts, vendored dependencies, corrected `univ4_hook` manifest, tests, and documentation.\n\n- Build, formatting, and all **73 offline tests pass**.\n- Hook plus NFT deployment uses approximately **6.92M gas**.\n- Bytecode limits and unlinked-library checks pass.\n\nSee [README](README.md) and [adversarial review](docs/ADVERSARIAL_REVIEW.md). Independent audit and external launch-schema attestation remain outstanding.","treeHash":"1c82ec9bc6219bdb5608a1ab9d2d732ef5a41cce","usage":{"cachedInputTokens":2420864,"inputTokens":157866,"model":"gpt-6-astra","outputTokens":59188,"runtime":"codex","turns":8,"wallClockMs":2200355}},{"artifacts":[],"attempt":2,"bundleHash":"0ec749dfeb0f08e78886eb2f5feea60e2165fae31d1205178f5885073f56b570","device":"f2d7eadae2a3cfdf","findings":[],"hash":"9b8f0feddd2f5be8b2b2f181197bef50956b21d25bda9ba0a0d166986982d36d","nodeId":"fcea41fa-7e55-4c0f-b4d4-cf9e02c384f7","outcome":"completed","summary":"Implemented contracts, launch manifest, vendored dependencies, tests, and documentation. `fundPools()` now requires B and pulls from `msg.sender`.\n\n- `forge build` passes.\n- All 43 tests pass.\n- `forge fmt --check` passes.\n- Deployment uses 6.05M gas; bytecode meets both limits.\n\n[Deployment documentation](README.md) and [local adversarial review](SECURITY_REVIEW.md) are included. Independent audit remains outstanding.","treeHash":"956f20a9c34d72292915133766bb111de6c78fdb","usage":{"cachedInputTokens":2950784,"inputTokens":125970,"model":"gpt-6-astra","outputTokens":48178,"runtime":"codex","turns":10,"wallClockMs":1901218}},{"artifacts":[],"attempt":1,"bundleHash":"93a85cf3a7283d5185ec8607256c34b71b8fb1e117b5e4a6e2d3c4582d21d557","device":"9d2479a5270b8df1","findings":[],"hash":"df7e129e26c5956a221ebdcc991359bc73d27a35372556fb004bcc251843ef1f","nodeId":"fcea41fa-7e55-4c0f-b4d4-cf9e02c384f7","outcome":"completed","summary":"Implemented contracts, launch manifest, pinned Foundry configuration, and vendored dependencies.\n\n- `forge build`, `forge test`, and `forge fmt --check` pass.\n- 40 tests pass, including 12 fuzz tests using the real PoolManager.\n- Hook deployment including WorkersNFT uses 6,285,701 gas; bytecode limits pass.\n\nDeployment assumptions are in [README.md](README.md); the local adversarial review is in [REVIEW.md](REVIEW.md).","treeHash":"d1f544cefe74a8fc66cc7c5509e26344762da0f3","usage":{"cachedInputTokens":1871943,"inputTokens":102550,"model":"gpt-6.1-sol","outputTokens":36591,"runtime":"codex","turns":8,"wallClockMs":727300}}],"verification":[{"checks":[{"durationMs":41781,"exitCode":0,"name":"build","output":"Compiling 103 files with Solc 0.8.26\nSolc 0.8.26 finished in 41.61s\nCompiler run successful!\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/WorkHook.sol:67:39\n   │\n67 │     constructor(IPoolManager manager, address token_, address owner_, int24 tickSpacing_) Protocol(owner_) {\n   │                                       ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/WorkHook.sol:204:17\n    │\n204 │                 emit ObservationWritten(count - 1, timestamp, cumulative, tick);\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/WorkHook.sol:210:9\n    │\n210 │         emit ObservationWritten(count, timestamp, cumulative, tick);\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/WorkHook.sol:125:9\n    │\n125 │         emit PoolInitialized(PoolId.unwrap(poolId), sqrtPriceX96);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:142:29\n    │\n142 │         uint256 magnitude = uint256(params.amountSpecified < 0 ? -params.amountSpecified : params.amountSpecified);\n    │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/WorkersNFT.sol:159:16\n    │\n159 │         return block.timestamp < pausedUntil;\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:154:63\n    │\n154 │         return (IHooks.beforeSwap.selector, toBeforeSwapDelta(int128(int256(fee)), 0), 0);\n    │                                                               ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:154:70\n    │\n154 │         return (IHooks.beforeSwap.selector, toBeforeSwapDelta(int128(int256(fee)), 0), 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[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/WorkHook.sol:176:58\n    │\n176 │         return (IHooks.afterSwap.selector, int128(int256(fee)));\n    │                                                          ━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:167:56\n    │\n167 │             int256 expected = params.amountSpecified + int256(_specifiedFee(params));\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/WorkHook.sol:170:33\n    │\n170 │             uint256 magnitude = uint256(imdDelta < 0 ? -int256(imdDelta) : int256(imdDelta));\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/WorkHook.sol:176:44\n    │\n176 │         return (IHooks.afterSwap.selector, int128(int256(fee)));\n    │                                            ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:176:51\n    │\n176 │         return (IHooks.afterSwap.selector, int128(int256(fee)));\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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/WorkersNFT.sol:163:27\n    │\n163 │         if (isPaused() || block.timestamp < nextPauseTime) revert InvalidParameter();\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/WorkHook.sol:189:34\n    │\n189 │         uint256 treasury = fee - share;\n    │                                  ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/WorkHook.sol:191:9\n    │\n191 │         emit FeeCollected(fee, share, treasury);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/WorkHook.sol:208:77\n    │\n208 │         observations[count % OBSERVATION_CAPACITY] = Observation(timestamp, cumulative, tick);\n    │                                                                             ━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:196:28\n    │\n196 │         uint64 timestamp = 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/WorkHook.sol:215:29\n    │\n215 │         if (!initialized || block.timestamp < initializedAt + TWAP_WINDOW) revert OracleNotReady();\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/WorkHook.sol:219:13\n    │\n219 │         if (observations[low % OBSERVATION_CAPACITY].timestamp > boundary) revert OracleNotReady();\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/WorkHook.sol:223:17\n    │\n223 │             if (observations[mid % OBSERVATION_CAPACITY].timestamp <= boundary) low = mid;\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:228:82\n    │\n228 │         int256 startCumulative = int256(start.cumulative) + int256(start.tick) * int256(boundary - start.timestamp);\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/WorkHook.sol:229:78\n    │\n229 │         int256 endCumulative = int256(last.cumulative) + int256(last.tick) * int256(block.timestamp - last.timestamp);\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/WorkHook.sol:231:39\n    │\n231 │         int256 average = difference / int256(TWAP_WINDOW);\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/WorkHook.sol:232:44\n    │\n232 │         if (difference < 0 && difference % int256(TWAP_WINDOW) != 0) --average;\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/WorkHook.sol:233:16\n    │\n233 │         return int24(average);\n    │                ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int24' 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/WorkHook.sol:259:29\n    │\n259 │         output = abi.decode(poolManager.unlock(abi.encode(amount, minimumOutput)), (uint256));\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/WorkHook.sol:261:9\n    │\n261 │         emit BuybackExecuted(amount, output, minimumOutput);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:271:35\n    │\n271 │                 amountSpecified: -int256(amount),\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/WorkHook.sol:281:31\n    │\n281 │         if (int256(input) != -int256(amount)) revert PartialFill();\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/WorkHook.sol:282:30\n    │\n282 │         if (received <= 0 || uint256(int256(received)) < minimumOutput) revert Slippage();\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[unused-return]: return value of an external call is not used\n    ╭▸ src/WorkHook.sol:285:9\n    │\n285 │         poolManager.settle();\n    │         ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:286:54\n    │\n286 │         poolManager.take(Currency.wrap(token), DEAD, uint256(int256(received)));\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/WorkHook.sol:287:27\n    │\n287 │         return abi.encode(uint256(int256(received)));\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[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/WorkersNFT.sol:182:9\n    │\n182 │         emit FloorChanged(value);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/WorkHook.sol:290:59\n    │\n290 │     function sweep(address strayToken) external onlyOwner nonReentrant {\n    │                                                           ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkersNFT.sol:216:16\n    │\n216 │         return uint256(int256(12 + epoch()) + floorAdjustment);\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/WorkersNFT.sol:216:24\n    │\n216 │         return uint256(int256(12 + epoch()) + floorAdjustment);\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/WorkersNFT.sol:276:9\n    │\n276 │         emit TargetUpdated(storedTarget);\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/WorkersNFT.sol:155:9\n    │\n155 │         emit MintEnded(block.timestamp, minted, burnReward);\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/WorkersNFT.sol:289:9\n    │\n289 │         emit MintPayment(reward, buy, treasury);\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/WorkersNFT.sol:292:9\n    │\n292 │         emit WorkMinted(msg.sender, id, digest, overclocked[id]);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkersNFT.sol:314:40\n    │\n314 │         stakes[id] = Stake(msg.sender, uint64(until), weight, uint256(weight) * accIMDPerWeight / REWARD_SCALE);\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/WorkersNFT.sol:340:9\n    │\n340 │         emit IMDClaimed(recipient, id, amount);\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/WorkersNFT.sol:329:54\n    │\n329 │             if (stakes[ids[i]].staker != msg.sender) revert Unauthorized();\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/WorkersNFT.sol:346:13\n    │\n346 │         if (block.timestamp < s.unlockTime) revert Locked();\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/WorkersNFT.sol:351:9\n    │\n351 │         emit Unstaked(msg.sender, id);\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/WorkersNFT.sol:375:18\n    │\n375 │         output = IWorkBuyback(hook).executeBuyback(amount);\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/WorkersNFT.sol:371:37\n    │\n371 │         if (lastBuybackTime != 0 && block.timestamp < lastBuybackTime + 60) revert Locked();\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/WorkersNFT.sol:376:9\n    │\n376 │         emit Buyback(amount, output);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/WorkersNFT.sol:424:33\n    │\n424 │             uint256 allocated = increment * activeWorkers;\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/WorkersNFT.sol:445:54\n    │\n445 │             if (beneficiaryOf(ids[i]) != msg.sender) revert Unauthorized();\n    │                                                      ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/WorkersNFT.sol:460:58\n    │\n460 │     function releaseMiningRemainder() external onlyOwner nonReentrant {\n    │                                                          ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/WorkersNFT.sol:461:45\n    │\n461 │         if (!mintEnded || miningReleased || block.timestamp < mintEndTime + MINING_DURATION) revert MiningClosed();\n    │                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/WorkersNFT.sol:492:54\n    │\n492 │     function sweep(address token) external onlyOwner nonReentrant {\n    │                                                      ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[incorrect-strict-equality]: dangerous strict equality check on an externally-influenced value\n    ╭▸ src/WorkersNFT.sol:501:13\n    │\n501 │         if (IERC20(IMD).balanceOf(address(this)) - beforeBalance != amount) revert InsufficientReserve();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/incorrect-strict-equality\n\n","passed":true},{"durationMs":499,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 2 tests for test/Work.t.sol:WorkTest\n[PASS] testFuzzAllowance(uint96) (runs: 128, μ: 126544, ~: 127762)\nLogs:\n  Bound result 5082\n\n[PASS] testSupplyAndTransfer() (gas: 115637)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 8.73ms (8.87ms CPU time)\n\nRan 11 tests for test/Mining.t.sol:MiningTest\n[PASS] testEarlyUnpauseStartsNewTwentyFourHourCooldown() (gas: 409480)\n[PASS] testEightErasEmitExactlyTwelvePointFiveMillionEach() (gas: 358245)\n[PASS] testFuzzAccrualConservedAndUnclaimedMoves(uint32) (runs: 128, μ: 908064, ~: 915073)\nLogs:\n  Bound result 3333\n\n[PASS] testFuzzActivationFeeAndOneTime(uint96) (runs: 128, μ: 391568, ~: 392370)\nLogs:\n  Bound result 3348\n\n[PASS] testFuzzBurnFixedPayoutAndStopsEarning(uint32) (runs: 128, μ: 907119, ~: 902356)\nLogs:\n  Bound result 3333\n\n[PASS] testFuzzNoWorkerCarryReleasedOnActivation(uint32) (runs: 128, μ: 584343, ~: 582001)\nLogs:\n  Bound result 3333\n\n[PASS] testFuzzPauseScopeAutoExpiryAndCooldown(uint32) (runs: 128, μ: 674549, ~: 674388)\nLogs:\n  Bound result 100\n\n[PASS] testNoActiveRemainderGoesToBAndClosesActivation() (gas: 342154)\n[PASS] testPauseCarriesWhileClaimsActivationAndBurnStillWork() (gas: 1028917)\n[PASS] testRemainderReleasePreservesAllAccruedClaims() (gas: 1001520)\n[PASS] testStakerCanActivateAndClaimWorkButCannotBurn() (gas: 509184)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 39.14ms (142.70ms CPU time)\n\nRan 8 tests for test/Staking.t.sol:StakingTest\n[PASS] testBadEscrowActionsAndOrdinaryTransfer() (gas: 320990)\n[PASS] testFundingOnlyFromBAndOnce() (gas: 358691)\n[PASS] testFuzzEscrowLockAndWeight(uint8,uint32) (runs: 128, μ: 375546, ~: 375465)\nLogs:\n  Bound result 19273\n\n[PASS] testFuzzRewardsConservationAndReserveCap(uint96) (runs: 128, μ: 585880, ~: 590990)\nLogs:\n  Bound result 9382\n\n[PASS] testFuzzSweepLimits(uint96,uint96) (runs: 128, μ: 1765985, ~: 1765902)\nLogs:\n  Bound result 15888\n  Bound result 962345887845286902669\n\n[PASS] testNotifyFeesAuthenticatedAndFunded() (gas: 191615)\n[PASS] testPauseNeverBlocksClaimsOrUnstakeOrTransfer() (gas: 1199873)\n[PASS] testWeightedMintIncomeAndNoPastRewardsForNewStake() (gas: 1598428)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 139.42ms (197.20ms CPU time)\n\nRan 4 tests for test/ProofOfWork.t.sol:WorkMathTest\n[PASS] testDrawExhaustsEveryId() (gas: 144736903)\n[PASS] testFuzzIdPickingUsesHashModuloAndSwapPop(uint256,uint8) (runs: 128, μ: 3242616, ~: 1829617)\nLogs:\n  Bound result 112\n\n[PASS] testFuzzIdleDoublesButNeverCrossesFloor(uint32,uint8) (runs: 128, μ: 19054, ~: 19145)\nLogs:\n  Bound result 17\n\n[PASS] testFuzzRetarget(uint256,uint32,uint8) (runs: 128, μ: 19660, ~: 19593)\nLogs:\n  Bound result 10\n  Bound result 4654\n  Bound result 98\n\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 185.61ms (290.49ms CPU time)\n\nRan 9 tests for test/ProofOfWork.t.sol:ProofOfWorkTest\n[PASS] testAnchorUsesL2AndRejectsOldCurrentAndFuture() (gas: 94348)\n[PASS] testBadProofAndMissingPaymentRollback() (gas: 686058)\n[PASS] testCapCanOnlyFallAndEndsPermanently() (gas: 1108733)\n[PASS] testFuzzScaledMintSplit(uint16) (runs: 128, μ: 491854, ~: 491967)\nLogs:\n  Bound result 5997\n\n[PASS] testFuzzWorkChecks(uint256,address,uint8) (runs: 128, μ: 78496, ~: 78454)\nLogs:\n  Bound result 3\n\n[PASS] testOverclockedURIAndCompatibleApprovals() (gas: 17891576)\n[PASS] testProofBindingReplayAndOnePerL2Block() (gas: 906157)\n[PASS] testRetargetOnEighthMintAndIdleRecovery() (gas: 10266663)\n[PASS] testStartingDifficultyPriceAndPaidMint() (gas: 513551)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 406.02ms (155.10ms CPU time)\n\nRan 7 tests for test/Adversarial.t.sol:AdversarialTest\n[PASS] testBeforeEndActivationAndBurnRevert() (gas: 452651)\n[PASS] testFuzzEpochFloorsAndPrices(uint16,uint16,int8) (runs: 128, μ: 4383612, ~: 4384878)\nLogs:\n  Bound result 2333\n  Bound result 5576\n  Bound result -2\n\n[PASS] testFuzzSequenceConservesPoolsAndUserLiabilities(uint256) (runs: 128, μ: 8377948, ~: 8350111)\n[PASS] testOwnerParameterBoundsAuthorizationAndEvents() (gas: 684343)\n[PASS] testReentrantReceiverCannotMintTwice() (gas: 1671189)\n[PASS] testRejectingReceiverRollsBackPaymentAndProof() (gas: 1716654)\n[PASS] testUnstakeUsesPlainTransferEvenIfReceiverRejects() (gas: 1898877)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 409.27ms (352.48ms CPU time)\n\nRan 16 tests for test/Hook.t.sol:HookReverseOrderTest\n[PASS] testActualCreate2DeploymentUnderTwelveMillionGasAndSizeLimits() (gas: 9448405)\nLogs:\n  Hook plus WorkersNFT creation gas: 6774181\n\n[PASS] testAfterMintWithoutStakersRoutesAllToB() (gas: 312879)\n[PASS] testBuyAndSellExactOutputFees() (gas: 469245)\n[PASS] testBuybackFeeExemptionOutputBurnAndCooldown() (gas: 1016415)\n[PASS] testBuybackHundredIMDCapEvenWithLargerFundedBalance() (gas: 597307)\n[PASS] testBuybackRejectsYoungOracleAndManipulatedSpotAtomically() (gas: 995310)\n[PASS] testFuzzBuyExactInputFeeDuringMint(uint96,uint16) (runs: 128, μ: 317177, ~: 317823)\nLogs:\n  Bound result 9999999999999000014225\n  Bound result 168\n\n[PASS] testFuzzBuybackAmount(uint96) (runs: 128, μ: 698794, ~: 737434)\nLogs:\n  Bound result 1671\n\n[PASS] testFuzzHookSplitAfterMint(uint16,uint96) (runs: 128, μ: 982425, ~: 982703)\nLogs:\n  Bound result 9219\n  Bound result 9999999999999000020317\n\n[PASS] testHookSweepOnlyStraysAndOwnerBounds() (gas: 259800)\n[PASS] testInitializationAndUnauthorizedCallbacks() (gas: 322976)\n[PASS] testMintPeriodRoutesAllToBEvenWithStakers() (gas: 750387)\n[PASS] testRepeatedSameTimestampAndRingWrap() (gas: 481190953)\n[PASS] testSellExactInputFee() (gas: 229028)\n[PASS] testSpecifiedIMDPartialFillRollsBackFee() (gas: 201756)\n[PASS] testTwapUsesElapsedTimeAndRejectsSpotManipulation() (gas: 458139)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 409.28ms (491.98ms CPU time)\n\nRan 16 tests for test/Hook.t.sol:HookTest\n[PASS] testActualCreate2DeploymentUnderTwelveMillionGasAndSizeLimits() (gas: 18429350)\nLogs:\n  Hook plus WorkersNFT creation gas: 6915525\n\n[PASS] testAfterMintWithoutStakersRoutesAllToB() (gas: 307144)\n[PASS] testBuyAndSellExactOutputFees() (gas: 469362)\n[PASS] testBuybackFeeExemptionOutputBurnAndCooldown() (gas: 1009558)\n[PASS] testBuybackHundredIMDCapEvenWithLargerFundedBalance() (gas: 591603)\n[PASS] testBuybackRejectsYoungOracleAndManipulatedSpotAtomically() (gas: 988777)\n[PASS] testFuzzBuyExactInputFeeDuringMint(uint96,uint16) (runs: 128, μ: 310644, ~: 312091)\nLogs:\n  Bound result 9999999999999000015889\n  Bound result 736\n\n[PASS] testFuzzBuybackAmount(uint96) (runs: 128, μ: 693779, ~: 731252)\nLogs:\n  Bound result 3262\n\n[PASS] testFuzzHookSplitAfterMint(uint16,uint96) (runs: 128, μ: 976590, ~: 976890)\nLogs:\n  Bound result 9171\n  Bound result 9999999999999000020873\n\n[PASS] testHookSweepOnlyStraysAndOwnerBounds() (gas: 259800)\n[PASS] testInitializationAndUnauthorizedCallbacks() (gas: 322976)\n[PASS] testMintPeriodRoutesAllToBEvenWithStakers() (gas: 744652)\n[PASS] testRepeatedSameTimestampAndRingWrap() (gas: 481858975)\n[PASS] testSellExactInputFee() (gas: 234794)\n[PASS] testSpecifiedIMDPartialFillRollsBackFee() (gas: 196331)\n[PASS] testTwapUsesElapsedTimeAndRejectsSpotManipulation() (gas: 452171)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 409.27ms (894.69ms CPU time)\n\nRan 8 test suites in 412.10ms (2.01s CPU time): 73 tests passed, 0 failed, 0 skipped (73 total tests)\n","passed":true},{"durationMs":53,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"Work.approve(address,uint256)\",\"Work.transfer(address,uint256)\",\"Work.transferFrom(address,address,uint256)\",\"WorkHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"WorkHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"WorkHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"WorkHook.executeBuyback(uint256)\",\"WorkHook.setFeeBps(uint16)\",\"WorkHook.setStakerShareBps(uint16)\",\"WorkHook.sweep(address)\",\"WorkHook.unlockCallback(bytes)\",\"WorkersNFT.activate(uint256)\",\"WorkersNFT.approve(address,uint256)\",\"WorkersNFT.burn(uint256)\",\"WorkersNFT.buyback(uint256)\",\"WorkersNFT.claimIMD(uint256[])\",\"WorkersNFT.claimWork(uint256[])\",\"WorkersNFT.endMint()\",\"WorkersNFT.fundPools()\",\"WorkersNFT.mint(uint256,uint256)\",\"WorkersNFT.notifyHookFees(uint256)\",\"WorkersNFT.pause()\",\"WorkersNFT.releaseMiningRemainder()\",\"WorkersNFT.safeTransferFrom(address,address,uint256)\",\"WorkersNFT.safeTransferFrom(address,address,uint256,bytes)\",\"WorkersNFT.setActivationFee(uint256)\",\"WorkersNFT.setApprovalForAll(address,bool)\",\"WorkersNFT.setBaseURI(string)\",\"WorkersNFT.setCap(uint256)\",\"WorkersNFT.setFloorAdjustment(int8)\",\"WorkersNFT.setPriceScaleBps(uint16)\",\"WorkersNFT.setRoyaltyBps(uint96)\",\"WorkersNFT.stake(uint256,uint256)\",\"WorkersNFT.sweep(address)\",\"WorkersNFT.transferFrom(address,address,uint256)\",\"WorkersNFT.unpause()\",\"WorkersNFT.unstake(uint256)\",\"WorkersNFT.updateWork()\"],\"files\":{\".gitignore\":4,\"README.md\":135,\"docs/ADVERSARIAL_REVIEW.md\":67,\"foundry.toml\":15,\"launch.json\":25,\"src/Protocol.sol\":33,\"src/Work.sol\":10,\"src/WorkHook.sol\":295,\"src/WorkMath.sol\":40,\"src/WorkersNFT.sol\":509,\"test/Adversarial.t.sol\":232,\"test/Fixtures.sol\":205,\"test/Hook.t.sol\":313,\"test/Mining.t.sol\":252,\"test/ProofOfWork.t.sol\":264,\"test/Staking.t.sol\":192,\"test/Work.t.sol\":28,\"tools/check_artifacts.py\":32},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":6844,"exitCode":0,"name":"slither","output":"[high/medium] weak-prng at src/WorkHook.sol:213: WorkHook.twapTick() (src/WorkHook.sol#213-234) uses a weak PRNG: \"difference < 0 && difference % int256(TWAP_WINDOW) != 0 (src/WorkHook.sol#232)\"\n[medium/medium] divide-before-multiply at src/WorkersNFT.sol:417: WorkersNFT._updateWork() (src/WorkersNFT.sol#417-430) performs a multiplication on the result of a division:\n[medium/high] incorrect-equality at src/WorkHook.sol:195: WorkHook._record(int24) (src/WorkHook.sol#195-211) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/WorkHook.sol:236: WorkHook.quoteBuyback(uint256) (src/WorkHook.sol#236-252) uses a dangerous strict equality:\n[medium/medium] uninitialized-local at src/WorkHook.sol:181: WorkHook._collect(uint256).share (src/WorkHook.sol#181) is a local variable never initialized\n[medium/medium] uninitialized-local at src/WorkHook.sol:198: WorkHook._record(int24).cumulative (src/WorkHook.sol#198) is a local variable never initialized\n[medium/medium] uninitialized-local at src/WorkersNFT.sol:308: WorkersNFT.stake(uint256,uint256).weight (src/WorkersNFT.sol#308) is a local variable never initialized\n[medium/medium] uninitialized-local at src/WorkHook.sol:164: WorkHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes).fee (src/WorkHook.sol#164) is a local variable never initialized\n[medium/medium] unused-return at src/WorkHook.sol:157: WorkHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/WorkHook.sol#157-177) ignores return value by (None,tick,None,None) = poolManager.getSlot0(poolId) (src/WorkHook.sol#174)\n[medium/medium] unused-return at src/WorkHook.sol:264: WorkHook.unlockCallback(bytes) (src/WorkHook.sol#264-288) ignores return value by (None,tick,None,None) = poolManager.getSlot0(poolId) (src/WorkHook.sol#277)\n[medium/medium] unused-return at src/WorkHook.sol:264: WorkHook.unlockCallback(bytes) (src/WorkHook.sol#264-288) ignores return value by poolManager.settle() (src/WorkHook.sol#285)\n[low/medium] reentrancy-benign at src/WorkHook.sol:264: Reentrancy in WorkHook.unlockCallback(bytes) (src/WorkHook.sol#264-288):\n[low/medium] reentrancy-benign at src/WorkHook.sol:255: Reentrancy in WorkHook.executeBuyback(uint256) (src/WorkHook.sol#255-262):\n[low/medium] reentrancy-benign at src/WorkHook.sol:157: Reentrancy in WorkHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/WorkHook.sol#157-177):\n[low/medium] reentrancy-events at src/WorkHook.sol:179: Reentrancy in WorkHook._collect(uint256) (src/WorkHook.sol#179-192):\n[low/medium] reentrancy-events at src/WorkHook.sol:264: Reentrancy in WorkHook.unlockCallback(bytes) (src/WorkHook.sol#264-288):\n[low/medium] reentrancy-events at src/WorkHook.sol:157: Reentrancy in WorkHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/WorkHook.sol#157-177):\n[low/medium] timestamp at src/WorkersNFT.sol:158: WorkersNFT.isPaused() (src/WorkersNFT.sol#158-160) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:334: WorkersNFT._claimIMD(uint256,address) (src/WorkersNFT.sol#334-341) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:417: WorkersNFT._updateWork() (src/WorkersNFT.sol#417-430) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkHook.sol:213: WorkHook.twapTick() (src/WorkHook.sol#213-234) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:460: WorkersNFT.releaseMiningRemainder() (src/WorkersNFT.sol#460-470) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:402: WorkersNFT.scheduledWork(uint256) (src/WorkersNFT.sol#402-411) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:354: WorkersNFT.notifyHookFees(uint256) (src/WorkersNFT.sol#354-362) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkHook.sol:236: WorkHook.quoteBuyback(uint256) (src/WorkHook.sol#236-252) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:255: WorkersNFT.mint(uint256,uint256) (src/WorkersNFT.sol#255-293) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkHook.sol:195: WorkHook._record(int24) (src/WorkHook.sol#195-211) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:343: WorkersNFT.unstake(uint256) (src/WorkersNFT.sol#343-352) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:251: WorkersNFT.checkWork(address,uint256,uint256) (src/WorkersNFT.sol#251-253) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:432: WorkersNFT.pendingWork(uint256) (src/WorkersNFT.sol#432-440) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:162: WorkersNFT.pause() (src/WorkersNFT.sol#162-168) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:369: WorkersNFT.buyback(uint256) (src/WorkersNFT.sol#369-377) uses timestamp for comparisons","passed":true},{"durationMs":535,"exitCode":0,"name":"aderyn","output":"[high] reentrancy-state-change at src/WorkHook.sol:259: Reentrancy: State change after external call (3 places)\n[high] unsafe-casting at src/WorkHook.sol:233: Unsafe Casting of integers (2 places)\n[low] centralization-risk at src/WorkHook.sol:93: Centralization Risk (14 places)\n[low] costly-loop at src/WorkersNFT.sol:328: Costly operations inside loop (2 places)\n[low] large-numeric-literal at src/Work.sol:8: Large Numeric Literal (14 places)\n[low] literal-instead-of-constant at src/WorkHook.sol:100: Literal Instead of Constant (22 places)\n[low] non-reentrant-not-first at src/WorkHook.sol:290: `nonReentrant` is Not the First Modifier (3 places)\n[low] require-revert-in-loop at src/WorkersNFT.sol:328: Loop Contains `require`/`revert` (2 places)\n[low] unchecked-return at src/WorkHook.sol:285: Unchecked Return (3 places)\n[low] uninitialized-local-variable at src/WorkersNFT.sol:328: Uninitialized Local Variable (3 places)\n[low] unused-public-function at src/WorkersNFT.sol:432: Public Function Not Used Internally","passed":true}],"detail":"launch.json is not a valid launch manifest: hook.contract: expected a contract name; hook.permissions: Invalid input: expected array, received undefined; token.contract: expected a contract name; pool.pairedCurrency: Invalid input: expected string, received undefined; pool.initialPrice: Invalid input: expected string, received undefined; notes: Invalid input: expected string, received undefined","evaluation":"checks","profile":"foundry","status":"rejected","submissionHash":"5ecd309c56113627b95fbd473c964bedf7c5526a65347303982a97d25798e348","verifiedTreeHash":"1c82ec9bc6219bdb5608a1ab9d2d732ef5a41cce","verifierVersion":"0.1.0+a2d9a899"},{"checks":[{"durationMs":28962,"exitCode":0,"name":"build","output":"Compiling 99 files with Solc 0.8.26\nSolc 0.8.26 finished in 28.79s\nCompiler run successful!\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/WorkHook.sol:65:39\n   │\n65 │     constructor(IPoolManager manager, address token_, address admin, int24 spacing) Configuration(admin) {\n   │                                       ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-events-access-control]: `committedWorkScaled` is changed without an event but is used for access control\n    ╭▸ src/WorkersNFT.sol:424:9\n    │\n424 │         committedWorkScaled += available - remainder;\n    │         ━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-events-access-control]: `miningReserve` is changed without an event but is used for access control\n    ╭▸ src/WorkersNFT.sol:371:9\n    │\n371 │         miningReserve = MINING_FUND;\n    │         ━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-events-access-control]: `workDebtScaled` is changed without an event but is used for access control\n    ╭▸ src/WorkersNFT.sol:388:9\n    │\n388 │         workDebtScaled[id] = accWorkPerWorker;\n    │         ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-events-access-control]: `miningReserve` is changed without an event but is used for access control\n    ╭▸ src/WorkersNFT.sol:470:9\n    │\n470 │         miningReserve = protected;\n    │         ━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-events-access-control]: `workDebtScaled` is changed without an event but is used for access control\n    ╭▸ src/WorkersNFT.sol:445:9\n    │\n445 │         workDebtScaled[id] += paidScaled;\n    │         ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-events-access-control]: `miningReserve` is changed without an event but is used for access control\n    ╭▸ src/WorkersNFT.sol:447:9\n    │\n447 │         miningReserve -= amount;\n    │         ━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:129:39\n    │\n129 │         observations.push(Observation(uint64(block.timestamp), tick, 0));\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/WorkHook.sol:146:29\n    │\n146 │         uint256 magnitude = uint256(amount < 0 ? -amount : amount);\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[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/WorkHook.sol:155:9\n    │\n155 │         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/WorkHook.sol:201:9\n    │\n201 │         emit FeeCollected(fee, share, fee - share);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:165:63\n    │\n165 │         return (IHooks.beforeSwap.selector, toBeforeSwapDelta(int128(fee.toUint128()), 0), 0);\n    │                                                               ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/WorkHook.sol:171:9\n    │\n171 │         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/WorkHook.sol:217:13\n    │\n217 │             emit ObservationWritten(index + 1, block.timestamp, tick, cumulative);\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/WorkHook.sol:220:13\n    │\n220 │             emit ObservationWritten(index, block.timestamp, tick, previous.cumulative);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:180:56\n    │\n180 │             int256 expected = params.amountSpecified + int256(_specifiedFee(params.amountSpecified));\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/WorkHook.sol:183:33\n    │\n183 │             uint256 magnitude = uint256(imdDelta < 0 ? -int256(imdDelta) : int256(imdDelta));\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/WorkHook.sol:188:44\n    │\n188 │         return (IHooks.afterSwap.selector, int128(fee.toUint128()));\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/WorkHook.sol:193:19\n    │\n193 │         if (fee > uint256(uint128(type(int128).max))) revert InvalidParameter();\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/WorkHook.sol:193:27\n    │\n193 │         if (fee > uint256(uint128(type(int128).max))) revert InvalidParameter();\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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/WorkHook.sol:213:13\n    │\n213 │         if (block.timestamp > previous.timestamp) {\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:215:63\n    │\n215 │                 previous.cumulative + int160(previous.tick) * int160(uint160(block.timestamp - previous.timestamp));\n    │                                                               ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int160' 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/WorkHook.sol:215:70\n    │\n215 │                 previous.cumulative + int160(previous.tick) * int160(uint160(block.timestamp - previous.timestamp));\n    │                                                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint160' 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/WorkHook.sol:216:43\n    │\n216 │             observations.push(Observation(uint64(block.timestamp), tick, cumulative));\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/WorkHook.sol:226:27\n    │\n226 │         if (count == 0 || block.timestamp < uint256(observations[0].timestamp) + TWAP_WINDOW) revert OracleNotReady();\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/WorkHook.sol:232:17\n    │\n232 │             if (observations[mid].timestamp <= cutoff) lo = mid;\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:237:78\n    │\n237 │         int256 endCumulative = int256(last.cumulative) + int256(last.tick) * int256(block.timestamp - last.timestamp);\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/WorkHook.sol:238:82\n    │\n238 │         int256 startCumulative = int256(start.cumulative) + int256(start.tick) * int256(cutoff - start.timestamp);\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/WorkHook.sol:242:32\n    │\n242 │             ? -((-difference + int256(TWAP_WINDOW) - 1) / int256(TWAP_WINDOW))\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/WorkHook.sol:242:59\n    │\n242 │             ? -((-difference + int256(TWAP_WINDOW) - 1) / int256(TWAP_WINDOW))\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/WorkHook.sol:243:28\n    │\n243 │             : difference / int256(TWAP_WINDOW);\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/WorkHook.sol:244:16\n    │\n244 │         return int24(average);\n    │                ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int24' 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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/WorkHook.sol:293:9\n    │\n293 │         emit BuybackExecuted(amount, received, minimum);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:279:35\n    │\n279 │                 amountSpecified: -int256(amount),\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/WorkHook.sol:286:23\n    │\n286 │         if (input != -int256(amount) || output <= 0 || uint256(uint128(output)) < minimum) revert Slippage();\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/WorkHook.sol:286:56\n    │\n286 │         if (input != -int256(amount) || output <= 0 || uint256(uint128(output)) < minimum) revert Slippage();\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/WorkHook.sol:286:64\n    │\n286 │         if (input != -int256(amount) || output <= 0 || uint256(uint128(output)) < minimum) revert Slippage();\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/WorkHook.sol:287:28\n    │\n287 │         uint256 received = uint256(uint128(output));\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/WorkHook.sol:287:36\n    │\n287 │         uint256 received = uint256(uint128(output));\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/WorkersNFT.sol:163:9\n    │\n163 │         emit FloorChanged(adjustment);\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/WorkersNFT.sol:164:9\n    │\n164 │         emit TargetChanged(target);\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/WorkersNFT.sol:188:16\n    │\n188 │         return block.timestamp < pausedUntil;\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/WorkersNFT.sol:192:13\n    │\n192 │         if (block.timestamp < nextPauseAt) revert Locked();\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/WorkersNFT.sol:196:9\n    │\n196 │         emit Paused(pausedUntil, nextPauseAt);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkersNFT.sol:211:16\n    │\n211 │         return uint256(int256(12 + epoch()) + floorAdjustment);\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/WorkersNFT.sol:211:24\n    │\n211 │         return uint256(int256(12 + epoch()) + floorAdjustment);\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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/WorkersNFT.sol:221:13\n    │\n221 │         if (idleSteps >= 256 || target > (ceiling >> idleSteps)) return ceiling;\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/WorkersNFT.sol:221:33\n    │\n221 │         if (idleSteps >= 256 || target > (ceiling >> idleSteps)) return ceiling;\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/WorkersNFT.sol:266:9\n    │\n266 │         emit TargetChanged(target);\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/WorkersNFT.sol:184:9\n    │\n184 │         emit MintEnded(mintEnd, minted, burnPayout);\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/WorkersNFT.sol:277:9\n    │\n277 │         emit WorkerMinted(msg.sender, id, hash, oc, 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/WorkersNFT.sol:297:9\n    │\n297 │         emit HookFeesReceived(amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkersNFT.sol:305:40\n    │\n305 │         stakes[id] = Stake(msg.sender, uint64(unlockAt), weight, accIMDPerWeight * weight);\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/WorkersNFT.sol:332:9\n    │\n332 │         emit IMDClaimed(msg.sender, amount);\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/WorkersNFT.sol:320:40\n    │\n320 │         if (s.depositor != msg.sender) revert Unauthorized();\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/WorkersNFT.sol:339:13\n    │\n339 │         if (block.timestamp < s.unlockAt) revert Locked();\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/WorkersNFT.sol:347:9\n    │\n347 │         emit IMDClaimed(msg.sender, reward);\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/WorkersNFT.sol:348:9\n    │\n348 │         emit Unstaked(msg.sender, id);\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/WorkersNFT.sol:362:18\n    │\n362 │         burned = IWorkBuyback(hook).executeBuyback(amount);\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/WorkersNFT.sol:358:13\n    │\n358 │         if (block.timestamp < nextBuybackAt) revert Locked();\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/WorkersNFT.sol:363:9\n    │\n363 │         emit Buyback(amount, burned);\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/WorkersNFT.sol:392:9\n    │\n392 │         emit Activated(id);\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/WorkersNFT.sol:393:9\n    │\n393 │         emit MetadataUpdate(id);\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/WorkersNFT.sol:426:9\n    │\n426 │         emit WorkAccrued(accWorkPerWorker, carryScaled);\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/WorkersNFT.sol:458:9\n    │\n458 │         emit WorkClaimed(msg.sender, amount);\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/WorkersNFT.sol:440:44\n    │\n440 │         if (beneficiary(id) != msg.sender) revert Unauthorized();\n    │                                            ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/WorkersNFT.sol:462:58\n    │\n462 │     function releaseMiningRemainder() external onlyOwner nonReentrant {\n    │                                                          ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/WorkersNFT.sol:463:71\n    │\n463 │         if (!mintEnded || !poolsFunded || miningClosed || paused() || block.timestamp < mintEnd + MINING_DURATION) {\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/WorkersNFT.sol:473:9\n    │\n473 │         emit MiningClosed(amount, protected);\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/WorkersNFT.sol:490:9\n    │\n490 │         emit WorkClaimed(msg.sender, earned);\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/WorkersNFT.sol:491:9\n    │\n491 │         emit WorkerBurned(id, burnPayout);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\n","passed":true},{"durationMs":1217,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 4 tests for test/Adversarial.t.sol:AdversarialTest\n[PASS] testDuplicateClaimsCannotPayTwice() (gas: 2583850)\n[PASS] testReceiverCannotMintTwice() (gas: 1214828)\n[PASS] testReentrantIMDCannotSweepDuringMint() (gas: 1871670)\n[PASS] testTransferTaxMintRevertsAllEffects() (gas: 884273)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 6.04ms (11.30ms CPU time)\n\nRan 13 tests for test/WorkHook.t.sol:WorkHookTest\n[PASS] testBuyback100LimitPauseAndRepeat() (gas: 749103)\n[PASS] testDeploymentBudgetAndWiring() (gas: 73451)\nLogs:\n  Hook plus WorkersNFT deployment gas: 6052391\n\n[PASS] testFuzzBuybackAmountAndCooldown(uint96) (runs: 64, μ: 5891141, ~: 5891171)\n[PASS] testFuzzFourSwapDirections(bool,bool,uint96) (runs: 64, μ: 247722, ~: 244947)\n[PASS] testFuzzHookSplit(uint96,uint16,uint16) (runs: 64, μ: 4493205, ~: 4507713)\n[PASS] testHookSweepAndOwnerBounds() (gas: 590952)\n[PASS] testInitializeWrongPoolAndUnauthorizedCallbacks() (gas: 275552)\n[PASS] testManipulationDoesNotChangeTwapAndBuybackRollsBack() (gas: 3905649)\n[PASS] testNoStakersAfterMintAllToB() (gas: 311772)\n[PASS] testOnlyOwnerOrDeployerCanInitialize() (gas: 12684445)\n[PASS] testOppositeTokenOrdering() (gas: 25735684)\n[PASS] testPartialFillCannotChargeForUnfilledIMD() (gas: 173287)\n[PASS] testTwapTimeWeightNegativeRoundingAndSameTimestamp() (gas: 469466)\nSuite result: ok. 13 passed; 0 failed; 0 skipped; finished in 1.10s (1.83s CPU time)\n\nRan 26 tests for test/WorkersNFT.t.sol:WorkersNFTTest\n[PASS] testAdminBoundsAndAuthorization() (gas: 1752210)\n[PASS] testArbBlockNotL1BlockAndOldestAnchor() (gas: 111862409)\n[PASS] testCapOnlyDownAndEndPermanent() (gas: 2136738)\n[PASS] testEraBoundariesAndCarryWithoutWorkers() (gas: 2143828)\n[PASS] testFundingMustBeInitiatedByB() (gas: 316296)\n[PASS] testFuzzActivationAccrualTransferAndClaim(uint32) (runs: 64, μ: 2317227, ~: 2316592)\n[PASS] testFuzzBurnAndConservation(uint24) (runs: 64, μ: 2974862, ~: 2982241)\n[PASS] testFuzzEpochPricesAndFloors(uint16,uint16) (runs: 64, μ: 299832, ~: 298869)\n[PASS] testFuzzMintSplitAndEscrow(uint8,uint16) (runs: 64, μ: 2422421, ~: 2422492)\n[PASS] testFuzzMultipleWorkersClaimOrderAndDust(uint32,bool) (runs: 64, μ: 4003497, ~: 4004454)\n[PASS] testFuzzPauseScopeAndCarry(uint24,uint24,bool) (runs: 64, μ: 3240125, ~: 3241253)\n[PASS] testFuzzRetargetElapsed(uint8) (runs: 64, μ: 5015490, ~: 5018403)\n[PASS] testFuzzSweepProtectsReserves(uint96) (runs: 64, μ: 3125963, ~: 3125903)\n[PASS] testFuzzTargetBounds(uint128,uint24,int8) (runs: 64, μ: 256435, ~: 257114)\n[PASS] testFuzzWorkAndPicking(uint64) (runs: 64, μ: 2649081, ~: 2403435)\n[PASS] testInvalidProofAnchorAndSender() (gas: 362004)\n[PASS] testLateFundingIsAtomicAndCannotSweepReserves() (gas: 2012211)\n[PASS] testNoSafeReceiverRequiredForUnstake() (gas: 2226055)\n[PASS] testOverclockMetadataAndApprovals() (gas: 1271370)\n[PASS] testPauseBlocksMintThenExpires() (gas: 1496317)\n[PASS] testPauseScopeCarryAndCooldown() (gas: 3255137)\n[PASS] testReleasePreservesClaimsAndClosesActivation() (gas: 2823320)\n[PASS] testReleaseUnallocatedAndZeroMintEnd() (gas: 458426)\n[PASS] testRetargetEveryEightAndIdle() (gas: 5064714)\n[PASS] testTokenSupplyAndTransfer() (gas: 191474)\n[PASS] testWeightedClaimsAndNoRetroactiveRewards() (gas: 3674226)\nSuite result: ok. 26 passed; 0 failed; 0 skipped; finished in 1.10s (3.30s CPU time)\n\nRan 3 test suites in 1.10s (2.21s CPU time): 43 tests passed, 0 failed, 0 skipped (43 total tests)\n","passed":true},{"durationMs":72,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"Work.approve(address,uint256)\",\"Work.transfer(address,uint256)\",\"Work.transferFrom(address,address,uint256)\",\"WorkHook.afterInitialize(address,(address,address,uint24,int24,address),uint160,int24)\",\"WorkHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"WorkHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"WorkHook.executeBuyback(uint256)\",\"WorkHook.setFee(uint256)\",\"WorkHook.setStakerShare(uint256)\",\"WorkHook.sweep(address)\",\"WorkHook.unlockCallback(bytes)\",\"WorkersNFT.activate(uint256)\",\"WorkersNFT.approve(address,uint256)\",\"WorkersNFT.burn(uint256)\",\"WorkersNFT.buyback(uint256)\",\"WorkersNFT.claimIMD(uint256[])\",\"WorkersNFT.claimWork(uint256[])\",\"WorkersNFT.endMint()\",\"WorkersNFT.fundPools()\",\"WorkersNFT.mint(uint256,uint256)\",\"WorkersNFT.notifyHookFees(uint256)\",\"WorkersNFT.pause()\",\"WorkersNFT.releaseMiningRemainder()\",\"WorkersNFT.safeTransferFrom(address,address,uint256)\",\"WorkersNFT.safeTransferFrom(address,address,uint256,bytes)\",\"WorkersNFT.setActivationFee(uint256)\",\"WorkersNFT.setApprovalForAll(address,bool)\",\"WorkersNFT.setBaseURI(string)\",\"WorkersNFT.setCap(uint256)\",\"WorkersNFT.setFloorAdjustment(int8)\",\"WorkersNFT.setPriceScale(uint256)\",\"WorkersNFT.setRoyalty(uint96)\",\"WorkersNFT.stake(uint256,uint256)\",\"WorkersNFT.sweep(address)\",\"WorkersNFT.transferFrom(address,address,uint256)\",\"WorkersNFT.unstake(uint256)\",\"WorkersNFT.updateMining()\"],\"files\":{\".gitignore\":2,\"DEPENDENCIES.md\":12,\"README.md\":83,\"SECURITY_REVIEW.md\":64,\"foundry.toml\":18,\"launch.json\":26,\"src/Configuration.sol\":21,\"src/Work.sol\":10,\"src/WorkHook.sol\":302,\"src/WorkersNFT.sol\":502,\"test/Adversarial.t.sol\":132,\"test/Support.sol\":170,\"test/WorkHook.t.sol\":333,\"test/WorkersNFT.t.sol\":604},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":8507,"exitCode":0,"name":"slither","output":"[high/medium] weak-prng at src/WorkersNFT.sol:412: WorkersNFT._updateMining() (src/WorkersNFT.sol#412-427) uses a weak PRNG: \"remainder = available % activeWorkers (src/WorkersNFT.sol#422)\"\n[medium/high] incorrect-equality at src/WorkHook.sol:247: WorkHook.quoteBuyback(uint256) (src/WorkHook.sol#247-260) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/WorkHook.sol:224: WorkHook.twapTick() (src/WorkHook.sol#224-245) uses a dangerous strict equality:\n[medium/medium] unused-return at src/WorkHook.sol:209: WorkHook._record() (src/WorkHook.sol#209-222) ignores return value by (None,tick,None,None) = poolManager.getSlot0(poolId) (src/WorkHook.sol#210)\n[low/medium] reentrancy-benign at src/WorkHook.sol:269: Reentrancy in WorkHook.unlockCallback(bytes) (src/WorkHook.sol#269-295):\n[low/medium] reentrancy-benign at src/WorkHook.sol:168: Reentrancy in WorkHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/WorkHook.sol#168-189):\n[low/medium] reentrancy-events at src/WorkHook.sol:269: Reentrancy in WorkHook.unlockCallback(bytes) (src/WorkHook.sol#269-295):\n[low/medium] reentrancy-events at src/WorkHook.sol:269: Reentrancy in WorkHook.unlockCallback(bytes) (src/WorkHook.sol#269-295):\n[low/medium] timestamp at src/WorkHook.sol:209: WorkHook._record() (src/WorkHook.sol#209-222) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkHook.sol:224: WorkHook.twapTick() (src/WorkHook.sol#224-245) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:336: WorkersNFT.unstake(uint256) (src/WorkersNFT.sol#336-349) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:429: WorkersNFT.pendingWork(uint256) (src/WorkersNFT.sol#429-437) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:462: WorkersNFT.releaseMiningRemainder() (src/WorkersNFT.sol#462-474) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:396: WorkersNFT.scheduledWork(uint256) (src/WorkersNFT.sol#396-406) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkHook.sol:247: WorkHook.quoteBuyback(uint256) (src/WorkHook.sol#247-260) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:412: WorkersNFT._updateMining() (src/WorkersNFT.sol#412-427) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:237: WorkersNFT.mint(uint256,uint256) (src/WorkersNFT.sol#237-278) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:191: WorkersNFT.pause() (src/WorkersNFT.sol#191-197) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:187: WorkersNFT.paused() (src/WorkersNFT.sol#187-189) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:356: WorkersNFT.buyback(uint256) (src/WorkersNFT.sol#356-364) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:292: WorkersNFT.notifyHookFees(uint256) (src/WorkersNFT.sol#292-298) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:218: WorkersNFT.currentTarget() (src/WorkersNFT.sol#218-223) uses timestamp for comparisons","passed":true},{"durationMs":732,"exitCode":0,"name":"aderyn","output":"[high] reentrancy-state-change at src/WorkersNFT.sol:117: Reentrancy: State change after external call (3 places)\n[high] unsafe-casting at src/WorkHook.sol:244: Unsafe Casting of integers (2 places)\n[low] centralization-risk at src/WorkHook.sol:102: Centralization Risk (11 places)\n[low] costly-loop at src/WorkersNFT.sol:328: Costly operations inside loop (2 places)\n[low] large-numeric-literal at src/Work.sol:8: Large Numeric Literal (14 places)\n[low] literal-instead-of-constant at src/WorkHook.sol:109: Literal Instead of Constant (24 places)\n[low] non-reentrant-not-first at src/WorkHook.sol:155: `nonReentrant` is Not the First Modifier (3 places)\n[low] require-revert-in-loop at src/WorkersNFT.sol:328: Loop Contains `require`/`revert` (2 places)\n[low] state-change-without-event at src/WorkHook.sol:262: State Change Without Event\n[low] unchecked-return at src/WorkersNFT.sol:130: Unchecked Return","passed":true}],"detail":"launch.json is not a valid launch manifest: kind: Invalid discriminator value. Expected 'univ4_hook' | 'evm_project' | 'custom_token' | 'evm_contracts'","evaluation":"checks","profile":"foundry","status":"rejected","submissionHash":"9b8f0feddd2f5be8b2b2f181197bef50956b21d25bda9ba0a0d166986982d36d","verifiedTreeHash":"956f20a9c34d72292915133766bb111de6c78fdb","verifierVersion":"0.1.0+a2d9a899"},{"checks":[{"durationMs":20887,"exitCode":0,"name":"build","output":"Compiling 95 files with Solc 0.8.26\nSolc 0.8.26 finished in 20.73s\nCompiler run successful!\nwarning[missing-events-access-control]: `totalWeight` is changed without an event but is used for access control\n    ╭▸ src/WorkersNFT.sol:314:9\n    │\n314 │         totalWeight += weight;\n    │         ━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/WorkHook.sol:68:39\n   │\n68 │     constructor(IPoolManager manager, address token_, address owner_, int24 spacing) {\n   │                                       ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:117:39\n    │\n117 │         observations[0] = Observation(uint64(block.timestamp), 0, tick);\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/WorkHook.sol:157:63\n    │\n157 │         return (IHooks.beforeSwap.selector, toBeforeSwapDelta(fee, 0), 0);\n    │                                                               ━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/WorkHook.sol:144:9\n    │\n144 │         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/WorkHook.sol:199:9\n    │\n199 │         emit FeeCollected(amount, share, amount - share);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:151:33\n    │\n151 │             uint256 magnitude = uint256(params.amountSpecified < 0 ? -params.amountSpecified : params.amountSpecified);\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:153:31\n    │\n153 │             require(amount <= uint256(uint128(type(int128).max)), \"fee size\");\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/WorkHook.sol:153:39\n    │\n153 │             require(amount <= uint256(uint128(type(int128).max)), \"fee size\");\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/WorkHook.sol:154:19\n    │\n154 │             fee = int128(int256(amount));\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/WorkHook.sol:154:26\n    │\n154 │             fee = int128(int256(amount));\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[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/WorkHook.sol:185:44\n    │\n185 │         return (IHooks.afterSwap.selector, fee);\n    │                                            ━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/WorkHook.sol:166:28\n    │\n166 │     ) external onlyManager nonReentrant returns (bytes4, int128) {\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/WorkHook.sol:216:9\n    │\n216 │         emit ObservationWritten(block.timestamp, cumulative, tick);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:172:33\n    │\n172 │             uint256 magnitude = uint256(params.amountSpecified < 0 ? -params.amountSpecified : params.amountSpecified);\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:174:56\n    │\n174 │             int256 expected = params.amountSpecified + int256(charged);\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/WorkHook.sol:180:30\n    │\n180 │             uint256 amount = uint256(imdDelta < 0 ? -imdDelta : imdDelta) * feeBps / 10000;\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/WorkHook.sol:181:19\n    │\n181 │             fee = int128(int256(amount));\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/WorkHook.sol:181:26\n    │\n181 │             fee = int128(int256(amount));\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[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/WorkHook.sol:198:46\n    │\n198 │         IERC20(IMD).safeTransfer(B, amount - share);\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/WorkHook.sol:211:13\n    │\n211 │         if (block.timestamp != last.timestamp) {\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:210:47\n    │\n210 │         int128 cumulative = last.cumulative + int128(int256(last.tick) * int256(block.timestamp - last.timestamp));\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/WorkHook.sol:210:74\n    │\n210 │         int128 cumulative = last.cumulative + int128(int256(last.tick) * int256(block.timestamp - last.timestamp));\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/WorkHook.sol:215:54\n    │\n215 │         observations[observationIndex] = Observation(uint64(block.timestamp), cumulative, tick);\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/WorkHook.sol:227:16\n    │\n227 │         while (lo < hi) {\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/WorkHook.sol:221:32\n    │\n221 │         require(initialized && block.timestamp >= TWAP_WINDOW, \"oracle\");\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/WorkHook.sol:224:17\n    │\n224 │         require(observations[oldestIndex].timestamp <= cutoff, \"oracle warming\");\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/WorkHook.sol:229:17\n    │\n229 │             if (observations[(oldestIndex + mid) % OBSERVATION_CAPACITY].timestamp <= cutoff) lo = mid;\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:234:78\n    │\n234 │         int256 nowCumulative = int256(last.cumulative) + int256(last.tick) * int256(block.timestamp - last.timestamp);\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/WorkHook.sol:235:79\n    │\n235 │         int256 pastCumulative = int256(past.cumulative) + int256(past.tick) * int256(cutoff - past.timestamp);\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/WorkHook.sol:237:36\n    │\n237 │         int256 mean = difference / int256(TWAP_WINDOW);\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/WorkHook.sol:238:44\n    │\n238 │         if (difference < 0 && difference % int256(TWAP_WINDOW) != 0) mean--;\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/WorkHook.sol:239:16\n    │\n239 │         return int24(mean);\n    │                ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int24' 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 `observationIndex` is updated\n    ╭▸ src/WorkHook.sol:261:29\n    │\n261 │         output = abi.decode(poolManager.unlock(abi.encode(amount, minimum)), (uint256));\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/WorkHook.sol:264:9\n    │\n264 │         emit BuybackExecuted(amount, output, minimum);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:274:30\n    │\n274 │                 zeroForOne, -int256(amount), zeroForOne ? TickMath.MIN_SQRT_PRICE + 1 : TickMath.MAX_SQRT_PRICE - 1\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/WorkHook.sol:280:27\n    │\n280 │         require(input == -int256(amount) && received >= int256(minimum), \"TWAP slippage\");\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/WorkHook.sol:280:57\n    │\n280 │         require(input == -int256(amount) && received >= int256(minimum), \"TWAP slippage\");\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[unused-return]: return value of an external call is not used\n    ╭▸ src/WorkHook.sol:283:9\n    │\n283 │         poolManager.settle();\n    │         ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkHook.sol:284:54\n    │\n284 │         poolManager.take(Currency.wrap(token), DEAD, uint256(received));\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/WorkHook.sol:285:27\n    │\n285 │         return abi.encode(uint256(received));\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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/WorkersNFT.sol:150:16\n    │\n150 │         return block.timestamp < pausedUntil;\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/WorkersNFT.sol:154:17\n    │\n154 │         require(block.timestamp >= nextPause, \"cooldown\");\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/WorkersNFT.sol:158:9\n    │\n158 │         emit Paused(pausedUntil, nextPause);\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/WorkersNFT.sol:165:9\n    │\n165 │         emit FloorAdjustmentChanged(value);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkersNFT.sol:198:16\n    │\n198 │         return uint256(int256(12 + epoch()) + floorAdjustment);\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/WorkersNFT.sol:198:24\n    │\n198 │         return uint256(int256(12 + epoch()) + floorAdjustment);\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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/WorkersNFT.sol:207:13\n    │\n207 │         if (block.timestamp - lastMintTime >= 300) {\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-oz-erc721-mint]: `ERC721._mint` does not check that the recipient can receive the token; use `_safeMint`\n    ╭▸ src/WorkersNFT.sol:286:9\n    │\n286 │         _mint(msg.sender, id);\n    │         ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-oz-erc721-mint\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/WorkersNFT.sol:277:9\n    │\n277 │         emit Retarget(target);\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/WorkersNFT.sol:146:9\n    │\n146 │         emit MintEnded(mintEnd, minted, burnPayout);\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/WorkersNFT.sol:306:9\n    │\n306 │         emit RewardAdded(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/WorkersNFT.sol:287:9\n    │\n287 │         emit MetadataUpdate(id);\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/WorkersNFT.sol:288:9\n    │\n288 │         emit WorkerMinted(msg.sender, id, proof, price, overclocked[id]);\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/WorkersNFT.sol:294:17\n    │\n294 │         require(IMD.balanceOf(address(this)) == beforeBalance + amount, \"nonstandard IMD\");\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/incorrect-strict-equality\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/WorkersNFT.sol:313:40\n    │\n313 │         stakes[id] = Stake(msg.sender, uint64(block.timestamp + daysLocked * 1 days), weight, accIMD);\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[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/WorkersNFT.sol:328:13\n    │\n328 │             require(stakes[ids[i]].holder == msg.sender, \"staker\");\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-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/WorkersNFT.sol:339:9\n    │\n339 │         emit IMDClaimed(holder, amount);\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/WorkersNFT.sol:344:43\n    │\n344 │         require(s.holder == msg.sender && block.timestamp >= s.unlockAt, \"locked\");\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/WorkersNFT.sol:350:9\n    │\n350 │         emit Unstaked(msg.sender, id);\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/WorkersNFT.sol:365:18\n    │\n365 │         output = IWorkBuyback(hook).executeBuyback(amount);\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/WorkersNFT.sol:361:17\n    │\n361 │         require(block.timestamp >= lastBuyback + 60, \"buyback cooldown\");\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/WorkersNFT.sol:366:9\n    │\n366 │         emit Buyback(amount, output);\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/WorkersNFT.sol:431:9\n    │\n431 │         emit WorkUpdated(scheduled, carriedWork, accWork);\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/WorkersNFT.sol:391:9\n    │\n391 │         emit Activated(id);\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/WorkersNFT.sol:226:9\n    │\n226 │         require(era < 8, \"era\");\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/WorkersNFT.sol:426:33\n    │\n426 │             uint256 allocated = perWorker * activeWorkers;\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/WorkersNFT.sol:427:24\n    │\n427 │             accWork += perWorker * SCALE;\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/WorkersNFT.sol:440:13\n    │\n440 │             amount += (accWork - workDebt[id]) / SCALE;\n    │             ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/WorkersNFT.sol:447:9\n    │\n447 │         emit WorkClaimed(msg.sender, amount);\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/WorkersNFT.sol:439:13\n    │\n439 │             require(_holder(id) == msg.sender && activated[id], \"worker\");\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/WorkersNFT.sol:450:58\n    │\n450 │     function releaseMiningRemainder() external onlyOwner nonReentrant {\n    │                                                          ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/WorkersNFT.sol:451:30\n    │\n451 │         require(mintEnded && block.timestamp >= miningEnd() && !paused() && !miningReleased && funded, \"release\");\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/WorkersNFT.sol:459:9\n    │\n459 │         emit MiningRemainderReleased(remainder);\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/WorkersNFT.sol:479:9\n    │\n479 │         emit Burned(id, burnPayout);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\n","passed":true},{"durationMs":1864,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 40 tests for test/Work.t.sol:WorkTest\n[PASS] testActivationAccrualMovesWithToken() (gas: 2196040)\n[PASS] testAllEpochPricesAndEraBoundaries() (gas: 134063)\n[PASS] testBuybackFailuresAndOracleHistory() (gas: 2131208)\n[PASS] testBuybackRejectsManipulatedSpot() (gas: 1941616)\n[PASS] testCapAndEndPermanent() (gas: 3439592)\n[PASS] testDeploymentGasMeasurement() (gas: 7807)\nLogs:\n  Hook + Workers deployment gas: 6285701\n\n[PASS] testDuplicateClaimIdsCannotDoubleSpend() (gas: 1842294)\n[PASS] testEscrowCannotBeDepositedOrBurned() (gas: 1814592)\n[PASS] testForeignPoolAndCallbackRejection() (gas: 137447)\n[PASS] testFuzzActivationAndTwoWorkerAccrual(uint96,uint32) (runs: 64, μ: 4058139, ~: 4066335)\nLogs:\n  Bound result 95\n  Bound result 1\n\n[PASS] testFuzzBurnFixedPayoutAndEarnedWork(uint32) (runs: 64, μ: 3768523, ~: 3769223)\nLogs:\n  Bound result 1\n\n[PASS] testFuzzBuybackAmount(uint96) (runs: 64, μ: 1818503, ~: 1818616)\nLogs:\n  Bound result 1000001\n\n[PASS] testFuzzEraAccrualAndCarry(uint32,bool) (runs: 64, μ: 2056677, ~: 2068385)\nLogs:\n  Bound result 192\n\n[PASS] testFuzzHookSplit(uint16,uint16,uint96) (runs: 64, μ: 2202634, ~: 2210632)\nLogs:\n  Bound result 9479\n  Bound result 3\n  Bound result 8900929522510644981\n\n[PASS] testFuzzIdPicking(address) (runs: 64, μ: 58029484, ~: 57900708)\n[PASS] testFuzzMintSplitAndEscrow(uint16,uint8) (runs: 64, μ: 3742450, ~: 3742511)\nLogs:\n  Bound result 5001\n\n[PASS] testFuzzPauseScope(uint32,bool) (runs: 64, μ: 4213294, ~: 4242715)\nLogs:\n  Bound result 192\n\n[PASS] testFuzzProofAcceptance(uint256,uint16) (runs: 64, μ: 95009, ~: 95469)\nLogs:\n  Bound result 1\n\n[PASS] testFuzzRetarget(uint32) (runs: 64, μ: 9788530, ~: 9791486)\nLogs:\n  Bound result 1\n\n[PASS] testFuzzSweepReserves(uint96) (runs: 64, μ: 3694510, ~: 3694746)\nLogs:\n  Bound result 1\n\n[PASS] testFuzzWorkDomain(address,uint256,bytes32) (runs: 64, μ: 46142, ~: 46142)\n[PASS] testHookFourSwapModesAndNoStakers() (gas: 898308)\n[PASS] testIdleAndFloorBounds() (gas: 9904927)\n[PASS] testInitcodeLimit() (gas: 24530)\n[PASS] testInitializationAndUnauthorizedCallbacks() (gas: 150745)\n[PASS] testMintRejectsETHAndZeroAnchorHash() (gas: 87846)\n[PASS] testMintSplitPickingApprovalsAndMetadata() (gas: 22128048)\n[PASS] testOracleIntegrationAndCircularHistory() (gas: 125710078)\n[PASS] testOwnerBoundsAndUnauthorized() (gas: 1762052)\n[PASS] testPauseActuallyStopsMintAndAccrual() (gas: 2079202)\n[PASS] testPauseScopeAndCooldown() (gas: 4374313)\n[PASS] testPausedReleaseAndUnauthorizedRelease() (gas: 1841555)\n[PASS] testReentrantIMDCannotSweepReservedFunds() (gas: 2437334)\n[PASS] testRemainderKeepsEarnedReservesAndClosesActivation() (gas: 3751843)\n[PASS] testRemainderWithNoWorkers() (gas: 1723620)\n[PASS] testStandardTokenTransfer() (gas: 80728)\n[PASS] testTinyBuybackRoundingAndPartialFillRevert() (gas: 2149998)\n[PASS] testTokenAndDeploymentLimits() (gas: 52317)\n[PASS] testWeightedStakersCannotClaimEarlierRewards() (gas: 4536002)\n[PASS] testWorkProofReplayAndAge() (gas: 1665903)\nSuite result: ok. 40 passed; 0 failed; 0 skipped; finished in 1.77s (7.05s CPU time)\n\nRan 1 test suite in 1.77s (1.77s CPU time): 40 tests passed, 0 failed, 0 skipped (40 total tests)\n","passed":true},{"durationMs":49,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"Work.approve(address,uint256)\",\"Work.transfer(address,uint256)\",\"Work.transferFrom(address,address,uint256)\",\"WorkHook.afterInitialize(address,(address,address,uint24,int24,address),uint160,int24)\",\"WorkHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"WorkHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"WorkHook.executeBuyback(uint256)\",\"WorkHook.poke()\",\"WorkHook.setFeeBps(uint256)\",\"WorkHook.setStakerShareBps(uint256)\",\"WorkHook.sweep(address)\",\"WorkHook.unlockCallback(bytes)\",\"WorkersNFT.activate(uint256)\",\"WorkersNFT.addHookReward(uint256)\",\"WorkersNFT.approve(address,uint256)\",\"WorkersNFT.burn(uint256)\",\"WorkersNFT.buyback(uint256)\",\"WorkersNFT.claimIMD(uint256[])\",\"WorkersNFT.claimWork(uint256[])\",\"WorkersNFT.endMint()\",\"WorkersNFT.fundPools()\",\"WorkersNFT.mint(uint256,uint256)\",\"WorkersNFT.pause()\",\"WorkersNFT.releaseMiningRemainder()\",\"WorkersNFT.safeTransferFrom(address,address,uint256)\",\"WorkersNFT.safeTransferFrom(address,address,uint256,bytes)\",\"WorkersNFT.setActivationFee(uint256)\",\"WorkersNFT.setApprovalForAll(address,bool)\",\"WorkersNFT.setBaseURI(string)\",\"WorkersNFT.setCap(uint256)\",\"WorkersNFT.setFloorAdjustment(int8)\",\"WorkersNFT.setPriceScaleBps(uint256)\",\"WorkersNFT.setRoyaltyBps(uint96)\",\"WorkersNFT.stake(uint256,uint256)\",\"WorkersNFT.sweep(address)\",\"WorkersNFT.transferFrom(address,address,uint256)\",\"WorkersNFT.unstake(uint256)\",\"WorkersNFT.updateMining()\"],\"files\":{\".gitignore\":4,\"README.md\":189,\"REVIEW.md\":67,\"foundry.toml\":14,\"launch.json\":6,\"src/Work.sol\":10,\"src/WorkHook.sol\":293,\"src/WorkersNFT.sol\":492,\"test/Helpers.sol\":106,\"test/Work.t.sol\":865},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":8478,"exitCode":0,"name":"slither","output":"[high/high] arbitrary-send-erc20 at src/WorkersNFT.sol:369: WorkersNFT.fundPools() (src/WorkersNFT.sol#369-376) uses arbitrary from in transferFrom: work.safeTransferFrom(B,address(this),MINING_FUND + BURN_FUND) (src/WorkersNFT.sol#374)\n[high/medium] weak-prng at src/WorkHook.sol:220: WorkHook.twapTick() (src/WorkHook.sol#220-240) uses a weak PRNG: \"difference < 0 && difference % int256(TWAP_WINDOW) != 0 (src/WorkHook.sol#238)\"\n[medium/medium] divide-before-multiply at src/WorkersNFT.sol:419: WorkersNFT._updateMining() (src/WorkersNFT.sol#419-432) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at src/WorkersNFT.sol:419: WorkersNFT._updateMining() (src/WorkersNFT.sol#419-432) performs a multiplication on the result of a division:\n[medium/high] incorrect-equality at src/WorkersNFT.sol:399: WorkersNFT.scheduledWork(uint256) (src/WorkersNFT.sol#399-409) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/WorkersNFT.sol:291: WorkersNFT._pullIMD(address,uint256) (src/WorkersNFT.sol#291-295) uses a dangerous strict equality:\n[medium/medium] reentrancy-no-eth at src/WorkHook.sol:256: Reentrancy in WorkHook.executeBuyback(uint256) (src/WorkHook.sol#256-265):\n[medium/medium] uninitialized-local at src/WorkersNFT.sol:436: WorkersNFT.claimWork(uint256[]).amount (src/WorkersNFT.sol#436) is a local variable never initialized\n[medium/medium] uninitialized-local at src/WorkHook.sol:191: WorkHook._collectFee(uint256).share (src/WorkHook.sol#191) is a local variable never initialized\n[medium/medium] uninitialized-local at src/WorkHook.sol:225: WorkHook.twapTick().lo (src/WorkHook.sol#225) is a local variable never initialized\n[medium/medium] uninitialized-local at src/WorkHook.sol:168: WorkHook.afterSwap(address,PoolKey,IPoolManager.SwapParams,BalanceDelta,bytes).fee (src/WorkHook.sol#168) is a local variable never initialized\n[medium/medium] uninitialized-local at src/WorkHook.sol:148: WorkHook.beforeSwap(address,PoolKey,IPoolManager.SwapParams,bytes).fee (src/WorkHook.sol#148) is a local variable never initialized\n[medium/medium] unused-return at src/WorkHook.sol:267: WorkHook.unlockCallback(bytes) (src/WorkHook.sol#267-286) ignores return value by poolManager.settle() (src/WorkHook.sol#283)\n[medium/medium] unused-return at src/WorkHook.sol:207: WorkHook._record() (src/WorkHook.sol#207-217) ignores return value by (None,tick,None,None) = poolManager.getSlot0(poolId) (src/WorkHook.sol#209)\n[low/medium] reentrancy-benign at src/WorkHook.sol:256: Reentrancy in WorkHook.executeBuyback(uint256) (src/WorkHook.sol#256-265):\n[low/medium] reentrancy-benign at src/WorkHook.sol:160: Reentrancy in WorkHook.afterSwap(address,PoolKey,IPoolManager.SwapParams,BalanceDelta,bytes) (src/WorkHook.sol#160-186):\n[low/medium] timestamp at src/WorkersNFT.sol:205: WorkersNFT.currentTarget() (src/WorkersNFT.sol#205-211) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:247: WorkersNFT.mint(uint256,uint256) (src/WorkersNFT.sol#247-289) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkHook.sol:220: WorkHook.twapTick() (src/WorkHook.sol#220-240) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:450: WorkersNFT.releaseMiningRemainder() (src/WorkersNFT.sol#450-460) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:399: WorkersNFT.scheduledWork(uint256) (src/WorkersNFT.sol#399-409) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:326: WorkersNFT.claimIMD(uint256[]) (src/WorkersNFT.sol#326-332) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkHook.sol:207: WorkHook._record() (src/WorkHook.sol#207-217) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:354: WorkersNFT._update(address,uint256,address) (src/WorkersNFT.sol#354-357) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:149: WorkersNFT.paused() (src/WorkersNFT.sol#149-151) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:342: WorkersNFT.unstake(uint256) (src/WorkersNFT.sol#342-351) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:153: WorkersNFT.pause() (src/WorkersNFT.sol#153-159) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkHook.sol:242: WorkHook.quoteBuyback(uint256) (src/WorkHook.sol#242-254) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkHook.sol:256: WorkHook.executeBuyback(uint256) (src/WorkHook.sol#256-265) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:419: WorkersNFT._updateMining() (src/WorkersNFT.sol#419-432) uses timestamp for comparisons\n[low/medium] timestamp at src/WorkersNFT.sol:359: WorkersNFT.buyback(uint256) (src/WorkersNFT.sol#359-367) uses timestamp for comparisons","passed":false}],"detail":"static analysis found arbitrary-send-erc20 at src/WorkersNFT.sol:369: WorkersNFT.fundPools() (src/WorkersNFT.sol#369-376) uses arbitrary from in transferFrom: work.safeTransferFrom(B,address(this),MINING_FUND + BURN_FUND) (src/WorkersNFT.sol#374)","evaluation":"checks","profile":"foundry","status":"rejected","submissionHash":"df7e129e26c5956a221ebdcc991359bc73d27a35372556fb004bcc251843ef1f","verifiedTreeHash":"d1f544cefe74a8fc66cc7c5509e26344762da0f3","verifierVersion":"0.1.0+a2d9a899"}]}