{"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":"c5f15366-9ee3-4aef-a855-a554674d7d90","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"e18d6463b2910602894a3651a603d6b30b5cac75cd50245504dc17f27f083b1d","dependsOn":["build_contract_project","manifest"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"c26edc76dc7a76e09a42c3634054429c1679c6e247747d647a03f77e5b332d7e","skillId":"adversarial-review","tools":[]},"key":"adversarial_review","kind":"code","role":"review","skillHash":"c26edc76dc7a76e09a42c3634054429c1679c6e247747d647a03f77e5b332d7e","skillId":"adversarial-review","state":"accepted"},{"acceptedSubmissionHash":"f8874b45fcb52f285a26cf349225afb26798592434d602e917872b181c9693f3","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"0f3e7566c3ff8e87fc95936b79ba455be33eea683bb01a6834a4a4d43e58e1df","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"0f3e7566c3ff8e87fc95936b79ba455be33eea683bb01a6834a4a4d43e58e1df","skillId":"build-contract-project","state":"accepted"},{"acceptedSubmissionHash":"113f12ec7453620e166bb17d3799e4a660f49f12c3c977eb653e9956731d9269","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"}],"objective":"Happy Hour: a Uniswap v4 hook on a native ETH pool. Every swap pays a 1% fee on its ETH side, burned to the dead address, except during one free hour each UTC day. The free hour moves every day on a fixed public schedule.\n\nToken: ERC-20, name \"Happy Hour\", symbol \"HAPPY\", 18 decimals. The zero argument constructor mints exactly 10^27 minor units to msg.sender (the launch factory) and nothing else, ever. No owner, mint, pause, proxy, fees or hooks on transfer.\n\nHook:\n- Constructor takes only the PoolManager address. No owner, admin, setters, pause, sweep or upgrade. Does not use beforeInitialize; the factory opens the pool.\n- On any pool whose currency0 is not native ETH, the hook does nothing.\n- Schedule: day = block.timestamp / 86400. The free hour for that day starts at UTC hour (day * 7) % 24 and lasts exactly 3600 seconds. Uses block.timestamp only; no oracle, no admin input.\n- Outside the free hour: every swap, buy or sell, exact input or exact output, pays exactly 1% of its ETH side (the ETH paid in on a buy, the ETH received on a sell). The fee is sent to 0x000000000000000000000000000000000000dEaD within the same swap.\n- Inside the free hour: no fee at all; the swap matches a hookless pool exactly.\n- The hook holds no ETH or tokens between calls.\n- Views: isHappyHour() returns true during the free hour; happyHourStart(uint256 day) returns that day's start as a Unix timestamp; nextHappyHour() returns the start of the next free hour; currentFeeBps() returns 100 or 0.\n- Event: FeeBurned(PoolId indexed poolId, uint256 amount) on every charged swap.\n- Tests: all four swap shapes charge exactly 1% of the ETH side against a hookless reference pool outside the free hour, and exactly 0 inside it; boundary tests at the first and last second of a free hour and one second either side; the schedule for several consecutive days, including the wrap from hour 23 back to hour 0; the hook's ETH and token balances are zero after every swap; a pool not paired with native ETH is left untouched; fuzz swap sizes and timestamps; the constructor rejects the zero PoolManager and mismatched permission bits.","parentJobId":null,"planHash":"317b0b4afd605ae8ab3fd77d7f275e92c10f110e101bf157699fb250ac53ab73","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"c5f15366-9ee3-4aef-a855-a554674d7d90","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-223-happy-hour-uniswap-v4"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"50975","feedbackHash":"c18e71c1bf31f8d5a46f773673dfb6e23899d889f71006469fb2297361d80c75","nodeKey":"adversarial_review","submissionHash":"e18d6463b2910602894a3651a603d6b30b5cac75cd50245504dc17f27f083b1d","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"50959","feedbackHash":"0ff21d328f78a0fee67748c86a8ad678a4ef47c6fda3df32619b811534b24b76","nodeKey":"build_contract_project","submissionHash":"f8874b45fcb52f285a26cf349225afb26798592434d602e917872b181c9693f3","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"50959","feedbackHash":"baa5212812af2db2c36c433f2cc8f829586030cf30f9a6d66b71b4fb102b370e","nodeKey":"manifest","submissionHash":"113f12ec7453620e166bb17d3799e4a660f49f12c3c977eb653e9956731d9269","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"dd9b0591b4ce810ce3cbc610ff4caed01ab2efba8ff5656bbf078db20a1d7c7c","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"449147d24953deba636ae3bf1397c406b4f97d64b1461973a1bb0f4fbee306b7","device":"468e82a89b9bfe18","findings":[],"hash":"113f12ec7453620e166bb17d3799e4a660f49f12c3c977eb653e9956731d9269","nodeId":"686631e4-41e1-46bf-a922-16a7d9e21cd6","outcome":"completed","summary":"Done. The manifest is written at `launch.json` and is the only changed file.\n\n**What it declares**\n\n- Kind is `univ4_hook` as the first field.\n- Hook is `HappyHourHook` with one constructor argument, the canonical Sepolia PoolManager address that `script/Deploy.s.sol` uses for chain 11155111.\n- Permissions are beforeSwap, afterSwap, beforeSwapReturnDelta and afterSwapReturnDelta. That is exactly the set of true fields in getHookPermissions, flag mask 0xCC.\n- Token is `HappyHourToken`, name \"Happy Hour\", symbol \"HAPPY\", 18 decimals.\n- Pool is paired with native ETH at the zero address, fee 3000, tickSpacing 60, initialPrice 79228162514264337593543950336. These match the accepted test fixture and the 1:1 sqrtPriceX96 used in earlier accepted manifests.\n- Notes run 3664 characters and describe the schedule, fee placement per swap shape, the CREATE2 address requirement, the review caveats, and the offline verification commands. They name no supply, owner or allocation.\n\n**Checks run**\n\n- A scratch validator enforced every schema constraint, the initialPrice refinement, the notes cap, and cross-checked the permission list against the hook source.\n- Build passed offline with exit code 0. All 56 tests passed offline.\n- Git status shows only the new launch.json.\n\nOne judgment call to flag: there is no univ4_hook manifest example on this box, so the PoolManager argument is written as the concrete Sepolia address rather than a placeholder token. The deploy script, README and REVIEW.md all pin that address, and the protected floor test expects a concrete manager address baked into the creation code.","treeHash":"9dc358fd27fd28f322d528a637e840a1d472e623","usage":{"cachedInputTokens":820475,"inputTokens":322,"model":"claude-fable-5-1","outputTokens":10943,"runtime":"claude","turns":18,"wallClockMs":183591}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"377843575071cdb1","findings":[{"description":"For exact-input buys and exact-output sells, beforeSwap burns 1% of params.amountSpecified before the filled amount is known. PoolManager permits partial fills at the price limit, but afterSwap skips both shapes and never corrects the fee. Consequently the burn can exceed the entire executed ETH leg, turn a sell into an ETH debt, or charge a swap that exchanges nothing. This violates the required 1% fee against the hookless reference. The fuzz test bounds sizes to 50 ether against 1000 ether liquidity, always uses extreme price limits, and calculates these two expected fees from the requested amount, so it misses this defect.","line":147,"path":"src/HappyHourHook.sol","reproduction":"Reproduced with the vendored PoolManager and PoolSwapTest on local Anvil. At timestamp 8683200 (day 100, outside happy hour), initialize identical ETH/HAPPY hooked and hookless pools with fee=3000, tickSpacing=60, sqrtPriceX96=79228162514264337593543950336, and liquidity=1000e18 across ticks [-887220,887220]. Call each through PoolSwapTest.swap with value=100 ether, TestSettings(false,false), empty hookData, and SwapParams(true,-10e18,TickMath.getSqrtPriceAtTick(-1)). Reference deltas are (-50149197655462483,49996250312472658). Hooked deltas are (-150149197655462483,49996250312472658), and DEAD gains 100000000000000000 wei instead of floor(abs(reference.amount0)/100)=501491976554624 wei. From fresh identical state, SwapParams(false,10e18,TickMath.getSqrtPriceAtTick(1)) gives reference ETH output 49996250312472658 wei, but the hooked swap burns 100000000000000000 wei and returns a negative ETH delta of -50003749687527342. If both target pools instead have no liquidity while another pool funds the manager, either request produces reference deltas (0,0), yet the hooked swap charges 0.1 ETH and produces no tokens; the expected burn is zero. Each case starts from its own unchanged initial state.","severity":"medium","title":"Partial fills burn fees for ETH that was never swapped"},{"description":"The hook sends ETH from PoolManager to DEAD inside the swap callback, before the router settles the buyer's ETH input. A valid native pool can contain only token-side liquidity and leave its manager with zero ETH. Both buy shapes then revert during the fee transfer despite sufficient buyer funding and available token liquidity. Trading depends on unrelated ETH already being held by the manager, a precondition absent from the requested design. The fixture seeds two full-range pools with ETH, concealing this case.","line":196,"path":"src/HappyHourHook.sol","reproduction":"Reproduced on local Anvil at timestamp 8683200. Deploy a fresh PoolManager, HAPPY, the production hook at an address with flags 0xCC, PoolSwapTest, and PoolModifyLiquidityTest. Initialize hooked and hookless ETH/HAPPY pools with fee=3000, tickSpacing=60 and sqrtPriceX96=79228162514264337593543950336. Seed each with liquidity=1000e18 only across ticks [-60,0], leaving manager.balance=0. In independent calls from this initial state, use PoolSwapTest.swap{value:10 ether} with TestSettings(false,false), empty hookData, and SwapParams(true,-1e18,4295128740). The hookless pool successfully takes 1000000000000000000 wei and returns 996006981039903216 HAPPY minor units. The hooked pool reverts with a wrapped NativeTransferFailed while attempting its 0.01 ETH burn. Changing amountSpecified to +1e18 reproduces the exact-output buy failure: the reference successfully charges 1004013040121365098 wei for 1e18 HAPPY, while the hook again reverts on the burn. Expected: both funded buys execute and burn their applicable 1% ETH fee within the swap. Run hooked and reference attempts independently so a reference buy does not first fund the shared manager.","severity":"medium","title":"Immediate fee withdrawals block buys in token-only pools"}],"hash":"e18d6463b2910602894a3651a603d6b30b5cac75cd50245504dc17f27f083b1d","nodeId":"afbbcb52-e88c-4b6b-b710-96e158a3a87c","outcome":"completed","summary":"Saved two **medium-severity** findings to [.imd-findings.json](/home/worker/.identitymd/work/c5f15366-9ee3-4aef-a855-a554674d7d90/afbbcb52-e88c-4b6b-b710-96e158a3a87c/.imd-findings.json):\n\n- Partial fills burn fees on unfilled ETH.\n- Token-only pools reject funded buys because fees are withdrawn before settlement.\n\nBoth reproduced locally with the real PoolManager. Source files remain unchanged.","treeHash":null,"usage":{"cachedInputTokens":650368,"inputTokens":74349,"model":"gpt-6-astra","outputTokens":11386,"runtime":"codex","turns":5,"wallClockMs":392864}},{"artifacts":[],"attempt":1,"bundleHash":"d0cef5276d08295e90c12b6224a993cf8f9344808f15c39d03e2caabb43de843","device":"468e82a89b9bfe18","findings":[],"hash":"f8874b45fcb52f285a26cf349225afb26798592434d602e917872b181c9693f3","nodeId":"4d1373fb-4cc8-40fd-8edb-f21405e9d3a3","outcome":"completed","summary":"The deliverable is complete and committed as `f2a861c`. A fresh clone of that commit passes every verifier check offline. The memory directory is write-denied in this sandbox, so no notes were saved there; nothing in the deliverable depends on that.\n\n**What was built**\n\n- `src/HappyHourToken.sol`: OpenZeppelin ERC-20 \"Happy Hour\" / \"HAPPY\", 18 decimals, mints exactly 1e27 to the deployer once. No admin surface.\n- `src/HappyHourHook.sol`: implements v4's `IHooks` directly with permissions beforeSwap, afterSwap and both swap return-delta bits (flag mask 0xCC). Constructor takes only the PoolManager, rejects zero, and validates the address bits. Native-ETH pools only. Fee is charged through the specified delta in `beforeSwap` when ETH is the specified currency, and through the unspecified delta in `afterSwap` otherwise, so every shape burns exactly 1% of what a hookless pool would move. The fee is taken straight from the PoolManager to the dead address and `FeeBurned` is emitted. Schedule and the four views follow the spec literally.\n- `src/HookFlags.sol` and `test/mocks/MockERC20.sol`: required by the protected floor suite, which imports them by relative path.\n- `script/Deploy.s.sol`: reads only `EXPECTED_CHAIN_ID` (0, 31337 or 11155111), mines a salt for the CREATE2 proxy, and performs a single deployment inside the broadcast markers. Tests call `configure` and `deploy` directly.\n- `README.md`, `REVIEW.md`, and ABI exports under `docs/abi/`.\n\n**Verification results**\n\n| Check | Result |\n| --- | --- |\n| `forge build --offline` | clean |\n| `forge test --offline` | 56 passed, 0 failed |\n| `forge fmt --check` | clean |\n| `EXPECTED_CHAIN_ID=0 forge script ... --offline` | success, hook lands on an address ending in `c0cc` |\n| Protected floor suite, run from scratch with real creation code | 9 passed, 0 failed |\n\n**Test coverage highlights**: all four swap shapes against a hookless reference pool outside and inside the free hour, first and last second of the free hour plus one second either side, 72 consecutive days of schedule including the hour-23 and hour-0 wraps, an ERC-20-only pool left untouched, zero hook balances after every swap, fuzz over shape, size and timestamp, and constructor rejection of the zero manager plus missing, extra and unmined address bits.\n\n**Two documented design points worth knowing**\n\n- The fee take happens before the trader settles, so it draws on the PoolManager's pooled ETH balance. That is always available on a live network but would revert on a fresh local manager whose only pool is token-only. Seeding the launch pool with some ETH-side liquidity removes the case.\n- For an exact-output sell that partially fills at a price limit, the fee is 1% of the requested ETH rather than of the filled amount. Both points are in `REVIEW.md` with their disposition.","treeHash":"d370e09b8d00f6430f0cae6821e96e84308ce939","usage":{"cachedInputTokens":2944985,"inputTokens":770,"model":"claude-fable-5-1","outputTokens":83904,"runtime":"claude","turns":42,"wallClockMs":996872}}],"verification":[{"checks":[{"durationMs":5967,"exitCode":0,"name":"build","output":"Compiling 86 files with Solc 0.8.26\nSolc 0.8.26 finished in 5.73s\nCompiler run successful with warnings:\nWarning (2018): Function state mutability can be restricted to view\n   --> test/HappyHourHook.t.sol:270:5:\n    |\n270 |     function assertNoFeeBurnedLog() internal {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/HappyHourToken.t.sol:66:9\n   │\n66 │         token.transferFrom(factory, alice, 1);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/utils/HappyHourFixture.sol:118:31\n    │\n118 │         return swap(k, true, -int256(ethIn), ethIn);\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/utils/HappyHourFixture.sol:122:30\n    │\n122 │         return swap(k, true, int256(tokensOut), ethBudget);\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/utils/HappyHourFixture.sol:126:32\n    │\n126 │         return swap(k, false, -int256(tokensIn), 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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/utils/HappyHourFixture.sol:130:31\n    │\n130 │         return swap(k, false, int256(ethOut), 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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/HappyHourToken.t.sol:72:9\n   │\n72 │         token.transfer(factory, 1);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/utils/HappyHourFixture.sol:146:24\n    │\n146 │         return a < 0 ? uint256(-a) : uint256(a);\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/utils/HappyHourFixture.sol:146:38\n    │\n146 │         return a < 0 ? uint256(-a) : uint256(a);\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/utils/HappyHourFixture.sol:151:24\n    │\n151 │         return a < 0 ? uint256(-a) : uint256(a);\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/utils/HappyHourFixture.sol:151:38\n    │\n151 │         return a < 0 ? uint256(-a) : uint256(a);\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/HappyHourHook.t.sol:128:32\n    │\n128 │         assertEq(d.amount0(), -int256(ethIn), \"user pays exactly what was specified\");\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/HappyHourToken.t.sol:79:9\n   │\n79 │         token.transfer(to, amount);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/HappyHourHook.t.sol:154:31\n    │\n154 │         assertEq(d.amount1(), int256(tokensOut), \"receives exactly the specified tokens\");\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/HappyHourHook.t.sol:173:32\n    │\n173 │         assertEq(d.amount1(), -int256(tokensIn));\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/HappyHourHook.t.sol:194:31\n    │\n194 │         assertEq(d.amount0(), int256(ethOut), \"receives exactly the specified ETH\");\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/HappyHourHook.sol:114:16\n    │\n114 │         return block.timestamp >= start && block.timestamp < start + HOUR;\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/HappyHourHook.sol:114:44\n    │\n114 │         return block.timestamp >= start && block.timestamp < start + HOUR;\n    │                                            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/HappyHourHook.sol:122:16\n    │\n122 │         return block.timestamp < start ? start : happyHourStart(day + 1);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/HappyHourHook.sol:170:43\n    │\n170 │         uint256 ethAmount = amount0 < 0 ? uint256(-amount0) : uint256(amount0);\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/HappyHourHook.sol:170:63\n    │\n170 │         uint256 ethAmount = amount0 < 0 ? uint256(-amount0) : uint256(amount0);\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\n","passed":true},{"durationMs":1613,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 8 tests for test/HappyHourToken.t.sol:HappyHourTokenTest\n[PASS] testFuzz_transferConservesSupply(address,uint256) (runs: 256, μ: 47101, ~: 47432)\n[PASS] test_metadata() (gas: 17739)\n[PASS] test_mintsWholeSupplyToDeployer() (gas: 13633)\n[PASS] test_noMintOrAdminSurface() (gas: 29552)\n[PASS] test_runtimeHasNoDelegatecallOrSelfdestruct() (gas: 532845)\n[PASS] test_transferFrom_respectsAllowance() (gas: 54640)\n[PASS] test_transferMovesExactAmount() (gas: 47636)\n[PASS] test_transfer_insufficientBalanceReverts() (gas: 16143)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 19.16ms (26.19ms CPU time)\n\nRan 7 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_configure_localDeploysScaffoldManager() (gas: 3997846)\n[PASS] test_configure_rejectsMismatch() (gas: 10102)\n[PASS] test_configure_rejectsUnsupportedChain() (gas: 13214)\n[PASS] test_configure_sepolia() (gas: 8120)\n[PASS] test_configure_zeroSkipsAssertion() (gas: 7109)\n[PASS] test_deploy_landsOnFlaggedAddress() (gas: 27988459)\n[PASS] test_deploy_revertsWhenDeployerAssumptionIsWrong() (gas: 15657228)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 79.54ms (133.96ms CPU time)\n\nRan 41 tests for test/HappyHourHook.t.sol:HappyHourHookTest\n[PASS] testFuzz_exactlyOneFreeHourPerDay(uint256) (runs: 256, μ: 3127748, ~: 3130134)\n[PASS] testFuzz_feeAcrossShapesAndTimestamps(uint8,uint256,uint48) (runs: 256, μ: 286740, ~: 287037)\n[PASS] testFuzz_schedule(uint256) (runs: 256, μ: 27174, ~: 27383)\n[PASS] test_boundary_firstSecond_isFree() (gas: 158481)\n[PASS] test_boundary_hour23_runsToDayEnd() (gas: 17248)\n[PASS] test_boundary_hourZero_dayStart() (gas: 14957)\n[PASS] test_boundary_lastSecond_isFree() (gas: 158557)\n[PASS] test_boundary_secondAfterEnd_charges() (gas: 197559)\n[PASS] test_boundary_secondBeforeStart_charges() (gas: 197252)\n[PASS] test_buyExactIn_charges1pctOfEthIn() (gas: 299399)\n[PASS] test_buyExactIn_vsReferenceSameParams() (gas: 277276)\n[PASS] test_buyExactOut_charges1pctOfEthIn() (gas: 311625)\n[PASS] test_callbacks_refuseNonManager() (gas: 19532)\n[PASS] test_callbacks_refuseNonManagerEvenAsPrankedRouter() (gas: 18536)\n[PASS] test_consecutiveSwapsAccumulateAtDead() (gas: 374696)\n[PASS] test_constructor_rejectsAddressWithoutFlags() (gas: 41378)\n[PASS] test_constructor_rejectsExtraFlags() (gas: 50675130)\n[PASS] test_constructor_rejectsPartialFlags() (gas: 592353)\n[PASS] test_constructor_rejectsZeroPoolManager() (gas: 9317595)\n[PASS] test_constructor_rejectsZeroPoolManagerBeforeCheckingAddress() (gas: 36820)\n[PASS] test_constructor_setsPoolManager() (gas: 8030)\n[PASS] test_currentFeeBps_matchesIsHappyHour() (gas: 15583)\n[PASS] test_erc20Pool_isUntouched() (gas: 2250366)\n[PASS] test_feeRoundsDown_andSkipsDust() (gas: 265988)\n[PASS] test_happyHour_buyExactIn_isFree() (gas: 259174)\n[PASS] test_happyHour_buyExactOut_isFree() (gas: 271163)\n[PASS] test_happyHour_emitsNothing() (gas: 143195)\n[PASS] test_happyHour_sellExactIn_isFree() (gas: 242665)\n[PASS] test_happyHour_sellExactOut_isFree() (gas: 244503)\n[PASS] test_nextHappyHour_afterTodays_pointsToTomorrow() (gas: 13047)\n[PASS] test_nextHappyHour_atExactStart_pointsToTomorrow() (gas: 12083)\n[PASS] test_nextHappyHour_beforeTodays() (gas: 11509)\n[PASS] test_nextHappyHour_duringTodays_pointsToTomorrow() (gas: 13968)\n[PASS] test_permissions_onlySwapCallbacks() (gas: 9002)\n[PASS] test_schedule_consecutiveDays() (gas: 237054)\n[PASS] test_schedule_realDate() (gas: 6122)\n[PASS] test_schedule_wrapsFrom23() (gas: 13441)\n[PASS] test_sellExactIn_charges1pctOfEthOut() (gas: 283198)\n[PASS] test_sellExactOut_charges1pctOfEthOut() (gas: 284919)\n[PASS] test_sellExactOut_vsReferenceSameParams() (gas: 262488)\n[PASS] test_undeclaredCallbacks_revert() (gas: 18791)\nSuite result: ok. 41 passed; 0 failed; 0 skipped; finished in 1.35s (1.50s CPU time)\n\nRan 3 test suites in 1.36s (1.45s CPU time): 56 tests passed, 0 failed, 0 skipped (56 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"113f12ec7453620e166bb17d3799e4a660f49f12c3c977eb653e9956731d9269","verifiedTreeHash":"9dc358fd27fd28f322d528a637e840a1d472e623","verifierVersion":"0.1.0+bb39ded9"},{"checks":[{"durationMs":2177,"exitCode":0,"name":"build","output":"Compiling 86 files with Solc 0.8.26\nSolc 0.8.26 finished in 2.09s\nCompiler run successful with warnings:\nWarning (2018): Function state mutability can be restricted to view\n   --> test/HappyHourHook.t.sol:270:5:\n    |\n270 |     function assertNoFeeBurnedLog() internal {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/HappyHourToken.t.sol:66:9\n   │\n66 │         token.transferFrom(factory, alice, 1);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/HappyHourHook.sol:114:16\n    │\n114 │         return block.timestamp >= start && block.timestamp < start + HOUR;\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/HappyHourHook.sol:114:44\n    │\n114 │         return block.timestamp >= start && block.timestamp < start + HOUR;\n    │                                            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/HappyHourHook.sol:122:16\n    │\n122 │         return block.timestamp < start ? start : happyHourStart(day + 1);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/utils/HappyHourFixture.sol:118:31\n    │\n118 │         return swap(k, true, -int256(ethIn), ethIn);\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/utils/HappyHourFixture.sol:122:30\n    │\n122 │         return swap(k, true, int256(tokensOut), ethBudget);\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/utils/HappyHourFixture.sol:126:32\n    │\n126 │         return swap(k, false, -int256(tokensIn), 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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/utils/HappyHourFixture.sol:130:31\n    │\n130 │         return swap(k, false, int256(ethOut), 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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/utils/HappyHourFixture.sol:146:24\n    │\n146 │         return a < 0 ? uint256(-a) : uint256(a);\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/utils/HappyHourFixture.sol:146:38\n    │\n146 │         return a < 0 ? uint256(-a) : uint256(a);\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/utils/HappyHourFixture.sol:151:24\n    │\n151 │         return a < 0 ? uint256(-a) : uint256(a);\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/utils/HappyHourFixture.sol:151:38\n    │\n151 │         return a < 0 ? uint256(-a) : uint256(a);\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/HappyHourToken.t.sol:72:9\n   │\n72 │         token.transfer(factory, 1);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/HappyHourHook.t.sol:128:32\n    │\n128 │         assertEq(d.amount0(), -int256(ethIn), \"user pays exactly what was specified\");\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/HappyHourToken.t.sol:79:9\n   │\n79 │         token.transfer(to, amount);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/HappyHourHook.sol:170:43\n    │\n170 │         uint256 ethAmount = amount0 < 0 ? uint256(-amount0) : uint256(amount0);\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/HappyHourHook.sol:170:63\n    │\n170 │         uint256 ethAmount = amount0 < 0 ? uint256(-amount0) : uint256(amount0);\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/HappyHourHook.t.sol:154:31\n    │\n154 │         assertEq(d.amount1(), int256(tokensOut), \"receives exactly the specified tokens\");\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/HappyHourHook.t.sol:173:32\n    │\n173 │         assertEq(d.amount1(), -int256(tokensIn));\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/HappyHourHook.t.sol:194:31\n    │\n194 │         assertEq(d.amount0(), int256(ethOut), \"receives exactly the specified ETH\");\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://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\n","passed":true},{"durationMs":658,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 8 tests for test/HappyHourToken.t.sol:HappyHourTokenTest\n[PASS] testFuzz_transferConservesSupply(address,uint256) (runs: 256, μ: 47113, ~: 47432)\n[PASS] test_metadata() (gas: 17739)\n[PASS] test_mintsWholeSupplyToDeployer() (gas: 13633)\n[PASS] test_noMintOrAdminSurface() (gas: 29552)\n[PASS] test_runtimeHasNoDelegatecallOrSelfdestruct() (gas: 532845)\n[PASS] test_transferFrom_respectsAllowance() (gas: 54640)\n[PASS] test_transferMovesExactAmount() (gas: 47636)\n[PASS] test_transfer_insufficientBalanceReverts() (gas: 16143)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 4.72ms (5.82ms CPU time)\n\nRan 7 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_configure_localDeploysScaffoldManager() (gas: 3997846)\n[PASS] test_configure_rejectsMismatch() (gas: 10102)\n[PASS] test_configure_rejectsUnsupportedChain() (gas: 13214)\n[PASS] test_configure_sepolia() (gas: 8120)\n[PASS] test_configure_zeroSkipsAssertion() (gas: 7109)\n[PASS] test_deploy_landsOnFlaggedAddress() (gas: 27988459)\n[PASS] test_deploy_revertsWhenDeployerAssumptionIsWrong() (gas: 15657228)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 21.39ms (36.30ms CPU time)\n\nRan 41 tests for test/HappyHourHook.t.sol:HappyHourHookTest\n[PASS] testFuzz_exactlyOneFreeHourPerDay(uint256) (runs: 256, μ: 3121540, ~: 3119952)\n[PASS] testFuzz_feeAcrossShapesAndTimestamps(uint8,uint256,uint48) (runs: 256, μ: 286109, ~: 287037)\n[PASS] testFuzz_schedule(uint256) (runs: 256, μ: 27213, ~: 27499)\n[PASS] test_boundary_firstSecond_isFree() (gas: 158481)\n[PASS] test_boundary_hour23_runsToDayEnd() (gas: 17248)\n[PASS] test_boundary_hourZero_dayStart() (gas: 14957)\n[PASS] test_boundary_lastSecond_isFree() (gas: 158557)\n[PASS] test_boundary_secondAfterEnd_charges() (gas: 197559)\n[PASS] test_boundary_secondBeforeStart_charges() (gas: 197252)\n[PASS] test_buyExactIn_charges1pctOfEthIn() (gas: 299399)\n[PASS] test_buyExactIn_vsReferenceSameParams() (gas: 277276)\n[PASS] test_buyExactOut_charges1pctOfEthIn() (gas: 311625)\n[PASS] test_callbacks_refuseNonManager() (gas: 19532)\n[PASS] test_callbacks_refuseNonManagerEvenAsPrankedRouter() (gas: 18536)\n[PASS] test_consecutiveSwapsAccumulateAtDead() (gas: 374696)\n[PASS] test_constructor_rejectsAddressWithoutFlags() (gas: 41378)\n[PASS] test_constructor_rejectsExtraFlags() (gas: 50675130)\n[PASS] test_constructor_rejectsPartialFlags() (gas: 592353)\n[PASS] test_constructor_rejectsZeroPoolManager() (gas: 9317595)\n[PASS] test_constructor_rejectsZeroPoolManagerBeforeCheckingAddress() (gas: 36820)\n[PASS] test_constructor_setsPoolManager() (gas: 8030)\n[PASS] test_currentFeeBps_matchesIsHappyHour() (gas: 15583)\n[PASS] test_erc20Pool_isUntouched() (gas: 2250366)\n[PASS] test_feeRoundsDown_andSkipsDust() (gas: 265988)\n[PASS] test_happyHour_buyExactIn_isFree() (gas: 259174)\n[PASS] test_happyHour_buyExactOut_isFree() (gas: 271163)\n[PASS] test_happyHour_emitsNothing() (gas: 143195)\n[PASS] test_happyHour_sellExactIn_isFree() (gas: 242665)\n[PASS] test_happyHour_sellExactOut_isFree() (gas: 244503)\n[PASS] test_nextHappyHour_afterTodays_pointsToTomorrow() (gas: 13047)\n[PASS] test_nextHappyHour_atExactStart_pointsToTomorrow() (gas: 12083)\n[PASS] test_nextHappyHour_beforeTodays() (gas: 11509)\n[PASS] test_nextHappyHour_duringTodays_pointsToTomorrow() (gas: 13968)\n[PASS] test_permissions_onlySwapCallbacks() (gas: 9002)\n[PASS] test_schedule_consecutiveDays() (gas: 237054)\n[PASS] test_schedule_realDate() (gas: 6122)\n[PASS] test_schedule_wrapsFrom23() (gas: 13441)\n[PASS] test_sellExactIn_charges1pctOfEthOut() (gas: 283198)\n[PASS] test_sellExactOut_charges1pctOfEthOut() (gas: 284919)\n[PASS] test_sellExactOut_vsReferenceSameParams() (gas: 262488)\n[PASS] test_undeclaredCallbacks_revert() (gas: 18791)\nSuite result: ok. 41 passed; 0 failed; 0 skipped; finished in 563.90ms (620.91ms CPU time)\n\nRan 3 test suites in 565.07ms (590.01ms CPU time): 56 tests passed, 0 failed, 0 skipped (56 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"f8874b45fcb52f285a26cf349225afb26798592434d602e917872b181c9693f3","verifiedTreeHash":"d370e09b8d00f6430f0cae6821e96e84308ce939","verifierVersion":"0.1.0+bb39ded9"}]}