{"assessments":[],"deployments":[{"attestationHash":"2fe514ad1ae3b132127388b056809a1b66c55d6510ad312706f9962fa10a0ae7","chainId":1,"contracts":[{"address":"0x5d2c8b3d792652a88bbf13cd3633b6c5abb10d30","blockNumber":26142669,"name":"MerkleDistributor","role":"distributor","txHash":"0xbd9054c58ea54980d017c0a7d5d12290726c449e23b9bddbdde91d666587b441"},{"address":"0xe52ab551160a74afed336c1fbf0f5d39b6fd4bba","blockNumber":26142669,"name":"PanicMonkeys","role":"token","txHash":"0xbd9054c58ea54980d017c0a7d5d12290726c449e23b9bddbdde91d666587b441"},{"address":"0xd78b3596cc0cad5afb799e270ba56a7a4af935cf","blockNumber":26142669,"name":"PanicHook","role":"hook","txHash":"0xbd9054c58ea54980d017c0a7d5d12290726c449e23b9bddbdde91d666587b441"}],"id":"78f747c8-2875-4984-a053-c0777cff1904","manifestHash":"a5b9d6e5aa63ad8eb0e7740b262e7e33d20073e616165ca011293ea969b72c14","status":"live"}],"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":"8540825c-a412-4c3d-be82-73cdf9002e30","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"bd245b8198f77c9f846e4dbb301c99868b05c4c0095f1bd1581eec1d750fbf1b","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_economics","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"8721f64a9681d02efee9cf360be33499dc52a29ee0fb23c56eea83709af127d0","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_flow","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"3869d926e654cbea12aafb36d3573148e3e386f65fe9ed4118ba970a1f8134db","dependsOn":["build_contract_project","write_foundry_tests","manifest","audit_math","audit_permissions","audit_economics","audit_flow"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"3014f1ea5961918ca059453a484bf4c8bcbbfc2248dbe31d94ac7c5cdf8f50bd","skillId":"audit-judge","tools":[]},"key":"audit_judge","kind":"code","role":"review","skillHash":"3014f1ea5961918ca059453a484bf4c8bcbbfc2248dbe31d94ac7c5cdf8f50bd","skillId":"audit-judge","state":"accepted"},{"acceptedSubmissionHash":"a4961e0ec6eb095d2b1d2ea97b82aa58af6817071b2cb1c0bdc566ada9c57de7","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_math","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"021280c523a88b3b365c925e5efa4dafe5a1ae3099d9f073dbe7ee0b10a50984","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_permissions","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"2b3222ccdf21e4552087551370c8689293ab1a8009984760be5851db44637f2e","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":"accepted"},{"acceptedSubmissionHash":"0161f705c0547bc761008c5dfea08b0762cba6474e8910facb4cbab2fba2721f","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"2019edc1fd2cb3bf3dd2f6d4963a6dc14c9073336d47773cf08e94ef78e6c2fc","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":"accepted"}],"objective":"START FROM EXISTING CODE: reuse https://github.com/identity-md-launches/launch-905-launch-panic-monkeys-panic at commit fe78b5defb150e3071181c675534e5e438a120da (fully built, tested and audited). Only two changes: set oracleFund to 0x788C311500FD3C15b8e44d6e2935fe7fF13E674b in launch.json/constructor, and remove the anti-splitting test. Keep everything else identical.\n\nLaunch Panic Monkeys ($PANIC, ERC-20 name \"Panic Monkeys\", symbol \"PANIC\") with a Uniswap v4 hook. The hook punishes selling while the price is down and makes dip buying cheap.\n\nREFERENCE PRICE: the hook keeps its own 1-hour time-weighted average price (TWAP) of this pool. It records at most one observation per block, using the pool price before the first swap of that block, so trades in the current block can never move the reference. Drawdown = how far the price is below the reference, in percent. \"Down\" means drawdown of 5% or more.\n\nHOOK FEE (on top of the pool's base fee), taken in the paired currency (the non-PANIC side): from the input on buys (beforeSwap return delta), from the output on sells (afterSwap return delta).\n- Buys, judged on the price before the buy: 0% when drawdown < 5%; 1% when drawdown >= 5%.\n- Sells, judged on the price AFTER the sell: 2% when drawdown < 5%; 10% when 5% <= drawdown < 15%; 20% when 15% <= drawdown < 30%; 30% when drawdown >= 30%.\n- No exemptions for any address. Hook fee never exceeds 30%.\n\nFEE SPLIT of every hook fee: 60% accrues to a Panic Oracle Fund claimable only to the fixed oracle budget address 0x788C311500FD3C15b8e44d6e2935fe7fF13E674b (hardcode this literal address as the oracleFund recipient in the deploy manifest and constructor; never the zero address); 30% is donated to in-range liquidity providers with PoolManager.donate; 10% accrues to a burn bucket: a permissionless buybackAndBurn() swaps it for PANIC in this pool and sends the PANIC to 0x000000000000000000000000000000000000dEaD; it reverts if it would receive less than 98% of the PANIC implied by the 1-hour reference price, and spends at most a capped amount per call. Claim, donate and buybackAndBurn are permissionless functions anyone can call. No dust may stay stuck.\n\nADMIN: nobody can change fees, thresholds, splits or the reference window after deployment. No owner, no pause, no upgrade.\n\nKNOWN AND ACCEPTED: splitting one large sell into many small sells pays less total tax than one sell (early chunks land at lower tiers). This is intended; do not add per-wallet tracking.\n\nREQUIRED TESTS: tiers switch exactly at 5%, 15%, 30% drawdown; a sell moving price from not-down to 20% down pays 20%; a buy and a sell in the same block cannot move the reference; after the price sits down but flat for 1 hour the panic tier no longer applies; the fee split sums to exactly 100%; hook fee capped at 30%; buybackAndBurn reverts when the price is more than 2% above the reference and all PANIC it buys ends at 0x...dEaD.","parentJobId":null,"planHash":"854dba5f64c9fd7ec9888f14e09a418ccdfc3d39ac0791faad262903c67dd152","previousHash":"b91e4a1e1539b0d91d882053b90881715c98dfa8e9ea3a190aa3828763dde780","projectId":"8540825c-a412-4c3d-be82-73cdf9002e30","publication":{"commit":"3638b78b9a22e168e6ed477187e4d00712bfcbb6","deliveredAt":"2026-10-07T19:39:57.228Z","repoUrl":"https://github.com/identity-md-launches/launch-922-start-existing-code-reuse"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[],"site":null,"snapshotHash":"194f443fc3c51b6f81563f0f20f897f5336f08ded0028a73e172d843f708f8f2","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"4e91f21c7d3eb10bf66b8e6b8a045fe821d736f4baed40c68b1ca01cb311aa24","device":"4ca9ed4f0937da89","findings":[],"hash":"0161f705c0547bc761008c5dfea08b0762cba6474e8910facb4cbab2fba2721f","nodeId":"4cb57aad-4681-42e4-affd-58a57b2c40ed","outcome":"completed","summary":"I left the starting price unchanged, disputed the reviewer's finding about it, and rewrote one sentence of the notes in `launch.json`. `forge build` succeeds and `forge test` passes all 120 tests in 15 suites.\n\n**The finding.** The reviewer's arithmetic is right: a starting price of 2^96 opens the pool at 1 PANIC per IMD (both tokens have 18 decimals). That implies a total value of 1e9 IMD, against an IMD supply of about 4.1M. I kept it because:\n- **PANIC's side of the pair isn't known yet.** It depends on which address sorts lower, and PANIC's address only exists once it is deployed. Any other value would mean opposite prices depending on which way the pair sorts, and the manifest has no field to say which way. 2^96 is the only value that means the same price either way.\n- **The brief sets no PANIC/IMD price.** It says to keep everything except the oracle fund address identical to the accepted launch at `fe78b5d`, which uses 2^96.\n- **I can't see the seed amounts.** They come from the separate launch policy, so I had nothing to work out a price from.\n\n**Notes change.** The notes said the price \"follows the deployment test\". They now give the reasoning above and ask the launch policy to confirm the price and seed sizes. The notes are 3,524 characters, under the 4,000 cap. My answer to the reviewer is in `.imd-responses.json`.\n\n**Checked, no change needed:**\n- The oracle fund address `0x788C311500FD3C15b8e44d6e2935fe7fF13E674b` is already in the manifest's constructor arguments, and the anti-splitting tests were already removed.\n- The 10 permissions in the manifest match what `getHookPermissions` returns in the current `PanicHook`.\n- The other manifest values are the token name and symbol, pair token `0xd34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7`, fee 12500, `$poolManager`/`$token`, and `\"kind\"` first. These match the brief.\n\n**Not fixed:** `README.md:165` still describes the pool as PANIC/ETH. That's outside what this task may edit, which is `launch.json` only.\n\nThe earlier attempt failed when restoring prior work. This checkout already had that work applied, so nothing needed redoing.","treeHash":"777ee493c79a0df760de7c79fdfaa4925a2be9cb","usage":{"cachedInputTokens":294861,"inputTokens":12,"model":"claude-opus-5-5","outputTokens":3221,"runtime":"claude","turns":6,"wallClockMs":698228}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"4eb5b0156b09157c","findings":[],"hash":"021280c523a88b3b365c925e5efa4dafe5a1ae3099d9f073dbe7ee0b10a50984","nodeId":"be30ced6-4339-4759-a839-3fcec806b4fb","outcome":"completed","summary":"Saved [.imd-findings.json](/home/imd/.identitymd/work/8540825c-a412-4c3d-be82-73cdf9002e30/be30ced6-4339-4759-a839-3fcec806b4fb/.imd-findings.json).\n\nNo substantiated defects in the assigned scope. All 12 entry points covered; offline Foundry tests passed. Implementation unchanged.","treeHash":null,"usage":{"cachedInputTokens":1540480,"inputTokens":130514,"model":"gpt-6-astra","outputTokens":6740,"runtime":"codex","turns":6,"wallClockMs":339119}},{"artifacts":[],"attempt":2,"bundleHash":null,"device":"02c6a88ea85b2673","findings":[],"hash":"1802f37868adb6a2e7ba80290f9b4db3fb02b9a6e42125933616682c542aa2ea","nodeId":"b41d7c2f-ead1-4e77-8741-7e0763c53e15","outcome":"failed","summary":"runtime reported <synthetic>, not the required premium model claude-fable-5-1","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":"<synthetic>","outputTokens":0,"runtime":"claude","turns":1,"wallClockMs":2488}},{"artifacts":[],"attempt":1,"bundleHash":"a1f28bf819c3ca8382e33ec5acc75d52865846d34125117cd8cd46f591151aa2","device":"e2a4a53638df3fc6","findings":[],"hash":"2019edc1fd2cb3bf3dd2f6d4963a6dc14c9073336d47773cf08e94ef78e6c2fc","nodeId":"ec86f4a4-a923-478f-8a4f-ac9135a6532c","outcome":"completed","summary":"The new same-block liquidity rule in the hook is now covered by the invariant tests, and I found no defects in it. The whole suite passes: 139 tests, plus repeated invariant runs with fuzz seeds 1, 2 and 3. I didn't write `.imd-findings.json` because there was nothing to report.\n\n**Why this revision:** after my last round, the hook gained a rule for liquidity added in the current block. If a position is added to and then touched again in the same block, it gives up the fees it earned in between. Those fees are donated to the other in-range liquidity, or, if none is left, the paired-currency part waits in the donation bucket and the PANIC part goes to the dead address. Only `test/PanicHook.Jit.t.sol` tested this, and none of the random-sequence tests ever added or removed liquidity.\n\n**What changed** (`test/handlers/PanicAccountingHandler.sol`, `test/PanicHook.Invariant.t.sol`, `test/README.md`):\n- **Two new random actions.** Three traders now add and remove their own narrow positions near the current price, through a separate router. This includes second adds in the same block and partial and full removals. The three campaigns (native ETH, PANIC as currency0, PANIC as currency1) each still run 256 sequences of 64 calls with no unexpected reverts.\n- **What is checked after each liquidity change:**\n  - An add pays exactly the principal, worked out with v4-core's own price maths rather than anything in the hook. For a position added in an earlier block, fees are first collected with a zero-size touch.\n  - A removal in the same block as the last add returns exactly the principal, so every fee earned in between was given up.\n  - A removal in a later block returns at least the principal, so the position keeps its fees.\n  - The fee buckets, `totalDonated` and the hook's claim balance don't change.\n  - The new router ends up holding no PANIC and no paired currency.\n- **One fixed-sequence test**, `test_handlerLiquidityAroundTradesInAndAcrossBlocks`, checks that a `SameBlockFeesForfeited` event with a non-zero amount is actually emitted, so the forfeit path isn't passing only because there were no fees.\n\n**Limits:**\n- The full-range liquidity always stays in place in these campaigns. Given-up fees therefore always go to other liquidity providers, and the empty-pool case (fees to the donation bucket and the dead address) is only covered by the existing `PanicHook.Jit.t.sol` test.\n- A position that collects its fees in the next block keeps them. The hook only stops recapture within one block, which is what its documentation says.\n- I ran the two protected test files from `.imd/reads` locally. The hook one stops in setup because it needs an `IMD_HOOK_CREATION_CODE` environment variable that I assume the verifier sets, and the token one was skipped. So I couldn't confirm either passes; I didn't add them to `test/`.\n\nThe three changed files are not committed yet.","treeHash":"25de6272f0f8a812f9330563211ec1f499c99717","usage":{"cachedInputTokens":1894137,"inputTokens":46,"model":"claude-opus-5-5","outputTokens":20968,"runtime":"claude","turns":24,"wallClockMs":662193}},{"artifacts":[],"attempt":3,"bundleHash":"45259740e3f6015bfa55a8b4ff860c8fc38c5c6578fb347bd1340f5e71d07bc8","device":"d20c1a95c50699ea","findings":[],"hash":"2b3222ccdf21e4552087551370c8689293ab1a8009984760be5851db44637f2e","nodeId":"5ab1373f-577d-4afa-9d17-f9ba02defd6c","outcome":"completed","summary":"I fixed the medium finding (a seller recapturing their own LP donation), and the reviewer's proof now passes. `forge build`, `forge test` (120 tests, none failing) and `forge fmt --check` all pass, and the protected Hook and Token checks pass with the new permission flags. Every finding has an answer in `.imd-responses.json`.\n\n**Medium finding (seller recaptures their own LP donation) — fixed.** I reproduced it: the same-transaction liquidity trick netted the seller 895,165,288,354,306,168,498 wei against 833,287,503,445,022,331,968 for a plain seller. The reviewer suggested holding the donation until a later block, but their own proof also requires the LP share to be donated inside the swap. So the hook keeps donating in the swap and instead takes back fees from liquidity that comes and goes within one block:\n- The hook now also runs after liquidity is added or removed, and records the block each position was last added to.\n- If a position added to in the current block is touched again in that same block, the fees it would collect are taken back and donated to the liquidity that stays in range. If no liquidity is left in range, the paired-currency part waits in the donation bucket and the PANIC part goes to `0x…dEaD`.\n- Result: the trick now nets the seller 1 wei less than a plain sell. LPs who hold across a block boundary keep their fees.\n- **Trade-off:** an honest LP who adds and then collects, or adds again, within one block loses the fees earned in between. This is stated in the README and the `launch.json` notes.\n- **This changes the hook address:** the permission flags go from `0x30cc` to `0x35cf`, so a fresh CREATE2 salt must be mined. I updated `HookFlags.sol`, the permissions in `launch.json` and the README to match.\n- New tests are in `test/PanicHook.Jit.t.sol`. Two existing donation tests collected the resident LP's fees in the same block the LP was added, which now counts as a same-block touch, so they move one block forward first.\n\n**Advisory findings:**\n- **98% buyback floor rounding — fixed.** The minimum is now 98% of the exact reference quote, rounded up, rather than 98% of an already rounded-down quote. The reviewer's case now reverts with `BuybackBelowReference(20, 21)` (new test `test_buybackFloorUsesTheUnroundedReferenceQuote`). One existing dust test now expects a minimum of 13 instead of 12.\n- **Buyback cap vs. the IMD pair — docs fixed, cap unchanged.** The README now says `launch.json` pairs PANIC with the IMD token, that the deploy script and most tests use native ETH, and that one call spends at most 1 IMD, with the gas cost that implies. Whether to change the cap is a launch decision.\n- **Exact-output sells and partially filled dip buys revert — documented.** The routing rule (send sells exact-input, price-limited dip buys exact-output) is now in the `launch.json` notes and README. Nothing is charged when these revert.\n- **Dust left in the burn bucket — disputed.** The leftover unit is not lost; it is spent together with the next burn share a taxed swap adds. Clearing it otherwise would mean sending it to LPs or another bucket.\n- **Reference rounded to a whole tick — no change.** This is the standard Uniswap TWAP definition, off by at most 0.01%, and already documented and tested.\n\nThe rejected attempt's failing buyback and fee-split tests don't fail on the current tree.\n\nNot run: Slither or other static analysis, chain forks, and any deployment transaction.","treeHash":"c08b4e0f62de09d5ae86c3d2213b63822bfb5dbb","usage":{"cachedInputTokens":2950507,"inputTokens":56,"model":"claude-opus-5-5","outputTokens":32683,"runtime":"claude","turns":33,"wallClockMs":697951}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"99c6d0bcc495ad61","findings":[],"hash":"3869d926e654cbea12aafb36d3573148e3e386f65fe9ed4118ba970a1f8134db","nodeId":"b41d7c2f-ead1-4e77-8741-7e0763c53e15","outcome":"completed","summary":"Review complete. The revised code settles every finding from the previous round, and nothing new reproduced as a defect. `.imd-findings.json` holds an empty findings list and a 22-row coverage record covering all 14 entry points plus the settled items. No tracked files were changed.\n\n**Settlement of my earlier findings**\n\n- **JIT self-recapture (medium): fixed.** The attached proof, copied to the scratch folder and run against the revised hook, now passes. The JIT seller nets 1 wei less than a plain seller. The fix adds afterAddLiquidity and afterRemoveLiquidity with return deltas, records each position's last add block, and forfeits the fees any same-block touch collects by donating them to the remaining in-range liquidity. I traced the delta accounting in the vendored PoolManager, confirmed the position key matches the manager's owner derivation, and verified with a scratch test that removal never reverts even when the touched position was the only liquidity. Hook flags 0x35cf match the manifest. All 139 project tests pass.\n- **98% floor rounding (low): fixed.** The minimum is now the ceiling of the unrounded 98% quote. I checked the carry arithmetic by hand and the author's regression test reverts with the expected BuybackBelowReference(20, 21) on my original scenario.\n- **Dust burn bucket, buyback cap in IMD, initialPrice basis, exact-output sells, tick quantization: dropped.** Each is now documented in the README or manifest notes, loses no funds, and the author's disputes hold against the brief's wording. The specialists' four economics items and the two math/flow dust items are the same root causes and were merged into these rows.\n\n**One residual, recorded in coverage rather than as a finding**\n\nA position added one block before the sell and removed in the sell block still recaptures 99% of the donation. That is exactly the cross-block bar my earlier finding set, it requires real capital held with price exposure, and the README states it. Raising it again would be a new objection to the agreed design, so it is noted on the afterRemoveLiquidity row with the measured numbers.\n\n**Static analysis leads** were all traced and none is a defect. The modulo operations are exact-rounding checks, the strict equalities are the once-per-block guards, and the int24 cast is a mean of in-range ticks.","treeHash":null,"usage":{"cachedInputTokens":1306176,"inputTokens":324,"model":"claude-fable-5-1","outputTokens":30980,"runtime":"claude","turns":21,"wallClockMs":770100}},{"artifacts":[],"attempt":3,"bundleHash":null,"device":"7c748c02cd2ee98f","findings":[{"citation":"resolved","description":"_split donates the LP share inside afterSwap to whatever liquidity is in range at the post-swap tick. A seller controls that tick (through sqrtPriceLimitX96) and can, in the same transaction, add a narrow position whose lower edge is the end tick, sell, and remove the position. PoolManager.donate pays feeGrowth pro rata to in-range liquidity, so with liquidity far above the resident liquidity the seller's own position receives almost the whole donation of the seller's own hook fee. The capital is only needed for one transaction (flash-loanable) and the self-trade across the edge is negligible when the sell stops one sqrt-price unit above the range's lower edge. Result: 30% of the hook fee flows straight back to the seller, so the 2/10/20/30% schedule is effectively 1.4/7/14/21% for any seller who wraps the sell in a JIT position. The brief's 'No exemptions for any address' and 'punishes selling while the price is down' are weakened for sophisticated sellers, and the LP share meant for resident liquidity providers is paid to the taxed party. README.md only acknowledges JIT exposure for third parties and for the fallback bucket; the self-recapture and its effect on the sell tax are not stated. This is not the accepted sell-splitting behaviour (no per-wallet tracking is needed to address it). A minimal fix that keeps the required donate mechanism: do not donate in the taxed swap's own transaction; keep the LP share in donationBucket and flush it at the next block's first observation (_observe) or via donateToLiquidityProviders, so capturing it requires holding liquidity across blocks with real price exposure. Alternatively require donationBucket to be flushed only when the block of accrual has passed.","line":672,"path":"src/PanicHook.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {PoolManager} from \"v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"v4-core/src/interfaces/IPoolManager.sol\";\nimport {IHooks} from \"v4-core/src/interfaces/IHooks.sol\";\nimport {PoolKey} from \"v4-core/src/types/PoolKey.sol\";\nimport {PoolId} from \"v4-core/src/types/PoolId.sol\";\nimport {Currency, CurrencyLibrary} from \"v4-core/src/types/Currency.sol\";\nimport {ModifyLiquidityParams, SwapParams} from \"v4-core/src/types/PoolOperation.sol\";\nimport {StateLibrary} from \"v4-core/src/libraries/StateLibrary.sol\";\nimport {TickMath} from \"v4-core/src/libraries/TickMath.sol\";\nimport {PoolSwapTest} from \"v4-core/src/test/PoolSwapTest.sol\";\nimport {PoolModifyLiquidityTest} from \"v4-core/src/test/PoolModifyLiquidityTest.sol\";\nimport {PanicMonkeys} from \"src/PanicMonkeys.sol\";\nimport {PanicHook} from \"src/PanicHook.sol\";\nimport {HookMiner} from \"src/HookMiner.sol\";\nimport {HookFlags} from \"src/HookFlags.sol\";\n\n/// @notice A seller who adds a narrow liquidity position at the tick where their own sell ends, in the same\n/// transaction, receives most of the 30% LP donation that `_split` pays out inside `afterSwap`, and withdraws it\n/// right after. The seller's net paired proceeds exceed a plain seller's by most of the donation.\n/// Fails on the current code; passes once the LP share can no longer be captured by same-transaction liquidity.\ncontract JitRecaptureTest is Test {\n    using StateLibrary for IPoolManager;\n\n    uint160 constant SQRT_PRICE_1_1 = 79228162514264337593543950336;\n    int24 constant TICK_SPACING = 100;\n    address constant ORACLE_FUND = 0x788C311500FD3C15b8e44d6e2935fe7fF13E674b;\n\n    PoolManager manager;\n    PanicMonkeys panic;\n    PanicHook hook;\n    PoolSwapTest swapRouter;\n    PoolModifyLiquidityTest lpRouter;\n    PoolKey key;\n    PoolId poolId;\n\n    receive() external payable {}\n\n    function setUp() public {\n        vm.warp(1_800_000_000);\n        vm.roll(1_000);\n        manager = new PoolManager(address(this));\n        panic = new PanicMonkeys();\n        swapRouter = new PoolSwapTest(IPoolManager(address(manager)));\n        lpRouter = new PoolModifyLiquidityTest(IPoolManager(address(manager)));\n\n        bytes memory creationCode = abi.encodePacked(\n            type(PanicHook).creationCode, abi.encode(IPoolManager(address(manager)), address(panic), ORACLE_FUND)\n        );\n        (address predicted, bytes32 salt) =\n            HookMiner.find(address(this), HookFlags.PANIC_HOOK, creationCode, 0, 1_000_000);\n        hook = new PanicHook{salt: salt}(IPoolManager(address(manager)), address(panic), ORACLE_FUND);\n        assertEq(address(hook), predicted);\n\n        // PANIC / native ETH pool: ETH is currency0, PANIC is currency1.\n        key = PoolKey({\n            currency0: CurrencyLibrary.ADDRESS_ZERO,\n            currency1: Currency.wrap(address(panic)),\n            fee: 12_500,\n            tickSpacing: TICK_SPACING,\n            hooks: IHooks(address(hook))\n        });\n        poolId = key.toId();\n        manager.initialize(key, SQRT_PRICE_1_1);\n\n        vm.deal(address(this), 1e27);\n        panic.approve(address(swapRouter), type(uint256).max);\n        panic.approve(address(lpRouter), type(uint256).max);\n        _addLiquidity(TickMath.minUsableTick(TICK_SPACING), TickMath.maxUsableTick(TICK_SPACING), 1e22);\n    }\n\n    function _addLiquidity(int24 lower, int24 upper, int256 liquidityDelta) internal {\n        lpRouter.modifyLiquidity{value: liquidityDelta > 0 ? 1e25 : 0}(\n            key, ModifyLiquidityParams({tickLower: lower, tickUpper: upper, liquidityDelta: liquidityDelta, salt: 0}), \"\"\n        );\n    }\n\n    /// @dev Exact-input sell of PANIC (oneForZero) up to a price limit.\n    function _sellPanicToPrice(uint160 limit) internal {\n        swapRouter.swap(\n            key,\n            SwapParams({zeroForOne: false, amountSpecified: -int256(1e26), sqrtPriceLimitX96: limit}),\n            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false}),\n            \"\"\n        );\n    }\n\n    function test_sameTransactionJitLiquidityMustNotRecaptureTheSellersOwnTax() public {\n        // The 20% tier sits at about tick 2231 from a 1:1 start. Both sellers stop at tick 2200 (19.75% down,\n        // still the 20% tier).\n        int24 lower = 2200;\n        int24 upper = 2300;\n        uint160 stopAt = TickMath.getSqrtPriceAtTick(lower) + 1;\n\n        uint256 snap = vm.snapshotState();\n\n        // Plain seller.\n        uint256 before = address(this).balance;\n        _sellPanicToPrice(stopAt);\n        uint256 plainGain = address(this).balance - before;\n        uint256 plainFee = hook.totalAccruedFees() + hook.totalDonated();\n        uint256 plainDonation = hook.totalDonated();\n        assertGt(plainDonation, 0, \"the sell's LP share was donated in-swap\");\n\n        vm.revertToState(snap);\n\n        // JIT seller: 100x the resident liquidity in a narrow range whose lower edge is the end tick,\n        // added before the sell and removed right after (atomic in practice, flash-loanable).\n        before = address(this).balance;\n        _addLiquidity(lower, upper, int256(1e24));\n        _sellPanicToPrice(stopAt);\n        (, int24 tickAfter,,) = IPoolManager(address(manager)).getSlot0(poolId);\n        assertEq(tickAfter, lower, \"the sell ends inside the JIT range\");\n        _addLiquidity(lower, upper, -int256(1e24));\n        uint256 jitGain = address(this).balance - before;\n\n        emit log_named_uint(\"plain seller: hook fee\", plainFee);\n        emit log_named_uint(\"plain seller: LP donation\", plainDonation);\n        emit log_named_uint(\"plain seller: net ETH\", plainGain);\n        emit log_named_uint(\"JIT seller:   net ETH\", jitGain);\n        if (jitGain > plainGain) {\n            emit log_named_uint(\"JIT seller recaptured (wei)\", jitGain - plainGain);\n            emit log_named_uint(\"as share of the donation (bps)\", (jitGain - plainGain) * 10_000 / plainDonation);\n        }\n        // Expected: liquidity that exists only for the seller's own transaction earns nothing of the seller's tax.\n        assertLe(jitGain, plainGain, \"a seller recaptures their own LP donation with same-transaction liquidity\");\n    }\n}","reproduction":"PANIC/native-ETH pool (PANIC = currency1), initialized at sqrtPriceX96 2^96, fee 12500, tickSpacing 100, full-range liquidity 1e22, fresh hook at a mined address with oracleFund 0x788C311500FD3C15b8e44d6e2935fe7fF13E674b. Baseline: one exact-input sell of PANIC (zeroForOne=false, amountSpecified=-1e26) with sqrtPriceLimitX96 = TickMath.getSqrtPriceAtTick(2200)+1 ends at tick 2200 (19.75% drawdown, 20% tier): hook fee 208,321,875,861,255,582,992 wei, donated in-swap 62,496,562,758,376,674,897 wei, seller nets 833,287,503,445,022,331,968 wei. JIT: same state, the seller first adds liquidity 1e24 in ticks [2200, 2300] (costs 4,467,793,134,144,645,995,541 wei of ETH for one transaction), performs the identical sell, then removes the position. Seller's net ETH is 895,165,288,354,306,168,498 wei, i.e. 61,877,784,909,283,836,530 wei more than the plain seller = 99.0% of the donation and 29.7% of the hook fee; the effective tax on the gross output falls from 20.0% to 14.1%. Expected: liquidity that exists only for the seller's own transaction earns none of the seller's tax. Actual: it receives 99% of the LP share. Proof: test/scratch/JitRecapture.t.sol (forge test --match-path test/scratch/JitRecapture.t.sol) fails with 'a seller recaptures their own LP donation with same-transaction liquidity: 895165288354306168498 > 833287503445022331968'.","severity":"medium","snippet":"        if (pending > 0 && poolManager.getLiquidity(poolId) > 0) {\n            donationBucket = 0;\n            _donate(pending);","title":"A seller recaptures up to 99% of the 30% LP donation on their own sell with same-transaction JIT liquidity at the post-sell tick, cutting the effective sell tax (20% tier becomes about 14%)"},{"citation":"resolved","description":"Every non-zero burn bucket must be cleared by an internal swap that returns at least one PANIC unit. With the required 12500 LP fee a one-unit exact-input swap has its whole input consumed by the rounded-up LP fee and returns zero PANIC, so both buybackAndBurn overloads revert BuybackBelowReference(0,1) and roll back. claimOracleFund and donateToLiquidityProviders cannot reach the burn bucket. The balance stays accounted (the hook keeps the ERC-6909 claim) and becomes spendable only if further taxed swaps top up the bucket, so this is dust-level and not a loss, but it leaves the final bucket unclearable without new trading. Same mechanism applies to any bucket below the PANIC-per-unit price. Possible fix that keeps the 98% floor: let buybackAndBurn accept a caller top-up (msg.value / transferFrom of the paired currency) merged with the bucket, or sweep a bucket below a documented dust threshold into the oracle fund.","line":501,"path":"src/PanicHook.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {PoolManager} from \"v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"v4-core/src/interfaces/IPoolManager.sol\";\nimport {IHooks} from \"v4-core/src/interfaces/IHooks.sol\";\nimport {PoolKey} from \"v4-core/src/types/PoolKey.sol\";\nimport {Currency, CurrencyLibrary} from \"v4-core/src/types/Currency.sol\";\nimport {ModifyLiquidityParams, SwapParams} from \"v4-core/src/types/PoolOperation.sol\";\nimport {TickMath} from \"v4-core/src/libraries/TickMath.sol\";\nimport {PoolSwapTest} from \"v4-core/src/test/PoolSwapTest.sol\";\nimport {PoolModifyLiquidityTest} from \"v4-core/src/test/PoolModifyLiquidityTest.sol\";\nimport {PanicMonkeys} from \"src/PanicMonkeys.sol\";\nimport {PanicHook} from \"src/PanicHook.sol\";\nimport {HookMiner} from \"src/HookMiner.sol\";\nimport {HookFlags} from \"src/HookFlags.sol\";\n\n/// @notice A burn bucket of one paired minor unit cannot be cleared by any permissionless outlet: the 1.25% LP\n/// fee rounds a one-unit swap's usable input to zero, the buyback returns zero PANIC and reverts, and the other\n/// outlets cannot touch the burn bucket. Fails on the current code; passes once accrued dust has a clearing path.\ncontract DustBucketTest is Test {\n    uint160 constant SQRT_PRICE_1_1 = 79228162514264337593543950336;\n    int24 constant TICK_SPACING = 100;\n    address constant ORACLE_FUND = 0x788C311500FD3C15b8e44d6e2935fe7fF13E674b;\n\n    PoolManager manager;\n    PanicMonkeys panic;\n    PanicHook hook;\n    PoolSwapTest swapRouter;\n    PoolModifyLiquidityTest lpRouter;\n    PoolKey key;\n\n    receive() external payable {}\n\n    function setUp() public {\n        vm.warp(1_800_000_000);\n        vm.roll(1_000);\n        manager = new PoolManager(address(this));\n        panic = new PanicMonkeys();\n        swapRouter = new PoolSwapTest(IPoolManager(address(manager)));\n        lpRouter = new PoolModifyLiquidityTest(IPoolManager(address(manager)));\n\n        bytes memory creationCode = abi.encodePacked(\n            type(PanicHook).creationCode, abi.encode(IPoolManager(address(manager)), address(panic), ORACLE_FUND)\n        );\n        (address predicted, bytes32 salt) =\n            HookMiner.find(address(this), HookFlags.PANIC_HOOK, creationCode, 0, 1_000_000);\n        hook = new PanicHook{salt: salt}(IPoolManager(address(manager)), address(panic), ORACLE_FUND);\n        assertEq(address(hook), predicted);\n\n        key = PoolKey({\n            currency0: CurrencyLibrary.ADDRESS_ZERO,\n            currency1: Currency.wrap(address(panic)),\n            fee: 12_500,\n            tickSpacing: TICK_SPACING,\n            hooks: IHooks(address(hook))\n        });\n        manager.initialize(key, SQRT_PRICE_1_1);\n\n        vm.deal(address(this), 1e27);\n        panic.approve(address(swapRouter), type(uint256).max);\n        panic.approve(address(lpRouter), type(uint256).max);\n        lpRouter.modifyLiquidity{value: 1e25}(\n            key,\n            ModifyLiquidityParams({\n                tickLower: TickMath.minUsableTick(TICK_SPACING),\n                tickUpper: TickMath.maxUsableTick(TICK_SPACING),\n                liquidityDelta: int256(1e22),\n                salt: 0\n            }),\n            \"\"\n        );\n    }\n\n    function test_oneUnitBurnBucketHasAPermissionlessClearingPath() public {\n        // Sell 600 PANIC minor units: gross output 591, hook fee 11 -> oracle 7, donated 3, burn 1.\n        swapRouter.swap(\n            key,\n            SwapParams({zeroForOne: false, amountSpecified: -600, sqrtPriceLimitX96: TickMath.MAX_SQRT_PRICE - 1}),\n            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false}),\n            \"\"\n        );\n        assertEq(hook.burnBucket(), 1, \"one unit accrued to the burn bucket\");\n\n        // An hour later, flat price: every outlet is tried.\n        vm.roll(block.number + 1);\n        vm.warp(block.timestamp + 3600);\n        hook.claimOracleFund();\n        (bool okDonate,) = address(hook).call(abi.encodeWithSignature(\"donateToLiquidityProviders()\"));\n        okDonate;\n        (bool okBuyback, bytes memory ret) = address(hook).call(abi.encodeWithSignature(\"buybackAndBurn()\"));\n        if (!okBuyback) emit log_named_bytes(\"buybackAndBurn() reverted with\", ret);\n        (bool okBuybackOne,) = address(hook).call(abi.encodeWithSignature(\"buybackAndBurn(uint256)\", uint256(1)));\n        okBuybackOne;\n\n        emit log_named_uint(\"burnBucket after every outlet\", hook.burnBucket());\n        emit log_named_uint(\"claims still held by the hook\", manager.balanceOf(address(hook), 0));\n        assertEq(hook.totalAccruedFees(), 0, \"accrued dust stays stuck in the burn bucket\");\n    }\n}","reproduction":"PANIC/native-ETH pool at 2^96, fee 12500, tickSpacing 100, full-range liquidity 1e22. Sell exactly 600 PANIC minor units (zeroForOne=false, amountSpecified=-600, no price limit): delta amount0=+580, amount1=-600, gross paired output 591, hook fee floor(591*200/10000)=11, oracleFundBucket=7, totalDonated=3, burnBucket=1. Next block, +3600 s: claimOracleFund() pays the 7 units; the hook now holds exactly 1 claim unit and burnBucket==1. buybackAndBurn() and buybackAndBurn(1) both revert BuybackBelowReference(0,1); donateToLiquidityProviders() reverts NothingToDonate; buybackAndBurn(0) reverts NothingToBuyBack. Expected per the brief: every accrued unit has a permissionless clearing path. Actual: totalAccruedFees() stays 1 forever unless new fees accrue. Proof: test/scratch/DustBucket.t.sol fails with 'accrued dust stays stuck in the burn bucket: 1 != 0'.","severity":"low","snippet":"        if (minimum == 0) minimum = 1;\n        if (burned < minimum) revert BuybackBelowReference(burned, minimum);","title":"A burn bucket too small to buy one PANIC unit (for example one paired minor unit) cannot be cleared by any permissionless outlet, contrary to 'No dust may stay stuck' (merged: audit_math and audit_flo"},{"citation":"resolved","description":"pairedToPanicAtSqrtPrice rounds the reference quote down to a whole PANIC minor unit before the 98% minimum is computed, so minimum = ceil(0.98 * floor(q)) which can be one unit below ceil(0.98 * q). For tiny buybacks this lets the call pass when the live price is more than 2% above the reference, which the brief says must revert. The error is bounded to less than one PANIC minor unit per call and cannot compound, so impact is dust-level; it is a guarantee that is slightly off rather than a loss. Fix: compute minimum = ceil(spent * num^2 * 9800 / (den^2 * 10000)) in full precision (fold the 98% into the mulDiv chain) and keep the 'at least 1' rule.","line":499,"path":"src/PanicHook.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {PoolManager} from \"v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"v4-core/src/interfaces/IPoolManager.sol\";\nimport {IHooks} from \"v4-core/src/interfaces/IHooks.sol\";\nimport {PoolKey} from \"v4-core/src/types/PoolKey.sol\";\nimport {Currency, CurrencyLibrary} from \"v4-core/src/types/Currency.sol\";\nimport {ModifyLiquidityParams, SwapParams} from \"v4-core/src/types/PoolOperation.sol\";\nimport {TickMath} from \"v4-core/src/libraries/TickMath.sol\";\nimport {StateLibrary} from \"v4-core/src/libraries/StateLibrary.sol\";\nimport {FullMath} from \"v4-core/src/libraries/FullMath.sol\";\nimport {PoolSwapTest} from \"v4-core/src/test/PoolSwapTest.sol\";\nimport {PoolModifyLiquidityTest} from \"v4-core/src/test/PoolModifyLiquidityTest.sol\";\nimport {PanicMonkeys} from \"src/PanicMonkeys.sol\";\nimport {PanicHook} from \"src/PanicHook.sol\";\nimport {HookMiner} from \"src/HookMiner.sol\";\nimport {HookFlags} from \"src/HookFlags.sol\";\n\n/// @notice `_buybackAndBurn` floors the reference-implied PANIC before applying the 98% minimum, so\n/// ceil(0.98 * floor(q)) can be one unit below ceil(0.98 * q). With the live price 3% above the reference a\n/// 1000-unit buyback returning 20 PANIC units is accepted although 98% of the exact quote (20.8999...) is 20.48,\n/// which requires 21. Fails on the current code; passes once the minimum is derived from the unfloored quote.\ncontract BuybackFloorRoundingTest is Test {\n    using StateLibrary for IPoolManager;\n\n    uint160 constant SQRT_PRICE_1_1 = 79228162514264337593543950336;\n    int24 constant TICK_SPACING = 100;\n    address constant ORACLE_FUND = 0x788C311500FD3C15b8e44d6e2935fe7fF13E674b;\n\n    PoolManager manager;\n    PanicMonkeys panic;\n    PanicHook hook;\n    PoolSwapTest swapRouter;\n    PoolModifyLiquidityTest lpRouter;\n    PoolKey key;\n\n    receive() external payable {}\n\n    function setUp() public {\n        vm.warp(1_800_000_000);\n        vm.roll(1_000);\n        manager = new PoolManager(address(this));\n        panic = new PanicMonkeys();\n        swapRouter = new PoolSwapTest(IPoolManager(address(manager)));\n        lpRouter = new PoolModifyLiquidityTest(IPoolManager(address(manager)));\n\n        bytes memory creationCode = abi.encodePacked(\n            type(PanicHook).creationCode, abi.encode(IPoolManager(address(manager)), address(panic), ORACLE_FUND)\n        );\n        (address predicted, bytes32 salt) =\n            HookMiner.find(address(this), HookFlags.PANIC_HOOK, creationCode, 0, 1_000_000);\n        hook = new PanicHook{salt: salt}(IPoolManager(address(manager)), address(panic), ORACLE_FUND);\n        assertEq(address(hook), predicted);\n\n        key = PoolKey({\n            currency0: CurrencyLibrary.ADDRESS_ZERO,\n            currency1: Currency.wrap(address(panic)),\n            fee: 12_500,\n            tickSpacing: TICK_SPACING,\n            hooks: IHooks(address(hook))\n        });\n        manager.initialize(key, SQRT_PRICE_1_1);\n\n        vm.deal(address(this), 1e27);\n        panic.approve(address(swapRouter), type(uint256).max);\n        panic.approve(address(lpRouter), type(uint256).max);\n        lpRouter.modifyLiquidity{value: 1e25}(\n            key,\n            ModifyLiquidityParams({\n                tickLower: TickMath.minUsableTick(TICK_SPACING),\n                tickUpper: TickMath.maxUsableTick(TICK_SPACING),\n                liquidityDelta: int256(1e22),\n                salt: 0\n            }),\n            \"\"\n        );\n    }\n\n    function _swap(bool zeroForOne, int256 amountSpecified, uint160 limit) internal {\n        uint256 value = zeroForOne ? uint256(-amountSpecified) : 0;\n        swapRouter.swap{value: value}(\n            key,\n            SwapParams({zeroForOne: zeroForOne, amountSpecified: amountSpecified, sqrtPriceLimitX96: limit}),\n            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false}),\n            \"\"\n        );\n    }\n\n    function test_smallBuybackThreePercentAboveReferenceMustRevert() public {\n        _swap(false, -1e18, TickMath.MAX_SQRT_PRICE - 1); // sell 1 PANIC: funds the burn bucket\n        _swap(true, -1e24, 11453882584939555244670964355); // buy up to a limit\n        vm.roll(block.number + 1);\n        vm.warp(block.timestamp + 3600); // flat for an hour: reference == this price\n        _swap(true, -1e24, 11285843134733390162692706488); // buy: live PANIC price 3% above the reference\n\n        uint160 ref = hook.referenceSqrtPriceX96();\n        (uint160 live,,,) = IPoolManager(address(manager)).getSlot0(key.toId());\n        uint256 premiumE4 = uint256(ref) * uint256(ref) / uint256(live) * 10_000 / uint256(live);\n        emit log_named_uint(\"live PANIC price / reference (e4)\", premiumE4);\n        assertGt(premiumE4, 10_200, \"more than 2% above the reference\");\n\n        // Exact reference quote for 1000 paired units, in millionths of a PANIC unit.\n        uint256 quoteE6 = FullMath.mulDiv(FullMath.mulDiv(1000 * 1e6, ref, 1 << 96), ref, 1 << 96);\n        uint256 minimumExact = (quoteE6 * 9800 + 1e10 - 1) / 1e10; // ceil(0.98 * quote)\n        emit log_named_uint(\"exact quote (e6)\", quoteE6);\n        emit log_named_uint(\"floored quote used by the hook\", hook.pairedToPanicAtSqrtPrice(1000, ref, false));\n        emit log_named_uint(\"minimum from the exact quote\", minimumExact);\n        assertEq(minimumExact, 21);\n\n        vm.expectRevert();\n        hook.buybackAndBurn(1000);\n    }\n}","reproduction":"PANIC/native-ETH pool at 2^96, fee 12500, tickSpacing 100, full-range liquidity 1e22, block 1000 / timestamp 1800000000. (1) Sell 1e18 PANIC (no limit) to fund the burn bucket (burnBucket = 1,974,804,988,007,434). (2) Buy with amountSpecified=-1e24 and sqrtPriceLimitX96=11453882584939555244670964355. (3) Roll one block and warp +3600 s so the reference equals that price: referenceSqrtPriceX96() = 11453879819504963640314164846. (4) Buy with amountSpecified=-1e24 and sqrtPriceLimitX96=11285843134733390162692706488, leaving the live PANIC price 3.00% above the reference (ref^2/live^2 = 1.0300). (5) buybackAndBurn(1000). Exact reference quote = 1000 * ref^2 / 2^192 = 20.899989 PANIC units, 98% of that = 20.48, so the minimum must be 21. The hook uses floor = 20 and minimum = ceil(20*0.98) = 20, receives 20 and succeeds, emitting BuybackAndBurn(1000, 20, 20). Expected: revert BuybackBelowReference(20, 21). Proof: test/scratch/BuybackFloorRounding.t.sol fails with 'next call did not revert as expected'.","severity":"low","snippet":"        uint256 implied = pairedToPanicAtSqrtPrice(spent, refSqrtPriceX96, panicIsCurrency0);\n        uint256 minimum = FullMath.mulDivRoundingUp(implied, MIN_BUYBACK_OUTPUT_BPS, BPS);","title":"The 98% buyback floor is applied to the already-floored reference quote, so a small buyback can succeed while receiving less than 98% of the exact reference-implied PANIC"},{"citation":"resolved","description":"The constant is immutable (no admin) and denominated in whatever the paired currency is. launch.json pairs the pool with 0xd34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7, which on Ethereum mainnet reports symbol IMD, 18 decimals and total supply 4,116,877.757721 (read with cast call against ethereum-rpc.publicnode.com on 2026-10-07). So one buybackAndBurn call can spend at most 1 IMD, while the call costs about 249k gas cold and 175k gas warm on an ERC-20 pair; on mainnet at 20 gwei that is roughly 0.0035 to 0.005 ETH of gas per call, more than the value of 1 IMD at public quotes near 8.5 USD. The outlet still works and nothing is lost or stuck, so this is recalibrated from the specialist's medium to low: it is a mismatch between the README's stated assumption ('The paired currency is native ETH', README.md:199; 'Pool: PANIC paired with native ETH', README.md:165; script/DeployPanic.s.sol initializes a native-ETH pool) and the manifest's IMD pair, which makes draining the bucket cost many calls and, on mainnet, more gas than it burns. The cap should be chosen for the actual paired currency (or expressed relative to pool liquidity) and the README corrected to match launch.json.","line":98,"path":"src/PanicHook.sol","reproduction":"PANIC/ERC-20 pool with an 18-decimal mock paired token as currency0 (same orientation possibilities as the manifest), price 1:1, full-range liquidity 1e22. One sell to 20% drawdown accrues burnBucket = 21,114,561,800,016,824,287 (21.1 paired units). Next block: buybackAndBurn() returns spent == 1e18 exactly (the cap) and consumes 248,679 gas; a second call in the same block consumes 175,370 gas; 27 calls are needed to empty the bucket from this single sell. Expected: a cap that bounds one call in a unit meaningful for the launch pair. Actual: 1 IMD per call for a token whose whole supply is 4.1M IMD. Scratch test used: test/scratch/Repro.t.sol:ReproErc20Test.test_buybackGasAndCapOnErc20Pair.","severity":"low","snippet":"    uint256 public constant MAX_BUYBACK_SPEND = 1 ether;","title":"MAX_BUYBACK_SPEND is 1e18 minor units of the paired currency, sized for a native-ETH pair, but the manifest pairs PANIC with IMD; README and deploy script still describe a PANIC/ETH pool"},{"citation":"resolved","description":"initialPrice is exactly 2^96, i.e. one raw currency1 unit per raw currency0 unit. Both PANIC (PanicMonkeys.decimals = 18) and the paired IMD token (18 decimals on-chain) have 18 decimals, so in either pool orientation the pool opens at 1 PANIC per IMD. PanicMonkeys mints 1,000,000,000 PANIC (TOTAL_SUPPLY = 1_000_000_000 ether), so the implied launch valuation is 1e9 IMD, about 243 times the entire IMD supply. The manifest's own notes say the price 'follow[s] the deployment test' and README.md:165 still describes the pool as PANIC/ETH. The hook anchors its one-hour reference at this initialization tick (afterInitialize stores initialTick and _reference assumes it prevailed for the hour before launch), so the opening price also decides which sells are 'down' during the first hour. I could not see the launch policy's seed amounts, so this is reported as a manifest value with no stated economic basis for this pair rather than a proven misconfiguration; the author should set initialPrice from the intended PANIC/IMD opening valuation and seed sizes.","line":29,"path":"launch.json","reproduction":"Decode launch.json: pairedCurrency = 0xd34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7 (cast call decimals() = 18, symbol() = IMD, totalSupply() = 4116877757721000000000000 on Ethereum mainnet), token.decimals = 18, initialPrice = 79228162514264337593543950336 = 2^96, so sqrtPrice = 1.0 and price = 1 PANIC per IMD. With TOTAL_SUPPLY = 1e27 minor units the implied FDV is 1e9 IMD; a two-sided seed of just 1% of the PANIC supply at this price would need 10,000,000 IMD, more than exist. Expected: an initial price derived from the launch's PANIC/IMD valuation. Actual: the 1:1 placeholder from the ETH test fixture.","severity":"low","snippet":"    \"initialPrice\": \"79228162514264337593543950336\"","title":"Manifest initialPrice 2^96 means 1 PANIC = 1 IMD at launch, implying a starting fully-diluted value of 1e9 IMD against a total IMD supply of 4.1M; the value was copied from the ETH test fixture"},{"citation":"resolved","description":"The brief takes the sell fee from the paired output through the afterSwap return delta, and a v4 afterSwap delta cannot adjust the specified currency. The implementation therefore rejects every exact-output sell in beforeSwap (line 323) and, for exact-input buys with a non-zero fee reserved in beforeSwap, rejects any partial fill in afterSwap because the specified input cannot be refunded (line 356, PartialExactInputBuyNotSupported). Neither path loses funds and both are documented in README.md and the manifest notes, but they are user-facing failures the brief does not list among the accepted limitations: an aggregator exact-output sell route, or an exact-input dip buy whose router sets a binding sqrtPriceLimitX96, reverts rather than trading. Options that keep the brief's economics: take the fee for exact-output sells from the unspecified (PANIC input) side converted at the post-swap price, or state the routing restriction (sells exact-input only, dip buys exact-output when price-limited) in the manifest notes so integrators configure routes accordingly.","line":323,"path":"src/PanicHook.sol","reproduction":"PANIC/native-ETH pool at 1:1 with full-range liquidity 1e22. (a) swapRouter.swap with zeroForOne=false (sell PANIC), amountSpecified=+1e18 (exact output of 1 ETH), sqrtPriceLimitX96 = MAX_SQRT_PRICE-1: expected per the brief a taxed sell paying 2% of the 1 ETH output; actual the PoolManager reverts WrappedError(hook, beforeSwap.selector, ExactOutputSellNotSupported, HookCallFailed) (existing test test_exactOutputSellIsRejected in test/PanicHook.Fees.t.sol). (b) After a sell to 10% drawdown, an exact-input buy of 100 ETH with sqrtPriceLimitX96 = price - price/10000 reverts WrappedError(hook, afterSwap.selector, PartialExactInputBuyNotSupported, HookCallFailed) with nothing charged (existing test test_partialDipBuyRevertsWithoutChargingOrMovingThePool in test/PanicHook.Revision.t.sol).","severity":"low","snippet":"        if (params.amountSpecified > 0) revert ExactOutputSellNotSupported();","title":"Exact-output sells and fee-bearing partial exact-input buys revert, so routers quoting a sell by desired output or price-limited dip buys fail instead of being taxed"},{"citation":"resolved","description":"_meanTick floors the cumulative-tick mean toward negative infinity and referenceSqrtPriceX96 converts that whole tick to a sqrt price, exactly as Uniswap v3's OracleLibrary.consult does. The fractional tick (up to 1 bp of price) is dropped: with PANIC as currency1 the reference PANIC price is rounded up (drawdown overstated by at most 1 bp), with PANIC as currency0 it is rounded down. A sell that truly ends 4.99% below the unquantized geometric mean can therefore land in the 10% tier, and vice versa in the other orientation. README.md documents this quantization and the brief's required boundary tests pass relative to the computed reference. Reported for completeness at info: it is the conventional tick-TWAP definition, the band is 1 bp, and interpolating between getSqrtPriceAtTick(t) and getSqrtPriceAtTick(t+1) by the remainder would remove it if the author wants an unquantized reference.","line":570,"path":"src/PanicHook.sol","reproduction":"PANIC/native-ETH pool at 1:1, full-range liquidity 1e22. Block +1800 s: sell PANIC with sqrtPriceLimitX96 = TickMath.getSqrtPriceAtTick(1) so the pool sits at tick 1. Block +1800 s more: the true mean tick over the hour is 0.5, but hook.referenceTick() == 0 and hook.referenceSqrtPriceX96() == 2^96. Let boundary = the sqrt price exactly 5% below the floored reference and fractional = 2^96 + (getSqrtPriceAtTick(1) - 2^96)/2: hook.drawdownBps(boundary, 2^96, false) == 500 (10% tier) while hook.drawdownBps(boundary, fractional, false) == 499 (2% tier). This is the existing test test_referenceUsesDocumentedWholeTickRounding in test/PanicHook.Revision.t.sol.","severity":"info","snippet":"        return TickMath.getSqrtPriceAtTick(tick);","title":"Reference price is the whole-tick floor of the mean tick, so tier boundaries are exact only relative to a reference quantized by up to 1 bp (standard Uniswap v3 TWAP behaviour, documented)"}],"hash":"49025ab6ae72f24422e57f2f02e8905e99935638de24c265160c908523eb768e","nodeId":"b41d7c2f-ead1-4e77-8741-7e0763c53e15","outcome":"completed","summary":"Review complete. The findings file is written and every anchor, snippet and proof was checked against the tree.\n\n**Outcome**: 7 findings in `.imd-findings.json` (1 medium, 5 low, 1 info) with a 17-row coverage record covering all 12 entry points plus invariants, manifest and static-analysis leads. All 129 repository tests pass; the three proof tests under `test/scratch/` fail on the current code as required.\n\n**Specialist findings, settled**\n- Kept and merged: the one-unit burn bucket that no outlet can clear (audit_math + audit_flow, same root cause) as one low, reproduced: sell 600 wei PANIC, claim the oracle share, then both buyback overloads revert with `BuybackBelowReference(0,1)`.\n- Kept as low: the 98% floor applied to the floored reference quote. Reproduced exactly: exact quote 20.899989 PANIC units, minimum should be 21, hook accepts 20 at a 3% premium.\n- Recalibrated medium to low: the 1-ether buyback cap on an IMD pair. I verified IMD on mainnet (18 decimals, 4.12M supply) and measured 248,679 gas cold / 175,370 warm, 27 calls to drain one 20% sell's bucket. Nothing is lost or stuck, so it is a README/manifest mismatch rather than a broken guarantee.\n- Kept as low: the 1:1 placeholder initial price, with the FDV arithmetic, and the exact-output sell / partial dip-buy reverts (merged into one documented integration limitation).\n- Demoted to info: whole-tick flooring of the reference. It is exactly Uniswap v3's TWAP convention and is documented.\n\n**New finding all four missed (medium, with proof)**: a seller can wrap their own sell in same-transaction JIT liquidity whose lower edge is the post-sell tick. Because `_split` donates the LP share inside `afterSwap` to liquidity in range at that tick, the seller's position captures 99% of the donation and withdraws it immediately. Measured: the seller nets 61.9 ETH more on a 208 ETH tax, so the 20% tier is effectively 14.1%. Capital is only needed for one transaction, so it is flash-loanable. Suggested fix keeps the donate mechanism but flushes the LP share no earlier than the next block's first observation.\n\n**Not found**: no access-control, delta-accounting, reentrancy or oracle-manipulation defects. Every slither and aderyn line was traced and found to be a false positive, recorded in the coverage row.","treeHash":null,"usage":{"cachedInputTokens":2594249,"inputTokens":514,"model":"claude-fable-5-1","outputTokens":68003,"runtime":"claude","turns":33,"wallClockMs":1189104}},{"artifacts":[],"attempt":1,"bundleHash":"b3ce917af930e0821b98cb07d60735cd497bbe3339df36f7e3980d494cca3222","device":"63fda2736ec51b55","findings":[],"hash":"6a429299b40d41db35b5cbfc176f9fbdf33956b88b49f89de96fbbaa746274be","nodeId":"5ab1373f-577d-4afa-9d17-f9ba02defd6c","outcome":"completed","summary":"Reused commit `fe78b5d`. Fixed `oracleFund` to `0x788C311500FD3C15b8e44d6e2935fe7fF13E674b` in the manifest and constructor, removed anti-splitting tests, and updated related fixtures/docs. Trading logic and dependencies remain unchanged.\n\nSolidity 0.8.26 checks passed: build, all 113 tests, and formatting.","treeHash":"665c58b13d3c593bb3916265782c7ec77a6be323","usage":{"cachedInputTokens":1977472,"inputTokens":115085,"model":"gpt-6-astra","outputTokens":10156,"runtime":"codex","turns":6,"wallClockMs":544693}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"77620edf9366f370","findings":[{"citation":"resolved","description":"The permissionless burn outlet cannot clear a final burnBucket balance of one paired-currency base unit. At the configured 12500 LP fee, v4 rounds the usable input of a one-unit exact-input swap to zero and produces zero PANIC. _buybackAndBurn requires at least one PANIC base unit and reverts, restoring the one-unit bucket and its claim. Every positive maxSpend is capped to the same one-unit bucket; the other outlets cannot spend it. The balance remains accounted for and can become spendable if additional trading accrues fees, but the existing balance cannot be drained on its own, contrary to the explicit no-stuck-dust requirement. Impact is limited to dust. A permissionless top-up mechanism that combines caller funds with the residual burn budget could preserve the fee splits and 98% output floor while allowing it to clear.","line":500,"path":"src/PanicHook.sol","reproduction":"Reproduced with a real vendored PoolManager in the isolated Foundry test test/scratch/FirstPrinciplesReview.t.sol (1 passed). At timestamp 1800000000/block 1000, deploy PanicMonkeys and a correctly mined PanicHook with the required oracle recipient. Initialize currency0=native currency, currency1=PANIC, fee=12500, tickSpacing=100, sqrtPriceX96=79228162514264337593543950336; add full-range liquidity 10000000000000000000000 over ticks -887200..887200. Through PoolSwapTest, swap with zeroForOne=false, amountSpecified=-600, sqrtPriceLimitX96=TickMath.MAX_SQRT_PRICE-1, and ordinary token settlement. The returned deltas are amount0=580 and amount1=-600: gross paired output 591 yields hook fee 11, oracleFundBucket=7, totalDonated=3, burnBucket=1. Call claimOracleFund(); the hook now holds exactly one native ERC6909 claim, with oracleFundBucket=0 and donationBucket=0. Calling buybackAndBurn() or buybackAndBurn(1) reverts BuybackBelowReference(0,1) and preserves burnBucket=1 and that claim. Advancing to timestamp 1800003600/block 1001 and calling buybackAndBurn() produces the same revert. Expected: the final accounted dust has a permissionless clearing path preserving the required burn/output constraints; actual: every existing outlet fails to clear it without generating additional fees.","severity":"low","snippet":"        uint256 minimum = FullMath.mulDivRoundingUp(implied, MIN_BUYBACK_OUTPUT_BPS, BPS);\n        if (minimum == 0) minimum = 1;\n        if (burned < minimum) revert BuybackBelowReference(burned, minimum);","title":"Final one-unit burn balance cannot be cleared without new fees"}],"hash":"8721f64a9681d02efee9cf360be33499dc52a29ee0fb23c56eea83709af127d0","nodeId":"ca1d0510-f59e-4db7-b4c8-d92c27e3233b","outcome":"completed","summary":"Recorded one low-severity finding in [.imd-findings.json](/home/imdc/.identitymd/work/8540825c-a412-4c3d-be82-73cdf9002e30/ca1d0510-f59e-4db7-b4c8-d92c27e3233b/.imd-findings.json): a final one-unit burn balance cannot be cleared without new fees.\n\nCovered all 12 entry points. Existing Foundry tests passed; the targeted reproduction confirmed the finding.","treeHash":null,"usage":{"cachedInputTokens":1308928,"inputTokens":66235,"model":"gpt-6-astra","outputTokens":5980,"runtime":"codex","turns":5,"wallClockMs":682437}},{"artifacts":[],"attempt":2,"bundleHash":"05e00e0cec532941836a2ee5e0d6a5aaefe579aa2f9a43382068d0f145c6c941","device":"ef5038c1bdac3372","findings":[],"hash":"8c449e81e61dae860b722593c79751e362724a82e94daf44cb7197f3c864f520","nodeId":"5ab1373f-577d-4afa-9d17-f9ba02defd6c","outcome":"completed","summary":"","treeHash":"e37341d2d0f1443d573ceb473c3eb5426dd6a36e","usage":{"cachedInputTokens":9818007,"inputTokens":1892,"model":"claude-fable-5-1","outputTokens":156830,"runtime":"claude","turns":61,"wallClockMs":2225329}},{"artifacts":[],"attempt":1,"bundleHash":"92f13e114d235c584b6d01ceacf003d0c8bcf8af9dddb58bcaf3398948afabca","device":"3d800e8d8dc2fdc5","findings":[],"hash":"950e0dcbde34f94dab6476b62b01c49519a9ccc198480c9c12bca909b95a0caa","nodeId":"4cb57aad-4681-42e4-affd-58a57b2c40ed","outcome":"completed","summary":"Updated [launch.json](/home/worker/.identitymd/work/8540825c-a412-4c3d-be82-73cdf9002e30/4cb57aad-4681-42e4-affd-58a57b2c40ed/launch.json), preserving the required deployment settings and correcting stale implementation notes. Only the manifest changed.\n\nSchema, ABI, permissions, and `forge build` checks passed. `forge test`: **122 passed, 0 failed, 1 skipped**—policy supply was not provided.","treeHash":"230fe9d2fe4beb217c1e0ccec2d3e2bea114ecdb","usage":{"cachedInputTokens":876416,"inputTokens":76863,"model":"gpt-6-astra","outputTokens":9116,"runtime":"codex","turns":6,"wallClockMs":434964}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"9b84a1e2e2a9ac5e","findings":[{"citation":"resolved","description":"_buybackAndBurn applies the 98% floor to an already-rounded-down PANIC quote. ceil(0.98 * floor(exactQuote)) can be smaller than ceil(0.98 * exactQuote). Consequently a permissionless caller can make a small buyback succeed when the pool price exceeds the reference by more than 2%, receiving less than 98% of the reference-implied PANIC. This violates the explicit buyback guarantee, although the rounding error is bounded to less than one PANIC minor unit per call, so severity is low. Preserve the fractional reference quote through the 98% calculation and round up only the final minimum, with full-precision arithmetic in both orientations.","line":499,"path":"src/PanicHook.sol","reproduction":"Confirmed with a real PoolManager using forge test --match-path test/scratch/MathBoundaryReview.t.sol --match-test test_smallBuybackAtThreePercentPremiumMustRevert: fails with \"next call did not revert as expected\". At timestamp 1800000000/block 1000 initialize native/PANIC (PANIC currency1), fee 12500, tickSpacing 100, sqrtPriceX96=79228162514264337593543950336; add full-range [-887200,887200] liquidity 10^22. In that block sell 10^18 PANIC with sqrtPriceLimitX96=1461446703485210103287273052203988822378723970341, accruing burnBucket=1974804988007434. Then buy with amountSpecified=-10^24 and sqrtPriceLimitX96=11453882584939555244670964355. Advance to block 1001/time 1800003600 so the price has been flat for one hour; referenceSqrtPriceX96 now equals 11453879819504963640314164846. In that block buy with amountSpecified=-10^24 and sqrtPriceLimitX96=11285843134733390162692706488, reaching a PANIC price 3% above the reference. Call buybackAndBurn(1000). Actual: spends 1000 paired minor units and sends 20 PANIC minor units to DEAD, successfully emitting BuybackAndBurn(1000,20,20). Exact reference implication is 1000*11453879819504963640314164846^2/2^192, approximately 20.8999899077757156 PANIC minor units; 98% is approximately 20.4819901096202013, so the minimum integer output must be 21 and this call must revert. The code instead uses floor(quote)=20 and ceil(20*9800/10000)=20. All swaps and liquidity changes use a normal unlock-and-settle router; no pool storage is mocked.","severity":"low","snippet":"        uint256 implied = pairedToPanicAtSqrtPrice(spent, refSqrtPriceX96, panicIsCurrency0);\n        uint256 minimum = FullMath.mulDivRoundingUp(implied, MIN_BUYBACK_OUTPUT_BPS, BPS);\n        if (minimum == 0) minimum = 1;\n        if (burned < minimum) revert BuybackBelowReference(burned, minimum);","title":"Flooring the reference quote first lets small buybacks bypass the 98% minimum"},{"citation":"resolved","description":"Every nonzero burn bucket must be spent by a swap producing at least one PANIC unit. With the required nonzero pool LP fee, a one-unit exact-input swap allocates its entire input to the rounded-up LP fee and returns zero PANIC. Both buyback overloads therefore revert forever on that balance unless new fees are generated; claimOracleFund and donateToLiquidityProviders cannot access it. This violates the explicit no-stuck-dust requirement. The minimum-output guard correctly prevents a zero-output purchase; the missing piece is an explicit dust settlement/top-up path that can clear the remainder without weakening that guard or changing the intended fee allocations.","line":499,"path":"src/PanicHook.sol","reproduction":"Confirmed with a real PoolManager using forge test --match-path test/scratch/MathBoundaryReview.t.sol --match-test test_oneUnitBurnBucketCannotDrain: fails with BuybackBelowReference(0,1). At timestamp 1800000000/block 1000 initialize native/PANIC at sqrtPriceX96=79228162514264337593543950336, fee=12500, tickSpacing=100 and full-range [-887200,887200] liquidity=10^22. Sell exactly 600 PANIC minor units. Gross paired output is 591; hook fee=floor(591*200/10000)=11, of which 3 is immediately donated, 7 accrues to the oracle and 1 accrues to burning. Advance one block and 3600 seconds, then claimOracleFund() to clear the 7-unit oracle bucket. Both remaining claims and burnBucket equal 1. Calling buybackAndBurn() or buybackAndBurn(1) spends 1 in the internal swap, receives 0 PANIC, and reverts BuybackBelowReference(0,1), rolling everything back. maxSpend=0 instead reverts NothingToBuyBack; any maxSpend>=1 is clamped to the same one-unit budget. Waiting longer does not help because the LP fee still consumes the single unit. Expected: a permissionless way to settle all accrued dust; actual: the last claim cannot be redeemed without creating additional trading fees.","severity":"low","snippet":"        uint256 implied = pairedToPanicAtSqrtPrice(spent, refSqrtPriceX96, panicIsCurrency0);\n        uint256 minimum = FullMath.mulDivRoundingUp(implied, MIN_BUYBACK_OUTPUT_BPS, BPS);\n        if (minimum == 0) minimum = 1;\n        if (burned < minimum) revert BuybackBelowReference(burned, minimum);","title":"A one-unit burn bucket cannot be drained through any bucket outlet"}],"hash":"a4961e0ec6eb095d2b1d2ea97b82aa58af6817071b2cb1c0bdc566ada9c57de7","nodeId":"3c697813-8877-49f2-9eb5-c6585aa83f99","outcome":"completed","summary":"Recorded two reproducible low-severity findings in [.imd-findings.json](.imd-findings.json):\n\n- Small buybacks can bypass the 98% minimum through rounding.\n- A one-unit burn bucket cannot drain without additional fees.\n\nCovered all 12 entry points. Existing 121 tests/invariants passed; both targeted regressions reproduced. Production files unchanged.","treeHash":null,"usage":{"cachedInputTokens":1991168,"inputTokens":131825,"model":"gpt-6-astra","outputTokens":14402,"runtime":"codex","turns":7,"wallClockMs":675351}},{"artifacts":[],"attempt":2,"bundleHash":null,"device":"232b62e021f6f394","findings":[{"citation":"resolved","description":"MAX_BUYBACK_SPEND is 1e18 minor units of whatever the paired currency is, and README.md:199 states the assumption behind it: 'The paired currency is native ETH (or another 18-decimal currency)'. launch.json:26 pairs the pool with 0xd34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7, which on-chain reports symbol IMD, name Identity.md, 18 decimals and a total supply of 4,116,877.76 tokens (read via cast call against three public Ethereum RPCs on 2026-10-07; public price trackers quote it near 8.5 USD). So a buyback call can spend at most 1 IMD, roughly 8 to 9 USD, while a measured buybackAndBurn() call costs 246,532 gas cold and 177,383 gas warm (scratch test, forge gas accounting, PANIC/ERC-20 pool with full-range liquidity). On Ethereum mainnet at 20 gwei and 4,000 USD/ETH that is 14 to 20 USD of gas per call, i.e. the caller pays about twice the value they burn. The brief's burn outlet ('10% accrues to a burn bucket: a permissionless buybackAndBurn() swaps it for PANIC') and the 'No dust may stay stuck' requirement therefore degrade into an outlet nobody is economically able to operate: the burn bucket grows with every taxed swap and stays there. The README's operational note ('call buybackAndBurn() repeatedly (1 ETH per call...)') and its gas remarks were written for an ETH pair and do not hold for this manifest. If the launch chain is an L2 the per-call gas is cheap and the issue is reduced to an inconvenience (hundreds of calls per crash), but the cap no longer bounds anything meaningful either way: it is 400x smaller in value than the ETH-denominated cap the design reasoned about. The constant should be chosen in terms of the actual paired currency (or expressed relative to pool liquidity), and the README assumption corrected.","line":98,"path":"src/PanicHook.sol","reproduction":"State: PANIC/IMD pool (PANIC as currency1, like the manifest's 18-decimal ERC-20 pair), full-range liquidity 1e22, price 1:1. (1) One sell drives the price 20% below the reference: burnBucket becomes 21,114,561,800,016,824,287 minor units (21.1 IMD, about 180 USD). (2) Call buybackAndBurn(): spent == 1e18 exactly (the cap), gas used 246,532; a second call in the same block uses 177,383 gas. (3) Draining the bucket needs 22 calls, about 4.1M gas; at 20 gwei on mainnet that is about 0.08 ETH (320 USD) of gas to burn 180 USD of PANIC. Expected per the brief: a permissionless outlet that lets the bucket be burned so no value stays stuck. Actual: every rational caller leaves the bucket alone, and it keeps accruing 10% of every hook fee indefinitely. Scratch test used: test/scratch/Gas.t.sol (setUp: _setUpErc20Pool(false, SQRT_PRICE_1_1); _fundAndApprove(); _addFullRangeLiquidity(1e22); then _sellToDrawdown(2000); _nextBlock(12); measure gasleft() around hook.buybackAndBurn()).","severity":"medium","snippet":"    uint256 public constant MAX_BUYBACK_SPEND = 1 ether;","title":"Per-call buyback cap is sized for a native-ETH pair but the manifest pairs PANIC with IMD, so burning the bucket costs more gas than it burns"},{"citation":"resolved","description":"_reference() computes the mean tick over the window and _meanTick (lines 783-786) floors it toward negative infinity; referenceSqrtPriceX96() then uses TickMath.getSqrtPriceAtTick(tick). The fractional part of the mean (up to one tick, i.e. up to 1 bp of price) is dropped, so the reference the fee tiers are judged against is not the geometric mean the brief describes. With PANIC as currency1 the floored reference is a higher PANIC price than the true mean, overstating drawdown by up to 1 bp, which pushes a sell that truly ends 4.99% down into the 10% tier (a 5x fee). With PANIC as currency0 the bias is the other way (understated by up to 1 bp), so a sell truly ending 5.00% down pays 2%. Because the orientation depends on the yet-unknown CREATE address of the PANIC token relative to 0xd34a..., either bias can be the production one. The brief's required test 'tiers switch exactly at 5%, 15%, 30% drawdown' is only met relative to the quantized reference, which README.md documents. Bounded impact (1 bp band at each threshold), but it is a real mispricing at the boundary that sqrt-price interpolation between the two adjacent ticks (weighting getSqrtPriceAtTick(t) and getSqrtPriceAtTick(t+1) by the remainder) would remove.","line":750,"path":"src/PanicHook.sol","reproduction":"PANIC/ETH pool, price 1:1, full-range liquidity 1e22. Block +1800 s: sell PANIC until the pool sits exactly at TickMath.getSqrtPriceAtTick(1). Block +1800 s more: true mean tick over the hour is 0.5; hook.referenceTick() == 0 and hook.referenceSqrtPriceX96() == 2^96. Let trueRef = sqrt(2^96 * getSqrtPriceAtTick(1)) (sqrt price of tick 0.5). Pick target = the sqrt price exactly 5% below the floored reference: hook.drawdownBps(target, 2^96, false) == 500 but hook.drawdownBps(target, trueRef, false) == 499. Sell PANIC with sqrtPriceLimitX96 = target (exact input, large amount). Observed: gross paired output 252,705,692,687,911,366,574; fee charged 25,270,569,268,791,136,657 (10%). Expected against the true one-hour mean (4.99% down, the brief's '< 5%' band): 5,054,113,853,758,227,331 (2%). The existing test_referenceUsesDocumentedWholeTickRounding shows the same 499-vs-500 split at the view level.","severity":"low","snippet":"        tick = _meanTick(cumNow - cumTarget, TWAP_WINDOW);","title":"Reference tick is floored to a whole tick, so a sell landing 4.99% below the true one-hour mean is charged the 10% tier instead of 2%"},{"citation":"resolved","description":"initialPrice is 2^96, which is one raw currency1 unit per raw currency0 unit. Both the launch token and the paired IMD token have 18 decimals, so in either pool orientation this means 1 PANIC = 1 IMD at launch. The manifest's own notes say the value was carried over from the deployment test ('Tick spacing 250 and initial sqrtPriceX96 2^96 follow the deployment test'), not chosen for this pair, and README.md:165 still describes the pool as 'PANIC paired with native ETH'. PanicMonkeys mints 1,000,000,000 PANIC; at 1 IMD each the implied fully diluted value is 1e9 IMD, about 243 times the entire IMD supply read on-chain (4,116,877.76). The hook anchors its one-hour reference at this initialization tick (afterInitialize stores initialTick and _reference() assumes it prevailed for the hour before launch), so if the factory seeds PANIC-only liquidity above this price the first trades will be judged against a reference far below any traded price, and every sell in the first hour pays the 2% tier regardless of how far it drops from the opening trades. I cannot see the launch policy's seed amounts, so I report this as a price that has no stated economic basis for this pair rather than as a proven misconfiguration; the manifest author should set initialPrice from the intended PANIC/IMD opening valuation.","line":29,"path":"launch.json","reproduction":"Decode launch.json: pairedCurrency = IMD (18 decimals), token decimals = 18, initialPrice = 79228162514264337593543950336 = 2^96 -> sqrtPrice 1.0 -> price 1 PANIC per IMD in either orientation. With TOTAL_SUPPLY = 1e27 (PanicMonkeys.sol:14), implied valuation = 1e9 IMD; IMD totalSupply() on mainnet = 4,116,877,757,721,000,000,000,000 (4.1M). A two-sided seed of even 1% of the PANIC supply at this price would need 10M IMD, more than exists. Expected: an initial price derived from the launch's PANIC/IMD valuation and the seed amounts. Actual: a placeholder from the ETH test fixture.","severity":"low","snippet":"    \"initialPrice\": \"79228162514264337593543950336\"","title":"Manifest initial price values 1 PANIC at 1 IMD, implying a launch valuation of 1e9 IMD against a total IMD supply of 4.1M"},{"citation":"resolved","description":"The brief says the sell fee is taken 'from the output on sells (afterSwap return delta)'. For an exact-output sell the paired output is the specified currency, which a v4 afterSwap delta cannot adjust, so beforeSwap reverts the whole swap. The same mechanism makes afterSwap revert fee-bearing exact-input buys that fill partially (line 356, PartialExactInputBuyNotSupported) because the fee was reserved from the specified input in beforeSwap. Both are documented in README.md as integration limitations and neither loses funds, but they are user-facing failures that the brief does not list among the accepted ones: a seller using an aggregator's exact-output route, or a dip buyer whose router sets a binding sqrtPriceLimitX96 on an exact-input buy, gets a revert instead of a taxed trade. An alternative that keeps the brief's economics is to take the sell fee in the unspecified (PANIC) side for exact-output sells converted at the post-swap price, or to document the restriction in the manifest notes so routers can be configured.","line":323,"path":"src/PanicHook.sol","reproduction":"PANIC/ETH pool at 1:1 with full-range liquidity. Call swapRouter.swap with zeroForOne = false (sell PANIC), amountSpecified = +1e18 (exact output of 1 ETH), sqrtPriceLimitX96 = MAX_SQRT_PRICE - 1. Expected per the brief: the sell executes and 2% of the 1 ETH output is taken as hook fee. Actual: the PoolManager reverts with WrappedError(hook, beforeSwap.selector, ExactOutputSellNotSupported, HookCallFailed) (existing test test_exactOutputSellIsRejected). Second case: after _sellToDrawdown(1000), an exact-input buy of 100 ETH with sqrtPriceLimitX96 = price - price/10000 reverts with PartialExactInputBuyNotSupported (existing test test_partialDipBuyRevertsWithoutChargingOrMovingThePool).","severity":"low","snippet":"        if (params.amountSpecified > 0) revert ExactOutputSellNotSupported();","title":"Exact-output sells are rejected, so any router that quotes a sell by desired paired output cannot trade this pool"}],"hash":"bd245b8198f77c9f846e4dbb301c99868b05c4c0095f1bd1581eec1d750fbf1b","nodeId":"cbe119c7-5e51-477c-9634-68faa8f417ef","outcome":"completed","summary":"The review is complete. The findings are in `.imd-findings.json` at the repository root, no tracked file was changed, and the scratch tests were removed after I ran them.\n\n**What I found**\n\n- **Medium: the buyback cap does not fit the manifest's pair.** The cap is 1e18 minor units, written for a native-ETH pair per the README. The manifest pairs PANIC with the IMD token, which I confirmed on-chain has 18 decimals and a 4.1M total supply. One call therefore spends at most 1 IMD but costs 177k to 247k gas, so on mainnet the gas exceeds the value burned and the burn bucket is left to accrue forever. That conflicts with the brief's burn outlet and the \"no dust stuck\" rule.\n- **Low: tier boundaries are quantized to a whole tick.** The reference floors the one-hour mean tick. I reproduced a sell that ends 4.99% below the true mean and is charged the 10% tier, paying about 25.3 instead of 5.1 paired units. The band is only 1 bp wide at each threshold.\n- **Low: the manifest's initial price values 1 PANIC at 1 IMD.** That implies a launch valuation of 1e9 IMD against the token's entire 4.1M supply. The manifest notes admit the value came from the ETH test fixture. I could not see the policy's seed amounts, so this is reported as a price with no stated basis rather than a proven misconfiguration.\n- **Low: exact-output sells and partially filled fee-bearing exact-input buys revert.** Documented in the README but user-facing and not among the brief's accepted limitations.\n\n**What holds**\n\nThe fee split, claim backing, reference immunity to same-block trades, the 98% buyback floor, the dip-fee self-taxation on buybacks, and all delta accounting traced cleanly. The existing suite of 107 tests passed on this tree. The coverage record answers all 12 entry points plus five invariant and economics rows. Buyback timing by sellers, tax-free maker exits via PANIC-only liquidity, and JIT capture of the LP donation were examined and recorded as accepted designs consistent with the brief, not as defects.\n\nSources for the paired-token identification: [Bitget IMD page](https://web3.bitget.com/en/swap/eth/0xD34a99Bc0f67aE1bbd63C660e6d0b0dd03E263B7), [OKX IMD guide](https://www.okx.com/en-us/how-to-buy/identity-md-imd), plus direct RPC reads of symbol, name, decimals and totalSupply.","treeHash":null,"usage":{"cachedInputTokens":2804709,"inputTokens":450,"model":"claude-fable-5-1","outputTokens":67280,"runtime":"claude","turns":43,"wallClockMs":1264871}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"a2f84c86958f4f37","findings":[],"hash":"c15d10cddd57da6e58305a3cea7de83e0c8d0683ca3b3ec14f454169943bd9f4","nodeId":"b41d7c2f-ead1-4e77-8741-7e0763c53e15","outcome":"failed","summary":"runtime reported <synthetic>, not the required premium model claude-fable-5-1","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":"<synthetic>","outputTokens":0,"runtime":"claude","turns":1,"wallClockMs":685}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"5ded77c3c883b7b0","findings":[],"hash":"cc8c38d3e2a7bd3242ffd4ac13a9a823dee1e85b25232f43133af5b74ba56849","nodeId":"4cb57aad-4681-42e4-affd-58a57b2c40ed","outcome":"failed","summary":"could not restore accepted work: accepted work conflicts with a dependency, which plan validation should have prevented: ","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":null,"outputTokens":0,"runtime":"claude","turns":0,"wallClockMs":1029}},{"artifacts":[],"attempt":1,"bundleHash":"c5f1caf013db87e3c4ecd3d7c3c17931410515be645209ac60ee982f9ffee33c","device":"19542bcd32391419","findings":[],"hash":"d16b52db738289d69e805855c84f9ea3acaa3e9cdc43d1cd7c99cc41678d01d3","nodeId":"ec86f4a4-a923-478f-8a4f-ac9135a6532c","outcome":"completed","summary":"Added 16 regression tests covering rollback, recovery, and recipient reentry. Expanded invariants with exact-output buys and the independent 98% buyback floor.\n\nOffline `forge build` and `forge test` pass: **129 passed, 0 failed, 0 skipped**.\n\nOnly `test/` changed. No new defects found.","treeHash":"3b53048569d95460567cf192e07eeb7e08872e0c","usage":{"cachedInputTokens":2249088,"inputTokens":138583,"model":"gpt-6-astra","outputTokens":11599,"runtime":"codex","turns":6,"wallClockMs":508504}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"6407a9ab49278517","findings":[],"hash":"eda784ca73659a70e970ebd86a4ecb8df986e6a5367bff74b590a58c750cd1ea","nodeId":"cbe119c7-5e51-477c-9634-68faa8f417ef","outcome":"failed","summary":"This content was flagged for possible cybersecurity risk. If this seems wrong, try rephrasing your request. If you’re doing authorized security work that requires more cyber permissive safeguards, apply for Daybreak access via https://platform.openai.com/… before retrying.","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":"gpt-6-astra","outputTokens":0,"runtime":"codex","turns":1,"wallClockMs":60047}},{"artifacts":[],"attempt":1,"bundleHash":"78dca04dcd09eb6a83df7d0685125feadc37c6c7ad464347a008f161259bbdad","device":"4199bf0c80a9d6cf","findings":[],"hash":"fe4775484ae429b57252eccdc0eb89801b0710e65baa05162355198f08504a67","nodeId":"5ab1373f-577d-4afa-9d17-f9ba02defd6c","outcome":"completed","summary":"","treeHash":"669047a93aa53f145e5eb292d0a7749de24b72e6","usage":{"cachedInputTokens":13730511,"inputTokens":1890,"model":"claude-fable-5-1","outputTokens":206834,"runtime":"claude","turns":61,"wallClockMs":3001169}}],"verification":[{"checks":[{"durationMs":81981,"exitCode":0,"name":"build","output":"Compiling 91 files with Solc 0.8.26\nSolc 0.8.26 finished in 81.88s\nCompiler run successful!\n","passed":true},{"durationMs":4656,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 6 tests for test/PanicHook.PriceMath.t.sol:PanicHookPriceMathTest\n[PASS] testFuzz_referenceQuoteMatchesSingleDivision(uint64,uint128) (runs: 256, μ: 13400, ~: 13352)\n[PASS] test_dustBuybackUsesExactReferenceQuoteAndRevertsAtomically() (gas: 863845)\n[PASS] test_referenceQuoteAtExtremeSqrtPrices() (gas: 22908)\n[PASS] test_referenceQuoteHandlesZeroAndMaximumAtParity() (gas: 24205)\n[PASS] test_referenceQuoteRetainsRemainderInBothOrientations() (gas: 12666)\n[PASS] test_referenceQuoteRevertsIfResultOverflows() (gas: 18996)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 43.10ms (7.05ms CPU time)\n\nRan 6 tests for test/PanicHook.Flipped.t.sol:PanicHookPanicAsCurrency1Erc20Test\n[PASS] test_buyWhileDownPays1PercentOfPairedInput() (gas: 616315)\n[PASS] test_buyWhileNotDownIsFree() (gas: 220721)\n[PASS] test_orientationIsDetected() (gas: 17612)\n[PASS] test_outletsWorkWithAnErc20PairedToken() (gas: 3743633)\n[PASS] test_referenceUnmovedByTradesInTheBlock() (gas: 611184)\n[PASS] test_sellTo20PercentDownPays20PercentInThePairedToken() (gas: 454087)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 49.01ms (6.06ms CPU time)\n\nRan 20 tests for test/PanicHook.Fees.t.sol:PanicHookFeesTest\n[PASS] testFuzz_drawdownIsZeroAtOrAboveReferenceAndNeverAbove100Percent(uint160,uint160) (runs: 256, μ: 13514, ~: 13474)\n[PASS] testFuzz_hookFeeNeverExceeds30Percent(uint256) (runs: 256, μ: 22814, ~: 22876)\n[PASS] test_buyIsJudgedOnThePriceBeforeTheBuy() (gas: 1047069)\n[PASS] test_buyTierSwitchesExactlyAt5Percent() (gas: 18561)\n[PASS] test_buyWhileDownPays1PercentOfInput() (gas: 581764)\n[PASS] test_buyWhileNotDownPaysNoHookFee() (gas: 212875)\n[PASS] test_drawdownIsExactAtThresholds() (gas: 194177)\n[PASS] test_exactOutputBuyPaysFeeOnThePairedInput() (gas: 584580)\n[PASS] test_exactOutputBuyWhileNotDownPaysNothing() (gas: 215357)\n[PASS] test_exactOutputSellIsRejected() (gas: 91320)\n[PASS] test_feeEventReportsDrawdownTierAndAmount() (gas: 603078)\n[PASS] test_feesAreTakenOnlyInThePairedCurrency() (gas: 777784)\n[PASS] test_hookFeeCappedAt30PercentEvenInACrash() (gas: 407297)\n[PASS] test_noAddressIsExempt() (gas: 1339523)\n[PASS] test_sellEnding30PercentOrMoreDownPays30PercentAndNoMore() (gas: 407197)\n[PASS] test_sellEndingBetween5And15PercentDownPays10Percent() (gas: 406898)\n[PASS] test_sellMovingPriceFromNotDownTo20PercentDownPays20Percent() (gas: 434073)\n[PASS] test_sellTiersSwitchAtExactBoundaryPrices() (gas: 1797651)\n[PASS] test_sellTiersSwitchExactlyAt5_15_30Percent() (gas: 32225)\n[PASS] test_sellWhileNotDownPays2PercentOfOutput() (gas: 371925)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 58.36ms (23.73ms CPU time)\n\nRan 2 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_deployIsRepeatableWithFreshState() (gas: 32594706)\n[PASS] test_deployProducesTokenHookAndPool() (gas: 16720362)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 67.61ms (113.15ms CPU time)\n\nRan 9 tests for test/PanicMonkeys.t.sol:PanicMonkeysTest\n[PASS] test_approveAndTransferFrom() (gas: 216975)\n[PASS] test_infiniteAllowanceIsNotDecremented() (gas: 116621)\n[PASS] test_metadata() (gas: 19860)\n[PASS] test_mintsExactlyOneBillionToDeployer() (gas: 16915)\n[PASS] test_noMintOrAdminEntrypoints() (gas: 144962)\n[PASS] test_runtimeHasNoDelegatecallOrSelfdestruct() (gas: 242678)\n[PASS] test_transferMovesExactAmount() (gas: 77743)\n[PASS] test_transferRevertsOnInsufficientBalance() (gas: 37711)\n[PASS] test_transferToZeroAddressReverts() (gas: 30229)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 79.85ms (2.27ms CPU time)\n\nRan 5 tests for test/PanicHook.Jit.t.sol:PanicHookJitTest\n[PASS] test_forfeitedFeesGoToTheLiquidityThatStayed() (gas: 804356)\n[PASS] test_positionHeldAcrossBlocksKeepsItsFees() (gas: 555835)\n[PASS] test_secondAddInTheSameBlockCannotCollectFees() (gas: 816292)\n[PASS] test_sellerCannotRecaptureTheirOwnDonationWithSameBlockLiquidity() (gas: 1163627)\n[PASS] test_withNoLiquidityLeftForfeitedFeesAreBucketedAndBurned() (gas: 1232202)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 85.51ms (4.42ms CPU time)\n\nRan 11 tests for test/PanicHook.Revision.t.sol:PanicHookRevisionTest\n[PASS] testFuzz_fullDipBuyFeeIsAtMostOnePercentOfPoolInput(uint96) (runs: 256, μ: 604577, ~: 606709)\n[PASS] testFuzz_tinyBuybacksAreAtomicAndBurnAllOutput(uint16) (runs: 256, μ: 552746, ~: 555807)\n[PASS] test_buybackFloorUsesTheUnroundedReferenceQuote() (gas: 852228)\n[PASS] test_dustBuybackRevertsAndPreservesAllFunds() (gas: 541176)\n[PASS] test_exactOutputLimitedDipBuyChargesOnlyRealisedInput() (gas: 615641)\n[PASS] test_jitPositionCannotCaptureAnEarlierSwapsDonation() (gas: 1111524)\n[PASS] test_partialBuyWithoutHookFeeStillWorks() (gas: 205835)\n[PASS] test_partialBuybackReallocatesFeeOnlyOnRealisedInput() (gas: 1289007)\n[PASS] test_partialDipBuyRevertsWithoutChargingOrMovingThePool() (gas: 591799)\n[PASS] test_perCallCapAllowsMultipleBuybacksInOneBlock() (gas: 842417)\n[PASS] test_referenceUsesDocumentedWholeTickRounding() (gas: 446279)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 91.25ms (102.19ms CPU time)\n\nRan 6 tests for test/PanicHook.Flipped.t.sol:PanicHookPanicAsCurrency0Test\n[PASS] test_buyWhileDownPays1PercentOfPairedInput() (gas: 620656)\n[PASS] test_buyWhileNotDownIsFree() (gas: 215230)\n[PASS] test_orientationIsDetected() (gas: 17612)\n[PASS] test_outletsWorkWithAnErc20PairedToken() (gas: 3733983)\n[PASS] test_referenceUnmovedByTradesInTheBlock() (gas: 605139)\n[PASS] test_sellTo20PercentDownPays20PercentInThePairedToken() (gas: 458618)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 101.58ms (5.57ms CPU time)\n\nRan 17 tests for test/PanicHook.Init.t.sol:PanicHookInitTest\n[PASS] test_anyStaticLpFeeTierIsAccepted() (gas: 15441444)\n[PASS] test_constructorRejectsAddressWithoutFlags() (gas: 10743)\n[PASS] test_constructorRejectsDifferentOracleFund() (gas: 4370421)\n[PASS] test_constructorRejectsZeroAddresses() (gas: 91402873)\n[PASS] test_constructorStoresImmutables() (gas: 19671)\n[PASS] test_disabledCallbacksRevert() (gas: 63323)\n[PASS] test_dynamicFeePoolIsRefused() (gas: 3980227)\n[PASS] test_enabledCallbacksRefuseCallersOtherThanThePoolManager() (gas: 143286)\n[PASS] test_initializationRegistersPoolAndFirstObservation() (gas: 120464)\n[PASS] test_liquidityCallbacksOnlyAcceptThePoolManager() (gas: 70361)\n[PASS] test_noAdminSurface() (gas: 196531)\n[PASS] test_permissionsMatchDeclaredFlagsAndAddress() (gas: 14742)\n[PASS] test_poolManagerIsTheOnlyPathIntoSwapCallbacks() (gas: 56016)\n[PASS] test_poolWithoutPanicIsRefused() (gas: 5376657)\n[PASS] test_runtimeCodeHasNoEscapeHatchAndFitsEip170() (gas: 7261972)\n[PASS] test_secondPoolCannotBeRegistered() (gas: 49173)\n[PASS] test_unlockCallbackCannotBeDrivenByAnyoneElse() (gas: 35684)\nSuite result: ok. 17 passed; 0 failed; 0 skipped; finished in 101.60ms (136.90ms CPU time)\n\nRan 18 tests for test/PanicHook.Buckets.t.sol:PanicHookBucketsTest\n[PASS] testFuzz_splitOfAnyFeeSumsExactly(uint128) (runs: 1000, μ: 352547, ~: 367527)\n[PASS] test_allThreeOutletsDrainEverythingLeavingNoDust() (gas: 3979302)\n[PASS] test_buybackAndBurnSendsEveryTokenBoughtToTheDeadAddress() (gas: 3661368)\n[PASS] test_buybackCannotMoveTheReferenceAndPaysTheDipFee() (gas: 709317)\n[PASS] test_buybackRevertsWhenPriceIsMoreThan2PercentAboveReference() (gas: 792422)\n[PASS] test_buybackRevertsWhenThereIsNothingToSpend() (gas: 541023)\n[PASS] test_buybackRevertsWithTheSpecificErrorWhenTooExpensive() (gas: 692816)\n[PASS] test_buybackSpendsAtMostTheCapPerCall() (gas: 899884)\n[PASS] test_buybackSucceedsAtAFlatPriceWithinTheLpFeeTolerance() (gas: 554471)\n[PASS] test_claimOracleFundIsPermissionlessAndPaysOnlyTheOracleAddress() (gas: 534651)\n[PASS] test_claimToARecipientThatRejectsEthFailsWithoutBlockingSwaps() (gas: 5309177)\n[PASS] test_donateRevertsWhileNoLiquidityIsInRangeAndKeepsTheBucket() (gas: 1288625)\n[PASS] test_donationReachesTheLiquidityProviderOnWithdrawal() (gas: 517234)\n[PASS] test_everyFeeIsSplitExactlyWithNoDust() (gas: 886688)\n[PASS] test_feeBearingBuyWorksOnAFreshManagerWhosePoolHoldsTokensOnly() (gas: 13176892)\n[PASS] test_feeSplitSumsToExactly100Percent() (gas: 26664)\n[PASS] test_smallBucketIsSpentInOneCall() (gas: 511784)\n[PASS] test_swapDonatesImmediatelyToInRangeLiquidityProviders() (gas: 449549)\nSuite result: ok. 18 passed; 0 failed; 0 skipped; finished in 101.73ms (129.02ms CPU time)\n\nRan 10 tests for test/PanicHook.Oracle.t.sol:PanicHookOracleTest\n[PASS] test_aCrashInThisBlockIsJudgedAgainstTheUntouchedReference() (gas: 705334)\n[PASS] test_afterAnHourDownButFlatThePanicTierNoLongerApplies() (gas: 997666)\n[PASS] test_atMostOneObservationPerBlockTakenBeforeTheFirstSwap() (gas: 815063)\n[PASS] test_blocksSharingATimestampDoNotDuplicateObservations() (gas: 904658)\n[PASS] test_buyAndSellInTheSameBlockCannotMoveTheReference() (gas: 1068382)\n[PASS] test_launchPriceAnchorsTheWindowBeforeTheFirstObservation() (gas: 451182)\n[PASS] test_panicTierStillAppliesBeforeTheHourIsUp() (gas: 715980)\n[PASS] test_referenceIsTheOneHourMeanTick() (gas: 484502)\n[PASS] test_swapsInTheInitializationBlockRecordNothingNew() (gas: 552620)\n[PASS] test_viewMatchesAnIndependentTwapOverManyObservations() (gas: 98224564)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 137.95ms (93.83ms CPU time)\n\nRan 4 tests for test/PanicMonkeys.Properties.t.sol:PanicMonkeysPropertiesTest\n[PASS] invariant_supplyBalancesAndAllowancesMatchIndependentLedger() (runs: 256, calls: 16384, reverts: 0)\n\n╭-------------------+--------------+-------+---------+----------╮\n| Contract          | Selector     | Calls | Reverts | Discards |\n+===============================================================+\n| PanicTokenHandler | approve      | 5614  | 0       | 0        |\n|-------------------+--------------+-------+---------+----------|\n| PanicTokenHandler | transfer     | 5392  | 0       | 0        |\n|-------------------+--------------+-------+---------+----------|\n| PanicTokenHandler | transferFrom | 5378  | 0       | 0        |\n╰-------------------+--------------+-------+---------+----------╯\n\n[PASS] testFuzz_transferFromFailureRestoresFiniteAllowance(uint256) (runs: 1000, μ: 120240, ~: 120133)\n[PASS] test_selfTransferOfFullSupplyAndZeroTransferFrom() (gas: 110214)\n[PASS] test_zeroAddressFailurePreservesBalanceAndAllowance() (gas: 108800)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 2.67s (2.68s CPU time)\n\nRan 2 tests for test/PanicHook.Invariant.t.sol:PanicNativeInvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+---------------+-------+---------+----------╮\n| Contract               | Selector      | Calls | Reverts | Discards |\n+=====================================================================+\n| PanicAccountingHandler | advance       | 2406  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buy           | 2398  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buyback       | 2362  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | claim         | 2300  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | donate        | 2259  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | sell          | 2355  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic | 2304  | 0       | 0        |\n╰------------------------+---------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2486085)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.29s (4.24s CPU time)\n\nRan 2 tests for test/PanicHook.Invariant.t.sol:PanicCurrency1InvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+---------------+-------+---------+----------╮\n| Contract               | Selector      | Calls | Reverts | Discards |\n+=====================================================================+\n| PanicAccountingHandler | advance       | 2406  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buy           | 2398  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buyback       | 2362  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | claim         | 2300  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | donate        | 2259  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | sell          | 2355  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic | 2304  | 0       | 0        |\n╰------------------------+---------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2558457)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.46s (4.42s CPU time)\n\nRan 2 tests for test/PanicHook.Invariant.t.sol:PanicCurrency0InvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+---------------+-------+---------+----------╮\n| Contract               | Selector      | Calls | Reverts | Discards |\n+=====================================================================+\n| PanicAccountingHandler | advance       | 2406  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buy           | 2398  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buyback       | 2362  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | claim         | 2300  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | donate        | 2259  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | sell          | 2355  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic | 2304  | 0       | 0        |\n╰------------------------+---------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2560824)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.56s (4.50s CPU time)\n\nRan 15 test suites in 4.56s (16.90s CPU time): 120 tests passed, 0 failed, 0 skipped (120 total tests)\n","passed":true},{"durationMs":54,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"PanicHook.afterAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"PanicHook.afterInitialize(address,(address,address,uint24,int24,address),uint160,int24)\",\"PanicHook.afterRemoveLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"PanicHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"PanicHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"PanicHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"PanicHook.buybackAndBurn()\",\"PanicHook.buybackAndBurn(uint256)\",\"PanicHook.claimOracleFund()\",\"PanicHook.donateToLiquidityProviders()\",\"PanicHook.unlockCallback(bytes)\",\"PanicMonkeys.approve(address,uint256)\",\"PanicMonkeys.transfer(address,uint256)\",\"PanicMonkeys.transferFrom(address,address,uint256)\"],\"files\":{\"README.md\":320,\"foundry.toml\":33,\"launch.json\":36,\"remappings.txt\":3,\"script/DeployPanic.s.sol\":77,\"src/HookFlags.sol\":43,\"src/HookMiner.sol\":48,\"src/PanicHook.sol\":866,\"src/PanicMonkeys.sol\":68,\"test/Deploy.t.sol\":78,\"test/PanicHook.Buckets.t.sol\":419,\"test/PanicHook.Fees.t.sol\":294,\"test/PanicHook.Flipped.t.sol\":104,\"test/PanicHook.Init.t.sol\":263,\"test/PanicHook.Invariant.t.sol\":143,\"test/PanicHook.Jit.t.sol\":99,\"test/PanicHook.Oracle.t.sol\":222,\"test/PanicHook.PriceMath.t.sol\":96,\"test/PanicHook.Revision.t.sol\":204,\"test/PanicMonkeys.Properties.t.sol\":137,\"test/PanicMonkeys.t.sol\":96,\"test/README.md\":46,\"test/handlers/PanicAccountingHandler.sol\":294,\"test/mocks/MockERC20.sol\":52,\"test/utils/PanicTestBase.sol\":281},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"0161f705c0547bc761008c5dfea08b0762cba6474e8910facb4cbab2fba2721f","verifiedTreeHash":"777ee493c79a0df760de7c79fdfaa4925a2be9cb","verifierVersion":"0.1.0+a2d9a899"},{"checks":[{"durationMs":92531,"exitCode":0,"name":"build","output":"Compiling 92 files with Solc 0.8.26\nSolc 0.8.26 finished in 92.44s\nCompiler run successful!\n","passed":true},{"durationMs":4989,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 9 tests for test/PanicMonkeys.t.sol:PanicMonkeysTest\n[PASS] test_approveAndTransferFrom() (gas: 216975)\n[PASS] test_infiniteAllowanceIsNotDecremented() (gas: 116621)\n[PASS] test_metadata() (gas: 19860)\n[PASS] test_mintsExactlyOneBillionToDeployer() (gas: 16915)\n[PASS] test_noMintOrAdminEntrypoints() (gas: 144962)\n[PASS] test_runtimeHasNoDelegatecallOrSelfdestruct() (gas: 242678)\n[PASS] test_transferMovesExactAmount() (gas: 77743)\n[PASS] test_transferRevertsOnInsufficientBalance() (gas: 37711)\n[PASS] test_transferToZeroAddressReverts() (gas: 30229)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 886.24µs (1.35ms CPU time)\n\nRan 5 tests for test/PanicHook.Atomicity.t.sol:PanicNativeAtomicityTest\n[PASS] test_failedBuybackRestoresFeeGrowthAndOracleThenRecoversAfterAnHour() (gas: 1320640)\n[PASS] test_recipientCannotReenterClaimOrSpendAnotherBucketDuringPayout() (gas: 1348551)\n[PASS] test_rejectedExactOutputSellCannotPoisonNextExactInputSell() (gas: 837648)\n[PASS] test_rejectedFirstSwapRollsBackObservationAndNextSwapRecovers() (gas: 1490298)\n[PASS] test_zeroSwapsRollbackInBothDirectionsAndDoNotReserveTheBlock() (gas: 921645)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 26.42ms (4.59ms CPU time)\n\nRan 5 tests for test/PanicHook.Jit.t.sol:PanicHookJitTest\n[PASS] test_forfeitedFeesGoToTheLiquidityThatStayed() (gas: 804356)\n[PASS] test_positionHeldAcrossBlocksKeepsItsFees() (gas: 555835)\n[PASS] test_secondAddInTheSameBlockCannotCollectFees() (gas: 816292)\n[PASS] test_sellerCannotRecaptureTheirOwnDonationWithSameBlockLiquidity() (gas: 1163627)\n[PASS] test_withNoLiquidityLeftForfeitedFeesAreBucketedAndBurned() (gas: 1232202)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 28.43ms (3.42ms CPU time)\n\nRan 4 tests for test/PanicHook.Atomicity.t.sol:PanicCurrency0AtomicityTest\n[PASS] test_failedBuybackRestoresFeeGrowthAndOracleThenRecoversAfterAnHour() (gas: 1379057)\n[PASS] test_rejectedExactOutputSellCannotPoisonNextExactInputSell() (gas: 892507)\n[PASS] test_rejectedFirstSwapRollsBackObservationAndNextSwapRecovers() (gas: 1556239)\n[PASS] test_zeroSwapsRollbackInBothDirectionsAndDoNotReserveTheBlock() (gas: 985533)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 33.90ms (3.20ms CPU time)\n\nRan 6 tests for test/PanicHook.Flipped.t.sol:PanicHookPanicAsCurrency0Test\n[PASS] test_buyWhileDownPays1PercentOfPairedInput() (gas: 620656)\n[PASS] test_buyWhileNotDownIsFree() (gas: 215230)\n[PASS] test_orientationIsDetected() (gas: 17612)\n[PASS] test_outletsWorkWithAnErc20PairedToken() (gas: 3733983)\n[PASS] test_referenceUnmovedByTradesInTheBlock() (gas: 605139)\n[PASS] test_sellTo20PercentDownPays20PercentInThePairedToken() (gas: 458618)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 34.76ms (4.60ms CPU time)\n\nRan 4 tests for test/PanicHook.Atomicity.t.sol:PanicCurrency1AtomicityTest\n[PASS] test_failedBuybackRestoresFeeGrowthAndOracleThenRecoversAfterAnHour() (gas: 1375809)\n[PASS] test_rejectedExactOutputSellCannotPoisonNextExactInputSell() (gas: 887225)\n[PASS] test_rejectedFirstSwapRollsBackObservationAndNextSwapRecovers() (gas: 1549179)\n[PASS] test_zeroSwapsRollbackInBothDirectionsAndDoNotReserveTheBlock() (gas: 991000)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 52.85ms (4.05ms CPU time)\n\nRan 6 tests for test/PanicHook.Flipped.t.sol:PanicHookPanicAsCurrency1Erc20Test\n[PASS] test_buyWhileDownPays1PercentOfPairedInput() (gas: 616315)\n[PASS] test_buyWhileNotDownIsFree() (gas: 220721)\n[PASS] test_orientationIsDetected() (gas: 17612)\n[PASS] test_outletsWorkWithAnErc20PairedToken() (gas: 3743633)\n[PASS] test_referenceUnmovedByTradesInTheBlock() (gas: 611184)\n[PASS] test_sellTo20PercentDownPays20PercentInThePairedToken() (gas: 454087)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 55.55ms (5.72ms CPU time)\n\nRan 2 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_deployIsRepeatableWithFreshState() (gas: 32594706)\n[PASS] test_deployProducesTokenHookAndPool() (gas: 16720362)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 60.40ms (90.05ms CPU time)\n\nRan 18 tests for test/PanicHook.Buckets.t.sol:PanicHookBucketsTest\n[PASS] testFuzz_splitOfAnyFeeSumsExactly(uint128) (runs: 1000, μ: 352114, ~: 367527)\n[PASS] test_allThreeOutletsDrainEverythingLeavingNoDust() (gas: 3979302)\n[PASS] test_buybackAndBurnSendsEveryTokenBoughtToTheDeadAddress() (gas: 3661368)\n[PASS] test_buybackCannotMoveTheReferenceAndPaysTheDipFee() (gas: 709317)\n[PASS] test_buybackRevertsWhenPriceIsMoreThan2PercentAboveReference() (gas: 792422)\n[PASS] test_buybackRevertsWhenThereIsNothingToSpend() (gas: 541023)\n[PASS] test_buybackRevertsWithTheSpecificErrorWhenTooExpensive() (gas: 692816)\n[PASS] test_buybackSpendsAtMostTheCapPerCall() (gas: 899884)\n[PASS] test_buybackSucceedsAtAFlatPriceWithinTheLpFeeTolerance() (gas: 554471)\n[PASS] test_claimOracleFundIsPermissionlessAndPaysOnlyTheOracleAddress() (gas: 534651)\n[PASS] test_claimToARecipientThatRejectsEthFailsWithoutBlockingSwaps() (gas: 5309177)\n[PASS] test_donateRevertsWhileNoLiquidityIsInRangeAndKeepsTheBucket() (gas: 1288625)\n[PASS] test_donationReachesTheLiquidityProviderOnWithdrawal() (gas: 517234)\n[PASS] test_everyFeeIsSplitExactlyWithNoDust() (gas: 886688)\n[PASS] test_feeBearingBuyWorksOnAFreshManagerWhosePoolHoldsTokensOnly() (gas: 13176892)\n[PASS] test_feeSplitSumsToExactly100Percent() (gas: 26664)\n[PASS] test_smallBucketIsSpentInOneCall() (gas: 511784)\n[PASS] test_swapDonatesImmediatelyToInRangeLiquidityProviders() (gas: 449549)\nSuite result: ok. 18 passed; 0 failed; 0 skipped; finished in 66.48ms (79.67ms CPU time)\n\nRan 17 tests for test/PanicHook.Init.t.sol:PanicHookInitTest\n[PASS] test_anyStaticLpFeeTierIsAccepted() (gas: 15441444)\n[PASS] test_constructorRejectsAddressWithoutFlags() (gas: 10743)\n[PASS] test_constructorRejectsDifferentOracleFund() (gas: 4370421)\n[PASS] test_constructorRejectsZeroAddresses() (gas: 91402873)\n[PASS] test_constructorStoresImmutables() (gas: 19671)\n[PASS] test_disabledCallbacksRevert() (gas: 63323)\n[PASS] test_dynamicFeePoolIsRefused() (gas: 3980227)\n[PASS] test_enabledCallbacksRefuseCallersOtherThanThePoolManager() (gas: 143286)\n[PASS] test_initializationRegistersPoolAndFirstObservation() (gas: 120464)\n[PASS] test_liquidityCallbacksOnlyAcceptThePoolManager() (gas: 70361)\n[PASS] test_noAdminSurface() (gas: 196531)\n[PASS] test_permissionsMatchDeclaredFlagsAndAddress() (gas: 14742)\n[PASS] test_poolManagerIsTheOnlyPathIntoSwapCallbacks() (gas: 56016)\n[PASS] test_poolWithoutPanicIsRefused() (gas: 5376657)\n[PASS] test_runtimeCodeHasNoEscapeHatchAndFitsEip170() (gas: 7261972)\n[PASS] test_secondPoolCannotBeRegistered() (gas: 49173)\n[PASS] test_unlockCallbackCannotBeDrivenByAnyoneElse() (gas: 35684)\nSuite result: ok. 17 passed; 0 failed; 0 skipped; finished in 89.57ms (118.26ms CPU time)\n\nRan 11 tests for test/PanicHook.Revision.t.sol:PanicHookRevisionTest\n[PASS] testFuzz_fullDipBuyFeeIsAtMostOnePercentOfPoolInput(uint96) (runs: 256, μ: 603069, ~: 606709)\n[PASS] testFuzz_tinyBuybacksAreAtomicAndBurnAllOutput(uint16) (runs: 256, μ: 552163, ~: 555807)\n[PASS] test_buybackFloorUsesTheUnroundedReferenceQuote() (gas: 852228)\n[PASS] test_dustBuybackRevertsAndPreservesAllFunds() (gas: 541176)\n[PASS] test_exactOutputLimitedDipBuyChargesOnlyRealisedInput() (gas: 615641)\n[PASS] test_jitPositionCannotCaptureAnEarlierSwapsDonation() (gas: 1111524)\n[PASS] test_partialBuyWithoutHookFeeStillWorks() (gas: 205835)\n[PASS] test_partialBuybackReallocatesFeeOnlyOnRealisedInput() (gas: 1289007)\n[PASS] test_partialDipBuyRevertsWithoutChargingOrMovingThePool() (gas: 591799)\n[PASS] test_perCallCapAllowsMultipleBuybacksInOneBlock() (gas: 842417)\n[PASS] test_referenceUsesDocumentedWholeTickRounding() (gas: 446279)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 96.46ms (93.97ms CPU time)\n\nRan 20 tests for test/PanicHook.Fees.t.sol:PanicHookFeesTest\n[PASS] testFuzz_drawdownIsZeroAtOrAboveReferenceAndNeverAbove100Percent(uint160,uint160) (runs: 256, μ: 13520, ~: 13459)\n[PASS] testFuzz_hookFeeNeverExceeds30Percent(uint256) (runs: 256, μ: 22811, ~: 22876)\n[PASS] test_buyIsJudgedOnThePriceBeforeTheBuy() (gas: 1047069)\n[PASS] test_buyTierSwitchesExactlyAt5Percent() (gas: 18561)\n[PASS] test_buyWhileDownPays1PercentOfInput() (gas: 581764)\n[PASS] test_buyWhileNotDownPaysNoHookFee() (gas: 212875)\n[PASS] test_drawdownIsExactAtThresholds() (gas: 194177)\n[PASS] test_exactOutputBuyPaysFeeOnThePairedInput() (gas: 584580)\n[PASS] test_exactOutputBuyWhileNotDownPaysNothing() (gas: 215357)\n[PASS] test_exactOutputSellIsRejected() (gas: 91320)\n[PASS] test_feeEventReportsDrawdownTierAndAmount() (gas: 603078)\n[PASS] test_feesAreTakenOnlyInThePairedCurrency() (gas: 777784)\n[PASS] test_hookFeeCappedAt30PercentEvenInACrash() (gas: 407297)\n[PASS] test_noAddressIsExempt() (gas: 1339523)\n[PASS] test_sellEnding30PercentOrMoreDownPays30PercentAndNoMore() (gas: 407197)\n[PASS] test_sellEndingBetween5And15PercentDownPays10Percent() (gas: 406898)\n[PASS] test_sellMovingPriceFromNotDownTo20PercentDownPays20Percent() (gas: 434073)\n[PASS] test_sellTiersSwitchAtExactBoundaryPrices() (gas: 1797651)\n[PASS] test_sellTiersSwitchExactlyAt5_15_30Percent() (gas: 32225)\n[PASS] test_sellWhileNotDownPays2PercentOfOutput() (gas: 371925)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 96.50ms (63.34ms CPU time)\n\nRan 6 tests for test/PanicHook.PriceMath.t.sol:PanicHookPriceMathTest\n[PASS] testFuzz_referenceQuoteMatchesSingleDivision(uint64,uint128) (runs: 256, μ: 13405, ~: 13352)\n[PASS] test_dustBuybackUsesExactReferenceQuoteAndRevertsAtomically() (gas: 863845)\n[PASS] test_referenceQuoteAtExtremeSqrtPrices() (gas: 22908)\n[PASS] test_referenceQuoteHandlesZeroAndMaximumAtParity() (gas: 24205)\n[PASS] test_referenceQuoteRetainsRemainderInBothOrientations() (gas: 12666)\n[PASS] test_referenceQuoteRevertsIfResultOverflows() (gas: 18996)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 101.94ms (79.54ms CPU time)\n\nRan 10 tests for test/PanicHook.Oracle.t.sol:PanicHookOracleTest\n[PASS] test_aCrashInThisBlockIsJudgedAgainstTheUntouchedReference() (gas: 705334)\n[PASS] test_afterAnHourDownButFlatThePanicTierNoLongerApplies() (gas: 997666)\n[PASS] test_atMostOneObservationPerBlockTakenBeforeTheFirstSwap() (gas: 815063)\n[PASS] test_blocksSharingATimestampDoNotDuplicateObservations() (gas: 904658)\n[PASS] test_buyAndSellInTheSameBlockCannotMoveTheReference() (gas: 1068382)\n[PASS] test_launchPriceAnchorsTheWindowBeforeTheFirstObservation() (gas: 451182)\n[PASS] test_panicTierStillAppliesBeforeTheHourIsUp() (gas: 715980)\n[PASS] test_referenceIsTheOneHourMeanTick() (gas: 484502)\n[PASS] test_swapsInTheInitializationBlockRecordNothingNew() (gas: 552620)\n[PASS] test_viewMatchesAnIndependentTwapOverManyObservations() (gas: 98224564)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 101.96ms (84.25ms CPU time)\n\nRan 4 tests for test/PanicMonkeys.Properties.t.sol:PanicMonkeysPropertiesTest\n[PASS] invariant_supplyBalancesAndAllowancesMatchIndependentLedger() (runs: 256, calls: 16384, reverts: 0)\n\n╭-------------------+--------------+-------+---------+----------╮\n| Contract          | Selector     | Calls | Reverts | Discards |\n+===============================================================+\n| PanicTokenHandler | approve      | 5474  | 0       | 0        |\n|-------------------+--------------+-------+---------+----------|\n| PanicTokenHandler | transfer     | 5384  | 0       | 0        |\n|-------------------+--------------+-------+---------+----------|\n| PanicTokenHandler | transferFrom | 5526  | 0       | 0        |\n╰-------------------+--------------+-------+---------+----------╯\n\n[PASS] testFuzz_transferFromFailureRestoresFiniteAllowance(uint256) (runs: 1000, μ: 120245, ~: 120133)\n[PASS] test_selfTransferOfFullSupplyAndZeroTransferFrom() (gas: 110214)\n[PASS] test_zeroAddressFailurePreservesBalanceAndAllowance() (gas: 108800)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 2.59s (2.60s CPU time)\n\nRan 4 tests for test/PanicHook.Invariant.t.sol:PanicNativeInvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+-----------------+-------+---------+----------╮\n| Contract               | Selector        | Calls | Reverts | Discards |\n+=======================================================================+\n| PanicAccountingHandler | addLiquidity    | 1579  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | advance         | 1585  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | buy             | 1648  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | buyExactOutput  | 1762  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | buyback         | 1655  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | claim           | 1616  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | donate          | 1586  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | removeLiquidity | 1633  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | sell            | 1636  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic   | 1684  | 0       | 0        |\n╰------------------------+-----------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2529175)\n[PASS] test_handlerLiquidityAroundTradesInAndAcrossBlocks() (gas: 3933916)\n[PASS] test_handlerMixesExactOutputAndExactInputAcrossTheHour() (gas: 2705406)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 4.43s (4.41s CPU time)\n\nRan 4 tests for test/PanicHook.Invariant.t.sol:PanicCurrency0InvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+-----------------+-------+---------+----------╮\n| Contract               | Selector        | Calls | Reverts | Discards |\n+=======================================================================+\n| PanicAccountingHandler | addLiquidity    | 1579  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | advance         | 1585  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | buy             | 1648  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | buyExactOutput  | 1762  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | buyback         | 1655  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | claim           | 1616  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | donate          | 1586  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | removeLiquidity | 1633  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | sell            | 1636  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic   | 1684  | 0       | 0        |\n╰------------------------+-----------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2606698)\n[PASS] test_handlerLiquidityAroundTradesInAndAcrossBlocks() (gas: 3986267)\n[PASS] test_handlerMixesExactOutputAndExactInputAcrossTheHour() (gas: 2762559)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 4.77s (4.75s CPU time)\n\nRan 4 tests for test/PanicHook.Invariant.t.sol:PanicCurrency1InvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+-----------------+-------+---------+----------╮\n| Contract               | Selector        | Calls | Reverts | Discards |\n+=======================================================================+\n| PanicAccountingHandler | addLiquidity    | 1579  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | advance         | 1585  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | buy             | 1648  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | buyExactOutput  | 1762  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | buyback         | 1655  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | claim           | 1616  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | donate          | 1586  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | removeLiquidity | 1633  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | sell            | 1636  | 0       | 0        |\n|------------------------+-----------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic   | 1684  | 0       | 0        |\n╰------------------------+-----------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2604388)\n[PASS] test_handlerLiquidityAroundTradesInAndAcrossBlocks() (gas: 4011789)\n[PASS] test_handlerMixesExactOutputAndExactInputAcrossTheHour() (gas: 2764073)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 4.90s (4.88s CPU time)\n\nRan 18 test suites in 4.90s (17.54s CPU time): 139 tests passed, 0 failed, 0 skipped (139 total tests)\n","passed":true},{"durationMs":65,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"PanicHook.afterAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"PanicHook.afterInitialize(address,(address,address,uint24,int24,address),uint160,int24)\",\"PanicHook.afterRemoveLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"PanicHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"PanicHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"PanicHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"PanicHook.buybackAndBurn()\",\"PanicHook.buybackAndBurn(uint256)\",\"PanicHook.claimOracleFund()\",\"PanicHook.donateToLiquidityProviders()\",\"PanicHook.unlockCallback(bytes)\",\"PanicMonkeys.approve(address,uint256)\",\"PanicMonkeys.transfer(address,uint256)\",\"PanicMonkeys.transferFrom(address,address,uint256)\"],\"files\":{\"README.md\":320,\"foundry.toml\":33,\"launch.json\":36,\"remappings.txt\":3,\"script/DeployPanic.s.sol\":77,\"src/HookFlags.sol\":43,\"src/HookMiner.sol\":48,\"src/PanicHook.sol\":866,\"src/PanicMonkeys.sol\":68,\"test/Deploy.t.sol\":78,\"test/PanicHook.Atomicity.t.sol\":245,\"test/PanicHook.Buckets.t.sol\":419,\"test/PanicHook.Fees.t.sol\":294,\"test/PanicHook.Flipped.t.sol\":104,\"test/PanicHook.Init.t.sol\":263,\"test/PanicHook.Invariant.t.sol\":204,\"test/PanicHook.Jit.t.sol\":99,\"test/PanicHook.Oracle.t.sol\":222,\"test/PanicHook.PriceMath.t.sol\":96,\"test/PanicHook.Revision.t.sol\":204,\"test/PanicMonkeys.Properties.t.sol\":137,\"test/PanicMonkeys.t.sol\":96,\"test/README.md\":55,\"test/handlers/PanicAccountingHandler.sol\":458,\"test/mocks/MockERC20.sol\":52,\"test/utils/PanicTestBase.sol\":281},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"2019edc1fd2cb3bf3dd2f6d4963a6dc14c9073336d47773cf08e94ef78e6c2fc","verifiedTreeHash":"25de6272f0f8a812f9330563211ec1f499c99717","verifierVersion":"0.1.0+a2d9a899"},{"checks":[{"durationMs":73224,"exitCode":0,"name":"build","output":"Compiling 91 files with Solc 0.8.26\nSolc 0.8.26 finished in 73.14s\nCompiler run successful!\n","passed":true},{"durationMs":4473,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 9 tests for test/PanicMonkeys.t.sol:PanicMonkeysTest\n[PASS] test_approveAndTransferFrom() (gas: 216975)\n[PASS] test_infiniteAllowanceIsNotDecremented() (gas: 116621)\n[PASS] test_metadata() (gas: 19860)\n[PASS] test_mintsExactlyOneBillionToDeployer() (gas: 16915)\n[PASS] test_noMintOrAdminEntrypoints() (gas: 144962)\n[PASS] test_runtimeHasNoDelegatecallOrSelfdestruct() (gas: 242678)\n[PASS] test_transferMovesExactAmount() (gas: 77743)\n[PASS] test_transferRevertsOnInsufficientBalance() (gas: 37711)\n[PASS] test_transferToZeroAddressReverts() (gas: 30229)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 10.03ms (1.77ms CPU time)\n\nRan 6 tests for test/PanicHook.Flipped.t.sol:PanicHookPanicAsCurrency1Erc20Test\n[PASS] test_buyWhileDownPays1PercentOfPairedInput() (gas: 616315)\n[PASS] test_buyWhileNotDownIsFree() (gas: 220721)\n[PASS] test_orientationIsDetected() (gas: 17612)\n[PASS] test_outletsWorkWithAnErc20PairedToken() (gas: 3743633)\n[PASS] test_referenceUnmovedByTradesInTheBlock() (gas: 611184)\n[PASS] test_sellTo20PercentDownPays20PercentInThePairedToken() (gas: 454087)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 38.22ms (5.55ms CPU time)\n\nRan 2 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_deployIsRepeatableWithFreshState() (gas: 32594706)\n[PASS] test_deployProducesTokenHookAndPool() (gas: 16720362)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 45.52ms (75.36ms CPU time)\n\nRan 20 tests for test/PanicHook.Fees.t.sol:PanicHookFeesTest\n[PASS] testFuzz_drawdownIsZeroAtOrAboveReferenceAndNeverAbove100Percent(uint160,uint160) (runs: 256, μ: 13533, ~: 13474)\n[PASS] testFuzz_hookFeeNeverExceeds30Percent(uint256) (runs: 256, μ: 22828, ~: 22876)\n[PASS] test_buyIsJudgedOnThePriceBeforeTheBuy() (gas: 1047069)\n[PASS] test_buyTierSwitchesExactlyAt5Percent() (gas: 18561)\n[PASS] test_buyWhileDownPays1PercentOfInput() (gas: 581764)\n[PASS] test_buyWhileNotDownPaysNoHookFee() (gas: 212875)\n[PASS] test_drawdownIsExactAtThresholds() (gas: 194177)\n[PASS] test_exactOutputBuyPaysFeeOnThePairedInput() (gas: 584580)\n[PASS] test_exactOutputBuyWhileNotDownPaysNothing() (gas: 215357)\n[PASS] test_exactOutputSellIsRejected() (gas: 91320)\n[PASS] test_feeEventReportsDrawdownTierAndAmount() (gas: 603078)\n[PASS] test_feesAreTakenOnlyInThePairedCurrency() (gas: 777784)\n[PASS] test_hookFeeCappedAt30PercentEvenInACrash() (gas: 407297)\n[PASS] test_noAddressIsExempt() (gas: 1339523)\n[PASS] test_sellEnding30PercentOrMoreDownPays30PercentAndNoMore() (gas: 407197)\n[PASS] test_sellEndingBetween5And15PercentDownPays10Percent() (gas: 406898)\n[PASS] test_sellMovingPriceFromNotDownTo20PercentDownPays20Percent() (gas: 434073)\n[PASS] test_sellTiersSwitchAtExactBoundaryPrices() (gas: 1797651)\n[PASS] test_sellTiersSwitchExactlyAt5_15_30Percent() (gas: 32225)\n[PASS] test_sellWhileNotDownPays2PercentOfOutput() (gas: 371925)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 53.35ms (20.20ms CPU time)\n\nRan 6 tests for test/PanicHook.Flipped.t.sol:PanicHookPanicAsCurrency0Test\n[PASS] test_buyWhileDownPays1PercentOfPairedInput() (gas: 620656)\n[PASS] test_buyWhileNotDownIsFree() (gas: 215230)\n[PASS] test_orientationIsDetected() (gas: 17612)\n[PASS] test_outletsWorkWithAnErc20PairedToken() (gas: 3733983)\n[PASS] test_referenceUnmovedByTradesInTheBlock() (gas: 605139)\n[PASS] test_sellTo20PercentDownPays20PercentInThePairedToken() (gas: 458618)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 54.85ms (4.43ms CPU time)\n\nRan 18 tests for test/PanicHook.Buckets.t.sol:PanicHookBucketsTest\n[PASS] testFuzz_splitOfAnyFeeSumsExactly(uint128) (runs: 1000, μ: 351400, ~: 367527)\n[PASS] test_allThreeOutletsDrainEverythingLeavingNoDust() (gas: 3979302)\n[PASS] test_buybackAndBurnSendsEveryTokenBoughtToTheDeadAddress() (gas: 3661368)\n[PASS] test_buybackCannotMoveTheReferenceAndPaysTheDipFee() (gas: 709317)\n[PASS] test_buybackRevertsWhenPriceIsMoreThan2PercentAboveReference() (gas: 792422)\n[PASS] test_buybackRevertsWhenThereIsNothingToSpend() (gas: 541023)\n[PASS] test_buybackRevertsWithTheSpecificErrorWhenTooExpensive() (gas: 692816)\n[PASS] test_buybackSpendsAtMostTheCapPerCall() (gas: 899884)\n[PASS] test_buybackSucceedsAtAFlatPriceWithinTheLpFeeTolerance() (gas: 554471)\n[PASS] test_claimOracleFundIsPermissionlessAndPaysOnlyTheOracleAddress() (gas: 534651)\n[PASS] test_claimToARecipientThatRejectsEthFailsWithoutBlockingSwaps() (gas: 5309177)\n[PASS] test_donateRevertsWhileNoLiquidityIsInRangeAndKeepsTheBucket() (gas: 1288625)\n[PASS] test_donationReachesTheLiquidityProviderOnWithdrawal() (gas: 517234)\n[PASS] test_everyFeeIsSplitExactlyWithNoDust() (gas: 886688)\n[PASS] test_feeBearingBuyWorksOnAFreshManagerWhosePoolHoldsTokensOnly() (gas: 13176892)\n[PASS] test_feeSplitSumsToExactly100Percent() (gas: 26664)\n[PASS] test_smallBucketIsSpentInOneCall() (gas: 511784)\n[PASS] test_swapDonatesImmediatelyToInRangeLiquidityProviders() (gas: 449549)\nSuite result: ok. 18 passed; 0 failed; 0 skipped; finished in 70.70ms (70.02ms CPU time)\n\nRan 11 tests for test/PanicHook.Revision.t.sol:PanicHookRevisionTest\n[PASS] testFuzz_fullDipBuyFeeIsAtMostOnePercentOfPoolInput(uint96) (runs: 256, μ: 604431, ~: 606709)\n[PASS] testFuzz_tinyBuybacksAreAtomicAndBurnAllOutput(uint16) (runs: 256, μ: 552622, ~: 555807)\n[PASS] test_buybackFloorUsesTheUnroundedReferenceQuote() (gas: 852228)\n[PASS] test_dustBuybackRevertsAndPreservesAllFunds() (gas: 541176)\n[PASS] test_exactOutputLimitedDipBuyChargesOnlyRealisedInput() (gas: 615641)\n[PASS] test_jitPositionCannotCaptureAnEarlierSwapsDonation() (gas: 1111524)\n[PASS] test_partialBuyWithoutHookFeeStillWorks() (gas: 205835)\n[PASS] test_partialBuybackReallocatesFeeOnlyOnRealisedInput() (gas: 1289007)\n[PASS] test_partialDipBuyRevertsWithoutChargingOrMovingThePool() (gas: 591799)\n[PASS] test_perCallCapAllowsMultipleBuybacksInOneBlock() (gas: 842417)\n[PASS] test_referenceUsesDocumentedWholeTickRounding() (gas: 446279)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 78.30ms (84.00ms CPU time)\n\nRan 6 tests for test/PanicHook.PriceMath.t.sol:PanicHookPriceMathTest\n[PASS] testFuzz_referenceQuoteMatchesSingleDivision(uint64,uint128) (runs: 256, μ: 13414, ~: 13397)\n[PASS] test_dustBuybackUsesExactReferenceQuoteAndRevertsAtomically() (gas: 863845)\n[PASS] test_referenceQuoteAtExtremeSqrtPrices() (gas: 22908)\n[PASS] test_referenceQuoteHandlesZeroAndMaximumAtParity() (gas: 24205)\n[PASS] test_referenceQuoteRetainsRemainderInBothOrientations() (gas: 12666)\n[PASS] test_referenceQuoteRevertsIfResultOverflows() (gas: 18996)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 101.69ms (80.85ms CPU time)\n\nRan 5 tests for test/PanicHook.Jit.t.sol:PanicHookJitTest\n[PASS] test_forfeitedFeesGoToTheLiquidityThatStayed() (gas: 804356)\n[PASS] test_positionHeldAcrossBlocksKeepsItsFees() (gas: 555835)\n[PASS] test_secondAddInTheSameBlockCannotCollectFees() (gas: 816292)\n[PASS] test_sellerCannotRecaptureTheirOwnDonationWithSameBlockLiquidity() (gas: 1163627)\n[PASS] test_withNoLiquidityLeftForfeitedFeesAreBucketedAndBurned() (gas: 1232202)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 101.67ms (3.79ms CPU time)\n\nRan 17 tests for test/PanicHook.Init.t.sol:PanicHookInitTest\n[PASS] test_anyStaticLpFeeTierIsAccepted() (gas: 15441444)\n[PASS] test_constructorRejectsAddressWithoutFlags() (gas: 10743)\n[PASS] test_constructorRejectsDifferentOracleFund() (gas: 4370421)\n[PASS] test_constructorRejectsZeroAddresses() (gas: 91402873)\n[PASS] test_constructorStoresImmutables() (gas: 19671)\n[PASS] test_disabledCallbacksRevert() (gas: 63323)\n[PASS] test_dynamicFeePoolIsRefused() (gas: 3980227)\n[PASS] test_enabledCallbacksRefuseCallersOtherThanThePoolManager() (gas: 143286)\n[PASS] test_initializationRegistersPoolAndFirstObservation() (gas: 120464)\n[PASS] test_liquidityCallbacksOnlyAcceptThePoolManager() (gas: 70361)\n[PASS] test_noAdminSurface() (gas: 196531)\n[PASS] test_permissionsMatchDeclaredFlagsAndAddress() (gas: 14742)\n[PASS] test_poolManagerIsTheOnlyPathIntoSwapCallbacks() (gas: 56016)\n[PASS] test_poolWithoutPanicIsRefused() (gas: 5376657)\n[PASS] test_runtimeCodeHasNoEscapeHatchAndFitsEip170() (gas: 7261972)\n[PASS] test_secondPoolCannotBeRegistered() (gas: 49173)\n[PASS] test_unlockCallbackCannotBeDrivenByAnyoneElse() (gas: 35684)\nSuite result: ok. 17 passed; 0 failed; 0 skipped; finished in 101.75ms (123.09ms CPU time)\n\nRan 10 tests for test/PanicHook.Oracle.t.sol:PanicHookOracleTest\n[PASS] test_aCrashInThisBlockIsJudgedAgainstTheUntouchedReference() (gas: 705334)\n[PASS] test_afterAnHourDownButFlatThePanicTierNoLongerApplies() (gas: 997666)\n[PASS] test_atMostOneObservationPerBlockTakenBeforeTheFirstSwap() (gas: 815063)\n[PASS] test_blocksSharingATimestampDoNotDuplicateObservations() (gas: 904658)\n[PASS] test_buyAndSellInTheSameBlockCannotMoveTheReference() (gas: 1068382)\n[PASS] test_launchPriceAnchorsTheWindowBeforeTheFirstObservation() (gas: 451182)\n[PASS] test_panicTierStillAppliesBeforeTheHourIsUp() (gas: 715980)\n[PASS] test_referenceIsTheOneHourMeanTick() (gas: 484502)\n[PASS] test_swapsInTheInitializationBlockRecordNothingNew() (gas: 552620)\n[PASS] test_viewMatchesAnIndependentTwapOverManyObservations() (gas: 98224564)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 101.65ms (83.01ms CPU time)\n\nRan 4 tests for test/PanicMonkeys.Properties.t.sol:PanicMonkeysPropertiesTest\n[PASS] invariant_supplyBalancesAndAllowancesMatchIndependentLedger() (runs: 256, calls: 16384, reverts: 0)\n\n╭-------------------+--------------+-------+---------+----------╮\n| Contract          | Selector     | Calls | Reverts | Discards |\n+===============================================================+\n| PanicTokenHandler | approve      | 5471  | 0       | 0        |\n|-------------------+--------------+-------+---------+----------|\n| PanicTokenHandler | transfer     | 5440  | 0       | 0        |\n|-------------------+--------------+-------+---------+----------|\n| PanicTokenHandler | transferFrom | 5473  | 0       | 0        |\n╰-------------------+--------------+-------+---------+----------╯\n\n[PASS] testFuzz_transferFromFailureRestoresFiniteAllowance(uint256) (runs: 1000, μ: 120244, ~: 120157)\n[PASS] test_selfTransferOfFullSupplyAndZeroTransferFrom() (gas: 110214)\n[PASS] test_zeroAddressFailurePreservesBalanceAndAllowance() (gas: 108800)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 2.63s (2.64s CPU time)\n\nRan 2 tests for test/PanicHook.Invariant.t.sol:PanicNativeInvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+---------------+-------+---------+----------╮\n| Contract               | Selector      | Calls | Reverts | Discards |\n+=====================================================================+\n| PanicAccountingHandler | advance       | 2370  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buy           | 2371  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buyback       | 2295  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | claim         | 2389  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | donate        | 2277  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | sell          | 2344  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic | 2338  | 0       | 0        |\n╰------------------------+---------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2486085)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.03s (3.99s CPU time)\n\nRan 2 tests for test/PanicHook.Invariant.t.sol:PanicCurrency0InvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+---------------+-------+---------+----------╮\n| Contract               | Selector      | Calls | Reverts | Discards |\n+=====================================================================+\n| PanicAccountingHandler | advance       | 2370  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buy           | 2371  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buyback       | 2295  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | claim         | 2389  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | donate        | 2277  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | sell          | 2344  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic | 2338  | 0       | 0        |\n╰------------------------+---------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2560824)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.28s (4.25s CPU time)\n\nRan 2 tests for test/PanicHook.Invariant.t.sol:PanicCurrency1InvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+---------------+-------+---------+----------╮\n| Contract               | Selector      | Calls | Reverts | Discards |\n+=====================================================================+\n| PanicAccountingHandler | advance       | 2370  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buy           | 2371  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buyback       | 2295  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | claim         | 2389  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | donate        | 2277  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | sell          | 2344  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic | 2338  | 0       | 0        |\n╰------------------------+---------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2558457)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.38s (4.35s CPU time)\n\nRan 15 test suites in 4.38s (16.07s CPU time): 120 tests passed, 0 failed, 0 skipped (120 total tests)\n","passed":true},{"durationMs":52,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"PanicHook.afterAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"PanicHook.afterInitialize(address,(address,address,uint24,int24,address),uint160,int24)\",\"PanicHook.afterRemoveLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"PanicHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"PanicHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"PanicHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"PanicHook.buybackAndBurn()\",\"PanicHook.buybackAndBurn(uint256)\",\"PanicHook.claimOracleFund()\",\"PanicHook.donateToLiquidityProviders()\",\"PanicHook.unlockCallback(bytes)\",\"PanicMonkeys.approve(address,uint256)\",\"PanicMonkeys.transfer(address,uint256)\",\"PanicMonkeys.transferFrom(address,address,uint256)\"],\"files\":{\"README.md\":320,\"foundry.toml\":33,\"launch.json\":36,\"remappings.txt\":3,\"script/DeployPanic.s.sol\":77,\"src/HookFlags.sol\":43,\"src/HookMiner.sol\":48,\"src/PanicHook.sol\":866,\"src/PanicMonkeys.sol\":68,\"test/Deploy.t.sol\":78,\"test/PanicHook.Buckets.t.sol\":419,\"test/PanicHook.Fees.t.sol\":294,\"test/PanicHook.Flipped.t.sol\":104,\"test/PanicHook.Init.t.sol\":263,\"test/PanicHook.Invariant.t.sol\":143,\"test/PanicHook.Jit.t.sol\":99,\"test/PanicHook.Oracle.t.sol\":222,\"test/PanicHook.PriceMath.t.sol\":96,\"test/PanicHook.Revision.t.sol\":204,\"test/PanicMonkeys.Properties.t.sol\":137,\"test/PanicMonkeys.t.sol\":96,\"test/README.md\":46,\"test/handlers/PanicAccountingHandler.sol\":294,\"test/mocks/MockERC20.sol\":52,\"test/utils/PanicTestBase.sol\":281},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":2583,"exitCode":0,"name":"slither","output":"[high/medium] weak-prng at src/PanicHook.sol:661: PanicHook._pairedToPanic(uint256,uint160,bool) (src/PanicHook.sol#661-678) uses a weak PRNG: \"inexact = carry % den != 0 || mulmod(uint256,uint256,uint256)(r,num,den) != 0 (src/PanicHook.sol#677)\"\n[high/medium] weak-prng at src/PanicHook.sol:507: PanicHook._buybackAndBurn(uint256) (src/PanicHook.sol#507-529) uses a weak PRNG: \"(inexact || scaled % BPS != 0) (src/PanicHook.sol#525)\"\n[high/medium] weak-prng at src/PanicHook.sol:849: PanicHook._meanTick(int56,uint32) (src/PanicHook.sol#849-853) uses a weak PRNG: \"cumulativeDelta < 0 && cumulativeDelta % int56(uint56(duration)) != 0 (src/PanicHook.sol#851)\"\n[high/medium] weak-prng at src/PanicHook.sol:635: PanicHook.drawdownBps(uint160,uint160,bool) (src/PanicHook.sol#635-649) uses a weak PRNG: \"dropped = mulmod(uint256,uint256,uint256)(scaled,num,den) | (t % den) (src/PanicHook.sol#646)\"\n[medium/medium] divide-before-multiply at src/PanicHook.sol:784: PanicHook._reference() (src/PanicHook.sol#784-817) performs a multiplication on the result of a division:\n[medium/high] incorrect-equality at src/PanicHook.sol:784: PanicHook._reference() (src/PanicHook.sol#784-817) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:762: PanicHook._observe() (src/PanicHook.sol#762-779) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:784: PanicHook._reference() (src/PanicHook.sol#784-817) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:821: PanicHook._prevailingTick() (src/PanicHook.sol#821-824) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:762: PanicHook._observe() (src/PanicHook.sol#762-779) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:507: PanicHook._buybackAndBurn(uint256) (src/PanicHook.sol#507-529) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:635: PanicHook.drawdownBps(uint160,uint160,bool) (src/PanicHook.sol#635-649) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:762: PanicHook._observe() (src/PanicHook.sol#762-779) uses a dangerous strict equality:\n[medium/medium] reentrancy-no-eth at src/PanicHook.sol:402: Reentrancy in PanicHook.afterAddLiquidity(address,PoolKey,ModifyLiquidityParams,BalanceDelta,BalanceDelta,bytes) (src/PanicHook.sol#402-415):\n[medium/medium] reentrancy-no-eth at src/PanicHook.sol:507: Reentrancy in PanicHook._buybackAndBurn(uint256) (src/PanicHook.sol#507-529):\n[medium/medium] uninitialized-local at src/PanicHook.sol:353: PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes).feeBps (src/PanicHook.sol#353) is a local variable never initialized\n[medium/medium] uninitialized-local at src/PanicHook.sol:356: PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes).isBuy (src/PanicHook.sol#356) is a local variable never initialized\n[medium/medium] uninitialized-local at src/PanicHook.sol:355: PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes).unspecifiedDelta (src/PanicHook.sol#355) is a local variable never initialized\n[medium/medium] uninitialized-local at src/PanicHook.sol:352: PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes).drawdown (src/PanicHook.sol#352) is a local variable never initialized\n[medium/medium] uninitialized-local at src/PanicHook.sol:354: PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes).feeAmount (src/PanicHook.sol#354) is a local variable never initialized\n[medium/medium] unused-return at src/PanicHook.sol:821: PanicHook._prevailingTick() (src/PanicHook.sol#821-824) ignores return value by (None,tick,None,None) = poolManager.getSlot0(poolId) (src/PanicHook.sol#823)\n[medium/medium] unused-return at src/PanicHook.sol:304: PanicHook.beforeSwap(address,PoolKey,SwapParams,bytes) (src/PanicHook.sol#304-337) ignores return value by (sqrtPriceX96,None,None,None) = poolManager.getSlot0(poolId) (src/PanicHook.sol#314)\n[medium/medium] unused-return at src/PanicHook.sol:719: PanicHook._forfeitSameBlockFees(bytes32,BalanceDelta) (src/PanicHook.sol#719-743) ignores return value by poolManager.donate(poolKey,amount0,amount1,) (src/PanicHook.sol#734)\n[medium/medium] unused-return at src/PanicHook.sol:762: PanicHook._observe() (src/PanicHook.sol#762-779) ignores return value by (None,tick,None,None) = poolManager.getSlot0(poolId) (src/PanicHook.sol#766)\n[medium/medium] unused-return at src/PanicHook.sol:340: PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/PanicHook.sol#340-395) ignores return value by (sqrtPriceAfter,None,None,None) = poolManager.getSlot0(poolId) (src/PanicHook.sol#376)\n[medium/medium] unused-return at src/PanicHook.sol:532: PanicHook.unlockCallback(bytes) (src/PanicHook.sol#532-575) ignores return value by (sqrtPriceX96,None,None,None) = poolManager.getSlot0(poolId) (src/PanicHook.sol#548)\n[medium/medium] unused-return at src/PanicHook.sol:486: PanicHook.donateToLiquidityProviders() (src/PanicHook.sol#486-492) ignores return value by poolManager.unlock(abi.encode(ACTION_DONATE,amount)) (src/PanicHook.sol#490)\n[medium/medium] unused-return at src/PanicHook.sol:599: PanicHook.currentDrawdownBps() (src/PanicHook.sol#599-603) ignores return value by (sqrtPriceX96,None,None,None) = poolManager.getSlot0(poolId) (src/PanicHook.sol#601)\n[medium/medium] unused-return at src/PanicHook.sol:476: PanicHook.claimOracleFund() (src/PanicHook.sol#476-482) ignores return value by poolManager.unlock(abi.encode(ACTION_CLAIM,amount)) (src/PanicHook.sol#480)\n[medium/medium] unused-return at src/PanicHook.sol:745: PanicHook._donate(uint256) (src/PanicHook.sol#745-750) ignores return value by poolManager.donate(poolKey,amount0,amount1,) (src/PanicHook.sol#747)\n[low/medium] reentrancy-benign at src/PanicHook.sol:719: Reentrancy in PanicHook._forfeitSameBlockFees(bytes32,BalanceDelta) (src/PanicHook.sol#719-743):\n[low/medium] reentrancy-benign at src/PanicHook.sol:745: Reentrancy in PanicHook._donate(uint256) (src/PanicHook.sol#745-750):\n[low/medium] reentrancy-events at src/PanicHook.sol:340: Reentrancy in PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/PanicHook.sol#340-395):\n[low/medium] reentrancy-events at src/PanicHook.sol:719: Reentrancy in PanicHook._forfeitSameBlockFees(bytes32,BalanceDelta) (src/PanicHook.sol#719-743):\n[low/medium] reentrancy-events at src/PanicHook.sol:476: Reentrancy in PanicHook.claimOracleFund() (src/PanicHook.sol#476-482):\n[low/medium] reentrancy-events at src/PanicHook.sol:532: Reentrancy in PanicHook.unlockCallback(bytes) (src/PanicHook.sol#532-575):\n[low/medium] reentrancy-events at src/PanicHook.sol:698: Reentrancy in PanicHook._split(uint256) (src/PanicHook.sol#698-714):\n[low/medium] reentrancy-events at src/PanicHook.sol:507: Reentrancy in PanicHook._buybackAndBurn(uint256) (src/PanicHook.sol#507-529):\n[low/medium] reentrancy-events at src/PanicHook.sol:486: Reentrancy in PanicHook.donateToLiquidityProviders() (src/PanicHook.sol#486-492):\n[low/medium] timestamp at src/PanicHook.sol:849: PanicHook._meanTick(int56,uint32) (src/PanicHook.sol#849-853) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:754: PanicHook._observeAndReference() (src/PanicHook.sol#754-759) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:784: PanicHook._reference() (src/PanicHook.sol#784-817) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:762: PanicHook._observe() (src/PanicHook.sol#762-779) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:625: PanicHook.sellFeeBps(uint256) (src/PanicHook.sol#625-630) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:661: PanicHook._pairedToPanic(uint256,uint160,bool) (src/PanicHook.sol#661-678) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:828: PanicHook._findWindowStart(uint32,uint256) (src/PanicHook.sol#828-846) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:507: PanicHook._buybackAndBurn(uint256) (src/PanicHook.sol#507-529) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:620: PanicHook.buyFeeBps(uint256) (src/PanicHook.sol#620-622) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:635: PanicHook.drawdownBps(uint160,uint160,bool) (src/PanicHook.sol#635-649) uses timestamp for comparisons","passed":true},{"durationMs":431,"exitCode":0,"name":"aderyn","output":"[high] unsafe-casting at src/PanicHook.sol:852: Unsafe Casting of integers\n[low] internal-function-used-once at src/HookFlags.sol:35: Internal Function Used Only Once (2 places)\n[low] large-numeric-literal at src/PanicHook.sol:67: Large Numeric Literal (2 places)\n[low] literal-instead-of-constant at src/PanicHook.sol:644: Literal Instead of Constant (2 places)\n[low] missing-inheritance at src/PanicMonkeys.sol:8: Missing Inheritance\n[low] unchecked-return at src/PanicHook.sol:480: Unchecked Return (4 places)","passed":true},{"durationMs":9348,"exitCode":0,"name":"proof d200a2cc9db8","output":"Compiling 78 files with Solc 0.8.26\nSolc 0.8.26 finished in 8.75s\nCompiler run successful!\n\nRan 1 test for test/imd-proof-f9d9de60/Proof_d200a2cc9db8.t.sol:JitRecaptureTest\n[PASS] test_sameTransactionJitLiquidityMustNotRecaptureTheSellersOwnTax() (gas: 1091391)\nLogs:\n  plain seller: hook fee: 208321875861255582992\n  plain seller: LP donation: 62496562758376674897\n  plain seller: net ETH: 833287503445022331968\n  JIT seller:   net ETH: 833287503445022331967\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 19.55ms (651.33µs CPU time)\n\nRan 1 test suite in 20.23ms (19.55ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"2b3222ccdf21e4552087551370c8689293ab1a8009984760be5851db44637f2e","verifiedTreeHash":"c08b4e0f62de09d5ae86c3d2213b63822bfb5dbb","verifierVersion":"0.1.0+a2d9a899"},{"checks":[{"durationMs":78254,"exitCode":0,"name":"build","output":"Compiling 90 files with Solc 0.8.26\nSolc 0.8.26 finished in 78.15s\nCompiler run successful!\n","passed":true},{"durationMs":4528,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 9 tests for test/PanicMonkeys.t.sol:PanicMonkeysTest\n[PASS] test_approveAndTransferFrom() (gas: 216975)\n[PASS] test_infiniteAllowanceIsNotDecremented() (gas: 116621)\n[PASS] test_metadata() (gas: 19860)\n[PASS] test_mintsExactlyOneBillionToDeployer() (gas: 16915)\n[PASS] test_noMintOrAdminEntrypoints() (gas: 144962)\n[PASS] test_runtimeHasNoDelegatecallOrSelfdestruct() (gas: 242678)\n[PASS] test_transferMovesExactAmount() (gas: 77743)\n[PASS] test_transferRevertsOnInsufficientBalance() (gas: 37711)\n[PASS] test_transferToZeroAddressReverts() (gas: 30229)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 962.40µs (1.50ms CPU time)\n\nRan 6 tests for test/PanicHook.Flipped.t.sol:PanicHookPanicAsCurrency1Erc20Test\n[PASS] test_buyWhileDownPays1PercentOfPairedInput() (gas: 615865)\n[PASS] test_buyWhileNotDownIsFree() (gas: 220625)\n[PASS] test_orientationIsDetected() (gas: 17612)\n[PASS] test_outletsWorkWithAnErc20PairedToken() (gas: 3720946)\n[PASS] test_referenceUnmovedByTradesInTheBlock() (gas: 610874)\n[PASS] test_sellTo20PercentDownPays20PercentInThePairedToken() (gas: 453752)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 14.81ms (11.96ms CPU time)\n\nRan 2 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_deployIsRepeatableWithFreshState() (gas: 16938919)\n[PASS] test_deployProducesTokenHookAndPool() (gas: 6929235)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 22.11ms (32.69ms CPU time)\n\nRan 16 tests for test/PanicHook.Init.t.sol:PanicHookInitTest\n[PASS] test_anyStaticLpFeeTierIsAccepted() (gas: 20378032)\n[PASS] test_constructorRejectsAddressWithoutFlags() (gas: 10721)\n[PASS] test_constructorRejectsDifferentOracleFund() (gas: 14346027)\n[PASS] test_constructorRejectsZeroAddresses() (gas: 48464444)\n[PASS] test_constructorStoresImmutables() (gas: 19611)\n[PASS] test_disabledCallbacksRevert() (gas: 94771)\n[PASS] test_dynamicFeePoolIsRefused() (gas: 12225174)\n[PASS] test_enabledCallbacksRefuseCallersOtherThanThePoolManager() (gas: 143198)\n[PASS] test_initializationRegistersPoolAndFirstObservation() (gas: 120376)\n[PASS] test_noAdminSurface() (gas: 196333)\n[PASS] test_permissionsMatchDeclaredFlagsAndAddress() (gas: 14417)\n[PASS] test_poolManagerIsTheOnlyPathIntoSwapCallbacks() (gas: 55950)\n[PASS] test_poolWithoutPanicIsRefused() (gas: 13621534)\n[PASS] test_runtimeCodeHasNoEscapeHatchAndFitsEip170() (gas: 6295412)\n[PASS] test_secondPoolCannotBeRegistered() (gas: 49187)\n[PASS] test_unlockCallbackCannotBeDrivenByAnyoneElse() (gas: 35640)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 55.18ms (217.44ms CPU time)\n\nRan 6 tests for test/PanicHook.Flipped.t.sol:PanicHookPanicAsCurrency0Test\n[PASS] test_buyWhileDownPays1PercentOfPairedInput() (gas: 620194)\n[PASS] test_buyWhileNotDownIsFree() (gas: 215134)\n[PASS] test_orientationIsDetected() (gas: 17612)\n[PASS] test_outletsWorkWithAnErc20PairedToken() (gas: 3711411)\n[PASS] test_referenceUnmovedByTradesInTheBlock() (gas: 604823)\n[PASS] test_sellTo20PercentDownPays20PercentInThePairedToken() (gas: 458277)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 60.01ms (9.19ms CPU time)\n\nRan 6 tests for test/PanicHook.PriceMath.t.sol:PanicHookPriceMathTest\n[PASS] testFuzz_referenceQuoteMatchesSingleDivision(uint64,uint128) (runs: 256, μ: 13154, ~: 13102)\n[PASS] test_dustBuybackUsesExactReferenceQuoteAndRevertsAtomically() (gas: 862033)\n[PASS] test_referenceQuoteAtExtremeSqrtPrices() (gas: 22408)\n[PASS] test_referenceQuoteHandlesZeroAndMaximumAtParity() (gas: 23525)\n[PASS] test_referenceQuoteRetainsRemainderInBothOrientations() (gas: 12416)\n[PASS] test_referenceQuoteRevertsIfResultOverflows() (gas: 18958)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 59.99ms (36.99ms CPU time)\n\nRan 20 tests for test/PanicHook.Fees.t.sol:PanicHookFeesTest\n[PASS] testFuzz_drawdownIsZeroAtOrAboveReferenceAndNeverAbove100Percent(uint160,uint160) (runs: 256, μ: 13446, ~: 13375)\n[PASS] testFuzz_hookFeeNeverExceeds30Percent(uint256) (runs: 256, μ: 22722, ~: 22788)\n[PASS] test_buyIsJudgedOnThePriceBeforeTheBuy() (gas: 1046254)\n[PASS] test_buyTierSwitchesExactlyAt5Percent() (gas: 18473)\n[PASS] test_buyWhileDownPays1PercentOfInput() (gas: 581314)\n[PASS] test_buyWhileNotDownPaysNoHookFee() (gas: 212779)\n[PASS] test_drawdownIsExactAtThresholds() (gas: 193253)\n[PASS] test_exactOutputBuyPaysFeeOnThePairedInput() (gas: 584130)\n[PASS] test_exactOutputBuyWhileNotDownPaysNothing() (gas: 215261)\n[PASS] test_exactOutputSellIsRejected() (gas: 91290)\n[PASS] test_feeEventReportsDrawdownTierAndAmount() (gas: 602628)\n[PASS] test_feesAreTakenOnlyInThePairedCurrency() (gas: 777142)\n[PASS] test_hookFeeCappedAt30PercentEvenInACrash() (gas: 406984)\n[PASS] test_noAddressIsExempt() (gas: 1338601)\n[PASS] test_sellEnding30PercentOrMoreDownPays30PercentAndNoMore() (gas: 406884)\n[PASS] test_sellEndingBetween5And15PercentDownPays10Percent() (gas: 406585)\n[PASS] test_sellMovingPriceFromNotDownTo20PercentDownPays20Percent() (gas: 433760)\n[PASS] test_sellTiersSwitchAtExactBoundaryPrices() (gas: 1795731)\n[PASS] test_sellTiersSwitchExactlyAt5_15_30Percent() (gas: 32225)\n[PASS] test_sellWhileNotDownPays2PercentOfOutput() (gas: 371634)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 59.95ms (19.51ms CPU time)\n\nRan 10 tests for test/PanicHook.Revision.t.sol:PanicHookRevisionTest\n[PASS] testFuzz_fullDipBuyFeeIsAtMostOnePercentOfPoolInput(uint96) (runs: 256, μ: 602346, ~: 606237)\n[PASS] testFuzz_tinyBuybacksAreAtomicAndBurnAllOutput(uint16) (runs: 256, μ: 551442, ~: 554547)\n[PASS] test_dustBuybackRevertsAndPreservesAllFunds() (gas: 539917)\n[PASS] test_exactOutputLimitedDipBuyChargesOnlyRealisedInput() (gas: 615169)\n[PASS] test_jitPositionCannotCaptureAnEarlierSwapsDonation() (gas: 1055153)\n[PASS] test_partialBuyWithoutHookFeeStillWorks() (gas: 205739)\n[PASS] test_partialBuybackReallocatesFeeOnlyOnRealisedInput() (gas: 1211102)\n[PASS] test_partialDipBuyRevertsWithoutChargingOrMovingThePool() (gas: 591368)\n[PASS] test_perCallCapAllowsMultipleBuybacksInOneBlock() (gas: 838321)\n[PASS] test_referenceUsesDocumentedWholeTickRounding() (gas: 445845)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 60.02ms (106.37ms CPU time)\n\nRan 10 tests for test/PanicHook.Oracle.t.sol:PanicHookOracleTest\n[PASS] test_aCrashInThisBlockIsJudgedAgainstTheUntouchedReference() (gas: 704818)\n[PASS] test_afterAnHourDownButFlatThePanicTierNoLongerApplies() (gas: 996933)\n[PASS] test_atMostOneObservationPerBlockTakenBeforeTheFirstSwap() (gas: 814465)\n[PASS] test_blocksSharingATimestampDoNotDuplicateObservations() (gas: 904016)\n[PASS] test_buyAndSellInTheSameBlockCannotMoveTheReference() (gas: 1067600)\n[PASS] test_launchPriceAnchorsTheWindowBeforeTheFirstObservation() (gas: 450891)\n[PASS] test_panicTierStillAppliesBeforeTheHourIsUp() (gas: 715475)\n[PASS] test_referenceIsTheOneHourMeanTick() (gas: 484189)\n[PASS] test_swapsInTheInitializationBlockRecordNothingNew() (gas: 552192)\n[PASS] test_viewMatchesAnIndependentTwapOverManyObservations() (gas: 98150459)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 94.53ms (91.44ms CPU time)\n\nRan 18 tests for test/PanicHook.Buckets.t.sol:PanicHookBucketsTest\n[PASS] testFuzz_splitOfAnyFeeSumsExactly(uint128) (runs: 1000, μ: 349986, ~: 367269)\n[PASS] test_allThreeOutletsDrainEverythingLeavingNoDust() (gas: 3956209)\n[PASS] test_buybackAndBurnSendsEveryTokenBoughtToTheDeadAddress() (gas: 3638146)\n[PASS] test_buybackCannotMoveTheReferenceAndPaysTheDipFee() (gas: 707722)\n[PASS] test_buybackRevertsWhenPriceIsMoreThan2PercentAboveReference() (gas: 790878)\n[PASS] test_buybackRevertsWhenThereIsNothingToSpend() (gas: 539597)\n[PASS] test_buybackRevertsWithTheSpecificErrorWhenTooExpensive() (gas: 691404)\n[PASS] test_buybackSpendsAtMostTheCapPerCall() (gas: 895696)\n[PASS] test_buybackSucceedsAtAFlatPriceWithinTheLpFeeTolerance() (gas: 553033)\n[PASS] test_claimOracleFundIsPermissionlessAndPaysOnlyTheOracleAddress() (gas: 534327)\n[PASS] test_claimToARecipientThatRejectsEthFailsWithoutBlockingSwaps() (gas: 13325902)\n[PASS] test_donateRevertsWhileNoLiquidityIsInRangeAndKeepsTheBucket() (gas: 1231995)\n[PASS] test_donationReachesTheLiquidityProviderOnWithdrawal() (gas: 501681)\n[PASS] test_everyFeeIsSplitExactlyWithNoDust() (gas: 885870)\n[PASS] test_feeBearingBuyWorksOnAFreshManagerWhosePoolHoldsTokensOnly() (gas: 10007566)\n[PASS] test_feeSplitSumsToExactly100Percent() (gas: 26576)\n[PASS] test_smallBucketIsSpentInOneCall() (gas: 510336)\n[PASS] test_swapDonatesImmediatelyToInRangeLiquidityProviders() (gas: 449291)\nSuite result: ok. 18 passed; 0 failed; 0 skipped; finished in 94.63ms (104.39ms CPU time)\n\nRan 4 tests for test/PanicMonkeys.Properties.t.sol:PanicMonkeysPropertiesTest\n[PASS] invariant_supplyBalancesAndAllowancesMatchIndependentLedger() (runs: 256, calls: 16384, reverts: 0)\n\n╭-------------------+--------------+-------+---------+----------╮\n| Contract          | Selector     | Calls | Reverts | Discards |\n+===============================================================+\n| PanicTokenHandler | approve      | 5474  | 0       | 0        |\n|-------------------+--------------+-------+---------+----------|\n| PanicTokenHandler | transfer     | 5418  | 0       | 0        |\n|-------------------+--------------+-------+---------+----------|\n| PanicTokenHandler | transferFrom | 5492  | 0       | 0        |\n╰-------------------+--------------+-------+---------+----------╯\n\n[PASS] testFuzz_transferFromFailureRestoresFiniteAllowance(uint256) (runs: 1000, μ: 120237, ~: 120133)\n[PASS] test_selfTransferOfFullSupplyAndZeroTransferFrom() (gas: 110214)\n[PASS] test_zeroAddressFailurePreservesBalanceAndAllowance() (gas: 108800)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 2.70s (2.80s CPU time)\n\nRan 2 tests for test/PanicHook.Invariant.t.sol:PanicNativeInvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+---------------+-------+---------+----------╮\n| Contract               | Selector      | Calls | Reverts | Discards |\n+=====================================================================+\n| PanicAccountingHandler | advance       | 2365  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buy           | 2365  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buyback       | 2371  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | claim         | 2318  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | donate        | 2388  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | sell          | 2275  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic | 2302  | 0       | 0        |\n╰------------------------+---------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2482595)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.30s (4.29s CPU time)\n\nRan 2 tests for test/PanicHook.Invariant.t.sol:PanicCurrency0InvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+---------------+-------+---------+----------╮\n| Contract               | Selector      | Calls | Reverts | Discards |\n+=====================================================================+\n| PanicAccountingHandler | advance       | 2365  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buy           | 2365  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buyback       | 2371  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | claim         | 2318  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | donate        | 2388  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | sell          | 2275  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic | 2302  | 0       | 0        |\n╰------------------------+---------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2557377)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.42s (4.42s CPU time)\n\nRan 2 tests for test/PanicHook.Invariant.t.sol:PanicCurrency1InvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+---------------+-------+---------+----------╮\n| Contract               | Selector      | Calls | Reverts | Discards |\n+=====================================================================+\n| PanicAccountingHandler | advance       | 2365  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buy           | 2365  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buyback       | 2371  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | claim         | 2318  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | donate        | 2388  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | sell          | 2275  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic | 2302  | 0       | 0        |\n╰------------------------+---------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2554967)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.43s (4.42s CPU time)\n\nRan 14 test suites in 4.43s (16.37s CPU time): 113 tests passed, 0 failed, 0 skipped (113 total tests)\n","passed":true},{"durationMs":60,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"PanicHook.afterInitialize(address,(address,address,uint24,int24,address),uint160,int24)\",\"PanicHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"PanicHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"PanicHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"PanicHook.buybackAndBurn()\",\"PanicHook.buybackAndBurn(uint256)\",\"PanicHook.claimOracleFund()\",\"PanicHook.donateToLiquidityProviders()\",\"PanicHook.unlockCallback(bytes)\",\"PanicMonkeys.approve(address,uint256)\",\"PanicMonkeys.transfer(address,uint256)\",\"PanicMonkeys.transferFrom(address,address,uint256)\"],\"files\":{\"README.md\":295,\"foundry.toml\":33,\"launch.json\":32,\"remappings.txt\":3,\"script/DeployPanic.s.sol\":77,\"src/HookFlags.sol\":41,\"src/HookMiner.sol\":48,\"src/PanicHook.sol\":800,\"src/PanicMonkeys.sol\":68,\"test/Deploy.t.sol\":78,\"test/PanicHook.Buckets.t.sol\":417,\"test/PanicHook.Fees.t.sol\":294,\"test/PanicHook.Flipped.t.sol\":104,\"test/PanicHook.Init.t.sol\":260,\"test/PanicHook.Invariant.t.sol\":143,\"test/PanicHook.Oracle.t.sol\":222,\"test/PanicHook.PriceMath.t.sol\":91,\"test/PanicHook.Revision.t.sol\":191,\"test/PanicMonkeys.Properties.t.sol\":137,\"test/PanicMonkeys.t.sol\":96,\"test/README.md\":46,\"test/handlers/PanicAccountingHandler.sol\":294,\"test/mocks/MockERC20.sol\":52,\"test/utils/PanicTestBase.sol\":281},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":2751,"exitCode":0,"name":"slither","output":"[high/medium] weak-prng at src/PanicHook.sol:610: PanicHook.drawdownBps(uint160,uint160,bool) (src/PanicHook.sol#610-624) uses a weak PRNG: \"dropped = mulmod(uint256,uint256,uint256)(scaled,num,den) | (t % den) (src/PanicHook.sol#621)\"\n[high/medium] weak-prng at src/PanicHook.sol:783: PanicHook._meanTick(int56,uint32) (src/PanicHook.sol#783-787) uses a weak PRNG: \"cumulativeDelta < 0 && cumulativeDelta % int56(uint56(duration)) != 0 (src/PanicHook.sol#785)\"\n[medium/medium] divide-before-multiply at src/PanicHook.sol:718: PanicHook._reference() (src/PanicHook.sol#718-751) performs a multiplication on the result of a division:\n[medium/high] incorrect-equality at src/PanicHook.sol:610: PanicHook.drawdownBps(uint160,uint160,bool) (src/PanicHook.sol#610-624) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:696: PanicHook._observe() (src/PanicHook.sol#696-713) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:718: PanicHook._reference() (src/PanicHook.sol#718-751) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:755: PanicHook._prevailingTick() (src/PanicHook.sol#755-758) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:696: PanicHook._observe() (src/PanicHook.sol#696-713) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:718: PanicHook._reference() (src/PanicHook.sol#718-751) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:485: PanicHook._buybackAndBurn(uint256) (src/PanicHook.sol#485-504) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:696: PanicHook._observe() (src/PanicHook.sol#696-713) uses a dangerous strict equality:\n[medium/medium] reentrancy-no-eth at src/PanicHook.sol:485: Reentrancy in PanicHook._buybackAndBurn(uint256) (src/PanicHook.sol#485-504):\n[medium/medium] uninitialized-local at src/PanicHook.sol:343: PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes).feeBps (src/PanicHook.sol#343) is a local variable never initialized\n[medium/medium] uninitialized-local at src/PanicHook.sol:346: PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes).isBuy (src/PanicHook.sol#346) is a local variable never initialized\n[medium/medium] uninitialized-local at src/PanicHook.sol:345: PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes).unspecifiedDelta (src/PanicHook.sol#345) is a local variable never initialized\n[medium/medium] uninitialized-local at src/PanicHook.sol:342: PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes).drawdown (src/PanicHook.sol#342) is a local variable never initialized\n[medium/medium] uninitialized-local at src/PanicHook.sol:344: PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes).feeAmount (src/PanicHook.sol#344) is a local variable never initialized\n[medium/medium] unused-return at src/PanicHook.sol:464: PanicHook.donateToLiquidityProviders() (src/PanicHook.sol#464-470) ignores return value by poolManager.unlock(abi.encode(ACTION_DONATE,amount)) (src/PanicHook.sol#468)\n[medium/medium] unused-return at src/PanicHook.sol:755: PanicHook._prevailingTick() (src/PanicHook.sol#755-758) ignores return value by (None,tick,None,None) = poolManager.getSlot0(poolId) (src/PanicHook.sol#757)\n[medium/medium] unused-return at src/PanicHook.sol:679: PanicHook._donate(uint256) (src/PanicHook.sol#679-684) ignores return value by poolManager.donate(poolKey,amount0,amount1,) (src/PanicHook.sol#681)\n[medium/medium] unused-return at src/PanicHook.sol:330: PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/PanicHook.sol#330-385) ignores return value by (sqrtPriceAfter,None,None,None) = poolManager.getSlot0(poolId) (src/PanicHook.sol#366)\n[medium/medium] unused-return at src/PanicHook.sol:574: PanicHook.currentDrawdownBps() (src/PanicHook.sol#574-578) ignores return value by (sqrtPriceX96,None,None,None) = poolManager.getSlot0(poolId) (src/PanicHook.sol#576)\n[medium/medium] unused-return at src/PanicHook.sol:294: PanicHook.beforeSwap(address,PoolKey,SwapParams,bytes) (src/PanicHook.sol#294-327) ignores return value by (sqrtPriceX96,None,None,None) = poolManager.getSlot0(poolId) (src/PanicHook.sol#304)\n[medium/medium] unused-return at src/PanicHook.sol:507: PanicHook.unlockCallback(bytes) (src/PanicHook.sol#507-550) ignores return value by (sqrtPriceX96,None,None,None) = poolManager.getSlot0(poolId) (src/PanicHook.sol#523)\n[medium/medium] unused-return at src/PanicHook.sol:696: PanicHook._observe() (src/PanicHook.sol#696-713) ignores return value by (None,tick,None,None) = poolManager.getSlot0(poolId) (src/PanicHook.sol#700)\n[medium/medium] unused-return at src/PanicHook.sol:454: PanicHook.claimOracleFund() (src/PanicHook.sol#454-460) ignores return value by poolManager.unlock(abi.encode(ACTION_CLAIM,amount)) (src/PanicHook.sol#458)\n[low/medium] reentrancy-benign at src/PanicHook.sol:679: Reentrancy in PanicHook._donate(uint256) (src/PanicHook.sol#679-684):\n[low/medium] reentrancy-events at src/PanicHook.sol:485: Reentrancy in PanicHook._buybackAndBurn(uint256) (src/PanicHook.sol#485-504):\n[low/medium] reentrancy-events at src/PanicHook.sol:454: Reentrancy in PanicHook.claimOracleFund() (src/PanicHook.sol#454-460):\n[low/medium] reentrancy-events at src/PanicHook.sol:464: Reentrancy in PanicHook.donateToLiquidityProviders() (src/PanicHook.sol#464-470):\n[low/medium] reentrancy-events at src/PanicHook.sol:330: Reentrancy in PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/PanicHook.sol#330-385):\n[low/medium] reentrancy-events at src/PanicHook.sol:507: Reentrancy in PanicHook.unlockCallback(bytes) (src/PanicHook.sol#507-550):\n[low/medium] reentrancy-events at src/PanicHook.sol:661: Reentrancy in PanicHook._split(uint256) (src/PanicHook.sol#661-677):\n[low/medium] timestamp at src/PanicHook.sol:783: PanicHook._meanTick(int56,uint32) (src/PanicHook.sol#783-787) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:688: PanicHook._observeAndReference() (src/PanicHook.sol#688-693) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:718: PanicHook._reference() (src/PanicHook.sol#718-751) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:610: PanicHook.drawdownBps(uint160,uint160,bool) (src/PanicHook.sol#610-624) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:696: PanicHook._observe() (src/PanicHook.sol#696-713) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:762: PanicHook._findWindowStart(uint32,uint256) (src/PanicHook.sol#762-780) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:595: PanicHook.buyFeeBps(uint256) (src/PanicHook.sol#595-597) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:600: PanicHook.sellFeeBps(uint256) (src/PanicHook.sol#600-605) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:485: PanicHook._buybackAndBurn(uint256) (src/PanicHook.sol#485-504) uses timestamp for comparisons","passed":true},{"durationMs":446,"exitCode":0,"name":"aderyn","output":"[high] unsafe-casting at src/PanicHook.sol:786: Unsafe Casting of integers\n[low] internal-function-used-once at src/HookFlags.sol:33: Internal Function Used Only Once (2 places)\n[low] large-numeric-literal at src/PanicHook.sol:61: Large Numeric Literal (2 places)\n[low] literal-instead-of-constant at src/PanicHook.sol:619: Literal Instead of Constant (2 places)\n[low] missing-inheritance at src/PanicMonkeys.sol:8: Missing Inheritance\n[low] unchecked-return at src/PanicHook.sol:458: Unchecked Return (3 places)","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"6a429299b40d41db35b5cbfc176f9fbdf33956b88b49f89de96fbbaa746274be","verifiedTreeHash":"665c58b13d3c593bb3916265782c7ec77a6be323","verifierVersion":"0.1.0+be003835"},{"checks":[{"durationMs":79369,"exitCode":0,"name":"build","output":"Compiling 90 files with Solc 0.8.26\nSolc 0.8.26 finished in 79.27s\nCompiler run successful!\n","passed":true},{"durationMs":5044,"exitCode":1,"name":"test","output":"No files changed, compilation skipped\n\nRan 6 tests for test/PanicHook.Flipped.t.sol:PanicHookPanicAsCurrency1Erc20Test\n[PASS] test_buyWhileDownPays1PercentOfPairedInput() (gas: 607908)\n[PASS] test_buyWhileNotDownIsFree() (gas: 226903)\n[PASS] test_orientationIsDetected() (gas: 17700)\n[PASS] test_outletsWorkWithAnErc20PairedToken() (gas: 846227)\n[PASS] test_referenceUnmovedByTradesInTheBlock() (gas: 638512)\n[PASS] test_sellTo20PercentDownPays20PercentInThePairedToken() (gas: 440967)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 9.67ms (2.66ms CPU time)\n\nRan 9 tests for test/PanicMonkeys.t.sol:PanicMonkeysTest\n[PASS] test_approveAndTransferFrom() (gas: 216975)\n[PASS] test_infiniteAllowanceIsNotDecremented() (gas: 116621)\n[PASS] test_metadata() (gas: 19860)\n[PASS] test_mintsExactlyOneBillionToDeployer() (gas: 16915)\n[PASS] test_noMintOrAdminEntrypoints() (gas: 144962)\n[PASS] test_runtimeHasNoDelegatecallOrSelfdestruct() (gas: 242678)\n[PASS] test_transferMovesExactAmount() (gas: 77743)\n[PASS] test_transferRevertsOnInsufficientBalance() (gas: 37711)\n[PASS] test_transferToZeroAddressReverts() (gas: 30229)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 11.20ms (1.63ms CPU time)\n\nRan 6 tests for test/PanicHook.Flipped.t.sol:PanicHookPanicAsCurrency0Test\n[PASS] test_buyWhileDownPays1PercentOfPairedInput() (gas: 612261)\n[PASS] test_buyWhileNotDownIsFree() (gas: 221412)\n[PASS] test_orientationIsDetected() (gas: 17700)\n[PASS] test_outletsWorkWithAnErc20PairedToken() (gas: 849137)\n[PASS] test_referenceUnmovedByTradesInTheBlock() (gas: 632461)\n[PASS] test_sellTo20PercentDownPays20PercentInThePairedToken() (gas: 445504)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 13.54ms (2.92ms CPU time)\n\nRan 6 tests for test/PanicHook.PriceMath.t.sol:PanicHookPriceMathTest\n[PASS] testFuzz_referenceQuoteMatchesSingleDivision(uint64,uint128) (runs: 256, μ: 13342, ~: 13292)\n[PASS] test_dustBuybackUsesExactReferenceQuoteAndRevertsAtomically() (gas: 899393)\n[PASS] test_referenceQuoteAtExtremeSqrtPrices() (gas: 22788)\n[PASS] test_referenceQuoteHandlesZeroAndMaximumAtParity() (gas: 23905)\n[PASS] test_referenceQuoteRetainsRemainderInBothOrientations() (gas: 12606)\n[PASS] test_referenceQuoteRevertsIfResultOverflows() (gas: 19148)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 21.28ms (4.59ms CPU time)\n\nRan 2 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_deployIsRepeatableWithFreshState() (gas: 25329046)\n[PASS] test_deployProducesTokenHookAndPool() (gas: 6973839)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 33.44ms (38.45ms CPU time)\n\nRan 22 tests for test/PanicHook.Buckets.t.sol:PanicHookBucketsTest\n[FAIL: assertion failed: 166 != 83; counterexample: calldata=0xc10bd02400000000000000000000000000000000000000000000000000000000000036f1 args=[14065 [1.406e4]]] testFuzz_splitOfAnyFeeSumsExactly(uint128) (runs: 0, μ: 0, ~: 0)\n[PASS] test_allThreeOutletsDrainEverythingLeavingNoDust() (gas: 1146591)\n[FAIL: BuybackBelowReference(154616534761539587220 [1.546e20], 155722698291008655860 [1.557e20])] test_buybackAndBurnSendsEveryTokenBoughtToTheDeadAddress() (gas: 1005840)\n[PASS] test_buybackCannotMoveTheReferenceAndPaysTheDipFee() (gas: 753332)\n[PASS] test_buybackRevertsWhenPriceIsMoreThan2PercentAboveReference() (gas: 845819)\n[PASS] test_buybackRevertsWhenThereIsNothingToSpend() (gas: 585555)\n[PASS] test_buybackRevertsWithTheSpecificErrorWhenTooExpensive() (gas: 745588)\n[PASS] test_buybackSpendsAtMostTheCapPerCall() (gas: 906724)\n[PASS] test_buybackSucceedsAtAFlatPriceWithinTheLpFeeTolerance() (gas: 557832)\n[FAIL: assertion failed: 100502512562814070351 != 100502512562814070350] test_capIsTheInputThatMovesTheSqrtPriceHalfAPercentAgainstInRangeLiquidity() (gas: 270707)\n[PASS] test_claimOracleFundIsPermissionlessAndPaysOnlyTheOracleAddress() (gas: 518098)\n[PASS] test_claimToARecipientThatRejectsEthFailsWithoutBlockingSwaps() (gas: 1912788)\n[PASS] test_donateIsPermissionlessOnceTheAccrualBlockHasPassed() (gas: 513008)\n[PASS] test_donateRevertsWhileNoLiquidityIsInRangeAndKeepsTheBucket() (gas: 1560942)\n[PASS] test_donationReachesTheLiquidityProviderOnWithdrawal() (gas: 593328)\n[FAIL: the LP share waits for a later block: 63343685400050472861 != 0] test_everyFeeIsSplitExactlyWithNoDust() (gas: 375270)\n[PASS] test_feeBearingBuyWorksOnAFreshManagerWhosePoolHoldsTokensOnly() (gas: 10562142)\n[PASS] test_feeSplitSumsToExactly100Percent() (gas: 27258)\n[PASS] test_lpShareIsPaidInsideTheSwapWhenNoLiquidityWasAddedInTheBlock() (gas: 493608)\n[PASS] test_lpShareIsWithheldInABlockWithLiquidityAdditionsAndPaidBeforeTheNextSwap() (gas: 888302)\n[PASS] test_oneCrashSellsBurnBucketClearsInOneCallWhenTheCapTracksDepth() (gas: 537882)\n[PASS] test_smallBucketIsSpentInOneCall() (gas: 529823)\nSuite result: FAILED. 18 passed; 4 failed; 0 skipped; finished in 46.39ms (29.79ms CPU time)\n\nRan 10 tests for test/PanicHook.Revision.t.sol:PanicHookRevisionTest\n[PASS] testFuzz_fullDipBuyFeeIsAtMostOnePercentOfPoolInput(uint96) (runs: 256, μ: 596925, ~: 598413)\n[PASS] testFuzz_tinyBuybacksAreAtomicAndBurnAllOutput(uint16) (runs: 256, μ: 555979, ~: 559165)\n[PASS] test_dustBuybackRevertsAndPreservesAllFunds() (gas: 544554)\n[PASS] test_exactOutputLimitedDipBuyChargesOnlyRealisedInput() (gas: 607344)\n[PASS] test_jitPositionInTheAccrualBlockCannotCaptureTheDonation() (gas: 1428705)\n[PASS] test_partialBuyWithoutHookFeeStillWorks() (gas: 210064)\n[FAIL: assertion failed: 18586656 != 14254536] test_partialBuybackReallocatesFeeOnlyOnRealisedInput() (gas: 1231894)\n[PASS] test_partialDipBuyRevertsWithoutChargingOrMovingThePool() (gas: 600444)\n[PASS] test_perCallCapAllowsMultipleBuybacksInOneBlock() (gas: 891054)\n[PASS] test_referenceUsesDocumentedWholeTickRounding() (gas: 471376)\nSuite result: FAILED. 9 passed; 1 failed; 0 skipped; finished in 49.04ms (70.59ms CPU time)\n\nRan 10 tests for test/PanicHook.Oracle.t.sol:PanicHookOracleTest\n[PASS] test_aCrashInThisBlockIsJudgedAgainstTheUntouchedReference() (gas: 745525)\n[PASS] test_afterAnHourDownButFlatThePanicTierNoLongerApplies() (gas: 1040202)\n[PASS] test_atMostOneObservationPerBlockTakenBeforeTheFirstSwap() (gas: 855240)\n[PASS] test_blocksSharingATimestampDoNotDuplicateObservations() (gas: 945231)\n[PASS] test_buyAndSellInTheSameBlockCannotMoveTheReference() (gas: 1111322)\n[PASS] test_launchPriceAnchorsTheWindowBeforeTheFirstObservation() (gas: 476077)\n[PASS] test_panicTierStillAppliesBeforeTheHourIsUp() (gas: 752221)\n[PASS] test_referenceIsTheOneHourMeanTick() (gas: 509485)\n[PASS] test_swapsInTheInitializationBlockRecordNothingNew() (gas: 540508)\n[PASS] test_viewMatchesAnIndependentTwapOverManyObservations() (gas: 101113503)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 95.56ms (86.34ms CPU time)\n\nRan 20 tests for test/PanicHook.Fees.t.sol:PanicHookFeesTest\n[PASS] testFuzz_drawdownIsZeroAtOrAboveReferenceAndNeverAbove100Percent(uint160,uint160) (runs: 256, μ: 13671, ~: 13595)\n[PASS] testFuzz_hookFeeNeverExceeds30Percent(uint256) (runs: 256, μ: 23326, ~: 23382)\n[PASS] test_buyIsJudgedOnThePriceBeforeTheBuy() (gas: 1030025)\n[PASS] test_buyTierSwitchesExactlyAt5Percent() (gas: 18913)\n[PASS] test_buyWhileDownPays1PercentOfInput() (gas: 573358)\n[PASS] test_buyWhileNotDownPaysNoHookFee() (gas: 219057)\n[PASS] test_drawdownIsExactAtThresholds() (gas: 195521)\n[PASS] test_exactOutputBuyPaysFeeOnThePairedInput() (gas: 576174)\n[PASS] test_exactOutputBuyWhileNotDownPaysNothing() (gas: 221539)\n[PASS] test_exactOutputSellIsRejected() (gas: 93555)\n[PASS] test_feeEventReportsDrawdownTierAndAmount() (gas: 568022)\n[PASS] test_feesAreTakenOnlyInThePairedCurrency() (gas: 750460)\n[PASS] test_hookFeeCappedAt30PercentEvenInACrash() (gas: 394089)\n[PASS] test_noAddressIsExempt() (gas: 1282787)\n[PASS] test_sellEnding30PercentOrMoreDownPays30PercentAndNoMore() (gas: 393989)\n[PASS] test_sellEndingBetween5And15PercentDownPays10Percent() (gas: 393690)\n[PASS] test_sellMovingPriceFromNotDownTo20PercentDownPays20Percent() (gas: 420887)\n[PASS] test_sellTiersSwitchAtExactBoundaryPrices() (gas: 1783510)\n[PASS] test_sellTiersSwitchExactlyAt5_15_30Percent() (gas: 32929)\n[PASS] test_sellWhileNotDownPays2PercentOfOutput() (gas: 358607)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 95.54ms (21.11ms CPU time)\n\nRan 17 tests for test/PanicHook.Init.t.sol:PanicHookInitTest\n[PASS] test_afterAddLiquidityOnlyRecordsThisPoolsAdditions() (gas: 125040)\n[PASS] test_anyStaticLpFeeTierIsAccepted() (gas: 5213621)\n[PASS] test_constructorRejectsAddressWithoutFlags() (gas: 10743)\n[PASS] test_constructorRejectsDifferentOracleFund() (gas: 3275107)\n[FAIL: EvmError: OutOfGas] test_constructorRejectsZeroAddresses() (gas: 299978936)\n[PASS] test_constructorStoresImmutables() (gas: 19787)\n[PASS] test_disabledCallbacksRevert() (gas: 79323)\n[PASS] test_dynamicFeePoolIsRefused() (gas: 531803)\n[PASS] test_enabledCallbacksRefuseCallersOtherThanThePoolManager() (gas: 171071)\n[PASS] test_initializationRegistersPoolAndFirstObservation() (gas: 121058)\n[PASS] test_noAdminSurface() (gas: 197411)\n[PASS] test_permissionsMatchDeclaredFlagsAndAddress() (gas: 14799)\n[PASS] test_poolManagerIsTheOnlyPathIntoSwapCallbacks() (gas: 56170)\n[PASS] test_poolWithoutPanicIsRefused() (gas: 1928365)\n[PASS] test_runtimeCodeHasNoEscapeHatchAndFitsEip170() (gas: 7839352)\n[PASS] test_secondPoolCannotBeRegistered() (gas: 49300)\n[PASS] test_unlockCallbackCannotBeDrivenByAnyoneElse() (gas: 35728)\nSuite result: FAILED. 16 passed; 1 failed; 0 skipped; finished in 99.63ms (109.07ms CPU time)\n\nRan 4 tests for test/PanicMonkeys.Properties.t.sol:PanicMonkeysPropertiesTest\n[PASS] invariant_supplyBalancesAndAllowancesMatchIndependentLedger() (runs: 256, calls: 16384, reverts: 0)\n\n╭-------------------+--------------+-------+---------+----------╮\n| Contract          | Selector     | Calls | Reverts | Discards |\n+===============================================================+\n| PanicTokenHandler | approve      | 5421  | 0       | 0        |\n|-------------------+--------------+-------+---------+----------|\n| PanicTokenHandler | transfer     | 5404  | 0       | 0        |\n|-------------------+--------------+-------+---------+----------|\n| PanicTokenHandler | transferFrom | 5559  | 0       | 0        |\n╰-------------------+--------------+-------+---------+----------╯\n\n[PASS] testFuzz_transferFromFailureRestoresFiniteAllowance(uint256) (runs: 1000, μ: 120234, ~: 120133)\n[PASS] test_selfTransferOfFullSupplyAndZeroTransferFrom() (gas: 110214)\n[PASS] test_zeroAddressFailurePreservesBalanceAndAllowance() (gas: 108800)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 3.12s (3.22s CPU time)\n\nRan 2 tests for test/PanicHook.Invariant.t.sol:PanicNativeInvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+---------------+-------+---------+----------╮\n| Contract               | Selector      | Calls | Reverts | Discards |\n+=====================================================================+\n| PanicAccountingHandler | advance       | 2253  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buy           | 2382  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buyback       | 2348  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | claim         | 2412  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | donate        | 2327  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | sell          | 2316  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic | 2346  | 0       | 0        |\n╰------------------------+---------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2568811)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.65s (4.63s CPU time)\n\nRan 2 tests for test/PanicHook.Invariant.t.sol:PanicCurrency1InvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+---------------+-------+---------+----------╮\n| Contract               | Selector      | Calls | Reverts | Discards |\n+=====================================================================+\n| PanicAccountingHandler | advance       | 2253  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buy           | 2382  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buyback       | 2348  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | claim         | 2412  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | donate        | 2327  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | sell          | 2316  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic | 2346  | 0       | 0        |\n╰------------------------+---------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2641178)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.83s (4.82s CPU time)\n\nRan 2 tests for test/PanicHook.Invariant.t.sol:PanicCurrency0InvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+---------------+-------+---------+----------╮\n| Contract               | Selector      | Calls | Reverts | Discards |\n+=====================================================================+\n| PanicAccountingHandler | advance       | 2253  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buy           | 2382  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buyback       | 2348  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | claim         | 2412  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | donate        | 2327  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | sell          | 2316  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic | 2346  | 0       | 0        |\n╰------------------------+---------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2641336)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.94s (4.92s CPU time)\n\nRan 14 test suites in 4.94s (18.02s CPU time): 112 tests passed, 6 failed, 0 skipped (118 total tests)\n\nFailing tests:\nEncountered 4 failing tests in test/PanicHook.Buckets.t.sol:PanicHookBucketsTest\n[FAIL: assertion failed: 166 != 83; counterexample: calldata=0xc10bd02400000000000000000000000000000000000000000000000000000000000036f1 args=[14065 [1.406e4]]] testFuzz_splitOfAnyFeeSumsExactly(uint128) (runs: 0, μ: 0, ~: 0)\n[FAIL: BuybackBelowReference(154616534761539587220 [1.546e20], 155722698291008655860 [1.557e20])] test_buybackAndBurnSendsEveryTokenBoughtToTheDeadAddress() (gas: 1005840)\n[FAIL: assertion failed: 100502512562814070351 != 100502512562814070350] test_capIsTheInputThatMovesTheSqrtPriceHalfAPercentAgainstInRangeLiquidity() (gas: 270707)\n[FAIL: the LP share waits for a later block: 63343685400050472861 != 0] test_everyFeeIsSplitExactlyWithNoDust() (gas: 375270)\n\nEncountered 1 failing test in test/PanicHook.Init.t.sol:PanicHookInitTest\n[FAIL: EvmError: OutOfGas] test_constructorRejectsZeroAddresses() (gas: 299978936)\n\nEncountered 1 failing test in test/PanicHook.Revision.t.sol:PanicHookRevisionTest\n[FAIL: assertion failed: 18586656 != 14254536] test_partialBuybackReallocatesFeeOnlyOnRealisedInput() (gas: 1231894)\n\nEncountered a total of 6 failing tests, 112 tests succeeded\n\nTip: Run `forge test --rerun` to retry only the 6 failed tests\nTip: Run `forge test --debug --match-test <TEST_NAME>` to inspect one failing test in the debugger\n\nFuzz seed: 0x4928e1f6131a231513b41bb97934683b53e8ddea30a3391579bd6af47a467249 (use `--fuzz-seed` to reproduce)\n","passed":false}],"detail":"test failed with exit code 1","evaluation":"checks","profile":"foundry","status":"rejected","submissionHash":"8c449e81e61dae860b722593c79751e362724a82e94daf44cb7197f3c864f520","verifiedTreeHash":"e37341d2d0f1443d573ceb473c3eb5426dd6a36e","verifierVersion":"0.1.0+a2d9a899"},{"checks":[{"durationMs":74018,"exitCode":0,"name":"build","output":"Compiling 90 files with Solc 0.8.26\nSolc 0.8.26 finished in 73.92s\nCompiler run successful!\n","passed":true},{"durationMs":4684,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 9 tests for test/PanicMonkeys.t.sol:PanicMonkeysTest\n[PASS] test_approveAndTransferFrom() (gas: 216975)\n[PASS] test_infiniteAllowanceIsNotDecremented() (gas: 116621)\n[PASS] test_metadata() (gas: 19860)\n[PASS] test_mintsExactlyOneBillionToDeployer() (gas: 16915)\n[PASS] test_noMintOrAdminEntrypoints() (gas: 144962)\n[PASS] test_runtimeHasNoDelegatecallOrSelfdestruct() (gas: 242678)\n[PASS] test_transferMovesExactAmount() (gas: 77743)\n[PASS] test_transferRevertsOnInsufficientBalance() (gas: 37711)\n[PASS] test_transferToZeroAddressReverts() (gas: 30229)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 1.18ms (2.27ms CPU time)\n\nRan 6 tests for test/PanicHook.Flipped.t.sol:PanicHookPanicAsCurrency0Test\n[PASS] test_buyWhileDownPays1PercentOfPairedInput() (gas: 620194)\n[PASS] test_buyWhileNotDownIsFree() (gas: 215134)\n[PASS] test_orientationIsDetected() (gas: 17612)\n[PASS] test_outletsWorkWithAnErc20PairedToken() (gas: 3711411)\n[PASS] test_referenceUnmovedByTradesInTheBlock() (gas: 604823)\n[PASS] test_sellTo20PercentDownPays20PercentInThePairedToken() (gas: 458277)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 7.00ms (4.77ms CPU time)\n\nRan 6 tests for test/PanicHook.Flipped.t.sol:PanicHookPanicAsCurrency1Erc20Test\n[PASS] test_buyWhileDownPays1PercentOfPairedInput() (gas: 615865)\n[PASS] test_buyWhileNotDownIsFree() (gas: 220625)\n[PASS] test_orientationIsDetected() (gas: 17612)\n[PASS] test_outletsWorkWithAnErc20PairedToken() (gas: 3720946)\n[PASS] test_referenceUnmovedByTradesInTheBlock() (gas: 610874)\n[PASS] test_sellTo20PercentDownPays20PercentInThePairedToken() (gas: 453752)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 10.96ms (4.64ms CPU time)\n\nRan 2 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_deployIsRepeatableWithFreshState() (gas: 16938919)\n[PASS] test_deployProducesTokenHookAndPool() (gas: 6929235)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 12.74ms (17.87ms CPU time)\n\nRan 6 tests for test/PanicHook.PriceMath.t.sol:PanicHookPriceMathTest\n[PASS] testFuzz_referenceQuoteMatchesSingleDivision(uint64,uint128) (runs: 256, μ: 13148, ~: 13069)\n[PASS] test_dustBuybackUsesExactReferenceQuoteAndRevertsAtomically() (gas: 862033)\n[PASS] test_referenceQuoteAtExtremeSqrtPrices() (gas: 22408)\n[PASS] test_referenceQuoteHandlesZeroAndMaximumAtParity() (gas: 23525)\n[PASS] test_referenceQuoteRetainsRemainderInBothOrientations() (gas: 12416)\n[PASS] test_referenceQuoteRevertsIfResultOverflows() (gas: 18958)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 43.46ms (6.31ms CPU time)\n\nRan 18 tests for test/PanicHook.Buckets.t.sol:PanicHookBucketsTest\n[PASS] testFuzz_splitOfAnyFeeSumsExactly(uint128) (runs: 1000, μ: 352008, ~: 367269)\n[PASS] test_allThreeOutletsDrainEverythingLeavingNoDust() (gas: 3956209)\n[PASS] test_buybackAndBurnSendsEveryTokenBoughtToTheDeadAddress() (gas: 3638146)\n[PASS] test_buybackCannotMoveTheReferenceAndPaysTheDipFee() (gas: 707722)\n[PASS] test_buybackRevertsWhenPriceIsMoreThan2PercentAboveReference() (gas: 790878)\n[PASS] test_buybackRevertsWhenThereIsNothingToSpend() (gas: 539597)\n[PASS] test_buybackRevertsWithTheSpecificErrorWhenTooExpensive() (gas: 691404)\n[PASS] test_buybackSpendsAtMostTheCapPerCall() (gas: 895696)\n[PASS] test_buybackSucceedsAtAFlatPriceWithinTheLpFeeTolerance() (gas: 553033)\n[PASS] test_claimOracleFundIsPermissionlessAndPaysOnlyTheOracleAddress() (gas: 534327)\n[PASS] test_claimToARecipientThatRejectsEthFailsWithoutBlockingSwaps() (gas: 13325902)\n[PASS] test_donateRevertsWhileNoLiquidityIsInRangeAndKeepsTheBucket() (gas: 1231995)\n[PASS] test_donationReachesTheLiquidityProviderOnWithdrawal() (gas: 501681)\n[PASS] test_everyFeeIsSplitExactlyWithNoDust() (gas: 885870)\n[PASS] test_feeBearingBuyWorksOnAFreshManagerWhosePoolHoldsTokensOnly() (gas: 10007566)\n[PASS] test_feeSplitSumsToExactly100Percent() (gas: 26576)\n[PASS] test_smallBucketIsSpentInOneCall() (gas: 510336)\n[PASS] test_swapDonatesImmediatelyToInRangeLiquidityProviders() (gas: 449291)\nSuite result: ok. 18 passed; 0 failed; 0 skipped; finished in 55.66ms (112.49ms CPU time)\n\nRan 10 tests for test/PanicHook.Revision.t.sol:PanicHookRevisionTest\n[PASS] testFuzz_fullDipBuyFeeIsAtMostOnePercentOfPoolInput(uint96) (runs: 256, μ: 604081, ~: 606237)\n[PASS] testFuzz_tinyBuybacksAreAtomicAndBurnAllOutput(uint16) (runs: 256, μ: 551438, ~: 554547)\n[PASS] test_dustBuybackRevertsAndPreservesAllFunds() (gas: 539917)\n[PASS] test_exactOutputLimitedDipBuyChargesOnlyRealisedInput() (gas: 615169)\n[PASS] test_jitPositionCannotCaptureAnEarlierSwapsDonation() (gas: 1055153)\n[PASS] test_partialBuyWithoutHookFeeStillWorks() (gas: 205739)\n[PASS] test_partialBuybackReallocatesFeeOnlyOnRealisedInput() (gas: 1211102)\n[PASS] test_partialDipBuyRevertsWithoutChargingOrMovingThePool() (gas: 591368)\n[PASS] test_perCallCapAllowsMultipleBuybacksInOneBlock() (gas: 838321)\n[PASS] test_referenceUsesDocumentedWholeTickRounding() (gas: 445845)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 68.71ms (105.49ms CPU time)\n\nRan 20 tests for test/PanicHook.Fees.t.sol:PanicHookFeesTest\n[PASS] testFuzz_drawdownIsZeroAtOrAboveReferenceAndNeverAbove100Percent(uint160,uint160) (runs: 256, μ: 13442, ~: 13452)\n[PASS] testFuzz_hookFeeNeverExceeds30Percent(uint256) (runs: 256, μ: 22721, ~: 22788)\n[PASS] test_buyIsJudgedOnThePriceBeforeTheBuy() (gas: 1046254)\n[PASS] test_buyTierSwitchesExactlyAt5Percent() (gas: 18473)\n[PASS] test_buyWhileDownPays1PercentOfInput() (gas: 581314)\n[PASS] test_buyWhileNotDownPaysNoHookFee() (gas: 212779)\n[PASS] test_drawdownIsExactAtThresholds() (gas: 193253)\n[PASS] test_exactOutputBuyPaysFeeOnThePairedInput() (gas: 584130)\n[PASS] test_exactOutputBuyWhileNotDownPaysNothing() (gas: 215261)\n[PASS] test_exactOutputSellIsRejected() (gas: 91290)\n[PASS] test_feeEventReportsDrawdownTierAndAmount() (gas: 602628)\n[PASS] test_feesAreTakenOnlyInThePairedCurrency() (gas: 777142)\n[PASS] test_hookFeeCappedAt30PercentEvenInACrash() (gas: 406984)\n[PASS] test_noAddressIsExempt() (gas: 1338601)\n[PASS] test_sellEnding30PercentOrMoreDownPays30PercentAndNoMore() (gas: 406884)\n[PASS] test_sellEndingBetween5And15PercentDownPays10Percent() (gas: 406585)\n[PASS] test_sellMovingPriceFromNotDownTo20PercentDownPays20Percent() (gas: 433760)\n[PASS] test_sellTiersSwitchAtExactBoundaryPrices() (gas: 1795731)\n[PASS] test_sellTiersSwitchExactlyAt5_15_30Percent() (gas: 32225)\n[PASS] test_sellWhileNotDownPays2PercentOfOutput() (gas: 371634)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 68.74ms (73.73ms CPU time)\n\nRan 16 tests for test/PanicHook.Init.t.sol:PanicHookInitTest\n[PASS] test_anyStaticLpFeeTierIsAccepted() (gas: 20378032)\n[PASS] test_constructorRejectsAddressWithoutFlags() (gas: 10721)\n[PASS] test_constructorRejectsDifferentOracleFund() (gas: 14346027)\n[PASS] test_constructorRejectsZeroAddresses() (gas: 48464444)\n[PASS] test_constructorStoresImmutables() (gas: 19611)\n[PASS] test_disabledCallbacksRevert() (gas: 94771)\n[PASS] test_dynamicFeePoolIsRefused() (gas: 12225174)\n[PASS] test_enabledCallbacksRefuseCallersOtherThanThePoolManager() (gas: 143198)\n[PASS] test_initializationRegistersPoolAndFirstObservation() (gas: 120376)\n[PASS] test_noAdminSurface() (gas: 196333)\n[PASS] test_permissionsMatchDeclaredFlagsAndAddress() (gas: 14417)\n[PASS] test_poolManagerIsTheOnlyPathIntoSwapCallbacks() (gas: 55950)\n[PASS] test_poolWithoutPanicIsRefused() (gas: 13621534)\n[PASS] test_runtimeCodeHasNoEscapeHatchAndFitsEip170() (gas: 6295412)\n[PASS] test_secondPoolCannotBeRegistered() (gas: 49187)\n[PASS] test_unlockCallbackCannotBeDrivenByAnyoneElse() (gas: 35640)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 77.10ms (186.26ms CPU time)\n\nRan 10 tests for test/PanicHook.Oracle.t.sol:PanicHookOracleTest\n[PASS] test_aCrashInThisBlockIsJudgedAgainstTheUntouchedReference() (gas: 704818)\n[PASS] test_afterAnHourDownButFlatThePanicTierNoLongerApplies() (gas: 996933)\n[PASS] test_atMostOneObservationPerBlockTakenBeforeTheFirstSwap() (gas: 814465)\n[PASS] test_blocksSharingATimestampDoNotDuplicateObservations() (gas: 904016)\n[PASS] test_buyAndSellInTheSameBlockCannotMoveTheReference() (gas: 1067600)\n[PASS] test_launchPriceAnchorsTheWindowBeforeTheFirstObservation() (gas: 450891)\n[PASS] test_panicTierStillAppliesBeforeTheHourIsUp() (gas: 715475)\n[PASS] test_referenceIsTheOneHourMeanTick() (gas: 484189)\n[PASS] test_swapsInTheInitializationBlockRecordNothingNew() (gas: 552192)\n[PASS] test_viewMatchesAnIndependentTwapOverManyObservations() (gas: 98150459)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 87.15ms (86.98ms CPU time)\n\nRan 4 tests for test/PanicMonkeys.Properties.t.sol:PanicMonkeysPropertiesTest\n[PASS] invariant_supplyBalancesAndAllowancesMatchIndependentLedger() (runs: 256, calls: 16384, reverts: 0)\n\n╭-------------------+--------------+-------+---------+----------╮\n| Contract          | Selector     | Calls | Reverts | Discards |\n+===============================================================+\n| PanicTokenHandler | approve      | 5446  | 0       | 0        |\n|-------------------+--------------+-------+---------+----------|\n| PanicTokenHandler | transfer     | 5422  | 0       | 0        |\n|-------------------+--------------+-------+---------+----------|\n| PanicTokenHandler | transferFrom | 5516  | 0       | 0        |\n╰-------------------+--------------+-------+---------+----------╯\n\n[PASS] testFuzz_transferFromFailureRestoresFiniteAllowance(uint256) (runs: 1000, μ: 120240, ~: 120133)\n[PASS] test_selfTransferOfFullSupplyAndZeroTransferFrom() (gas: 110214)\n[PASS] test_zeroAddressFailurePreservesBalanceAndAllowance() (gas: 108800)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 2.77s (2.81s CPU time)\n\nRan 2 tests for test/PanicHook.Invariant.t.sol:PanicNativeInvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+---------------+-------+---------+----------╮\n| Contract               | Selector      | Calls | Reverts | Discards |\n+=====================================================================+\n| PanicAccountingHandler | advance       | 2420  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buy           | 2323  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buyback       | 2359  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | claim         | 2278  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | donate        | 2401  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | sell          | 2301  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic | 2302  | 0       | 0        |\n╰------------------------+---------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2482595)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.24s (4.24s CPU time)\n\nRan 2 tests for test/PanicHook.Invariant.t.sol:PanicCurrency0InvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+---------------+-------+---------+----------╮\n| Contract               | Selector      | Calls | Reverts | Discards |\n+=====================================================================+\n| PanicAccountingHandler | advance       | 2420  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buy           | 2323  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buyback       | 2359  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | claim         | 2278  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | donate        | 2401  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | sell          | 2301  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic | 2302  | 0       | 0        |\n╰------------------------+---------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2557377)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.36s (4.35s CPU time)\n\nRan 2 tests for test/PanicHook.Invariant.t.sol:PanicCurrency1InvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+---------------+-------+---------+----------╮\n| Contract               | Selector      | Calls | Reverts | Discards |\n+=====================================================================+\n| PanicAccountingHandler | advance       | 2420  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buy           | 2323  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buyback       | 2359  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | claim         | 2278  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | donate        | 2401  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | sell          | 2301  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic | 2302  | 0       | 0        |\n╰------------------------+---------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2554967)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.57s (4.56s CPU time)\n\nRan 14 test suites in 4.57s (16.37s CPU time): 113 tests passed, 0 failed, 0 skipped (113 total tests)\n","passed":true},{"durationMs":49,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"PanicHook.afterInitialize(address,(address,address,uint24,int24,address),uint160,int24)\",\"PanicHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"PanicHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"PanicHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"PanicHook.buybackAndBurn()\",\"PanicHook.buybackAndBurn(uint256)\",\"PanicHook.claimOracleFund()\",\"PanicHook.donateToLiquidityProviders()\",\"PanicHook.unlockCallback(bytes)\",\"PanicMonkeys.approve(address,uint256)\",\"PanicMonkeys.transfer(address,uint256)\",\"PanicMonkeys.transferFrom(address,address,uint256)\"],\"files\":{\"README.md\":295,\"foundry.toml\":33,\"launch.json\":32,\"remappings.txt\":3,\"script/DeployPanic.s.sol\":77,\"src/HookFlags.sol\":41,\"src/HookMiner.sol\":48,\"src/PanicHook.sol\":800,\"src/PanicMonkeys.sol\":68,\"test/Deploy.t.sol\":78,\"test/PanicHook.Buckets.t.sol\":417,\"test/PanicHook.Fees.t.sol\":294,\"test/PanicHook.Flipped.t.sol\":104,\"test/PanicHook.Init.t.sol\":260,\"test/PanicHook.Invariant.t.sol\":143,\"test/PanicHook.Oracle.t.sol\":222,\"test/PanicHook.PriceMath.t.sol\":91,\"test/PanicHook.Revision.t.sol\":191,\"test/PanicMonkeys.Properties.t.sol\":137,\"test/PanicMonkeys.t.sol\":96,\"test/README.md\":46,\"test/handlers/PanicAccountingHandler.sol\":294,\"test/mocks/MockERC20.sol\":52,\"test/utils/PanicTestBase.sol\":281},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"950e0dcbde34f94dab6476b62b01c49519a9ccc198480c9c12bca909b95a0caa","verifiedTreeHash":"230fe9d2fe4beb217c1e0ccec2d3e2bea114ecdb","verifierVersion":"0.1.0+be003835"},{"checks":[{"durationMs":102836,"exitCode":0,"name":"build","output":"Compiling 91 files with Solc 0.8.26\nSolc 0.8.26 finished in 102.73s\nCompiler run successful!\n","passed":true},{"durationMs":5127,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 9 tests for test/PanicMonkeys.t.sol:PanicMonkeysTest\n[PASS] test_approveAndTransferFrom() (gas: 216975)\n[PASS] test_infiniteAllowanceIsNotDecremented() (gas: 116621)\n[PASS] test_metadata() (gas: 19860)\n[PASS] test_mintsExactlyOneBillionToDeployer() (gas: 16915)\n[PASS] test_noMintOrAdminEntrypoints() (gas: 144962)\n[PASS] test_runtimeHasNoDelegatecallOrSelfdestruct() (gas: 242678)\n[PASS] test_transferMovesExactAmount() (gas: 77743)\n[PASS] test_transferRevertsOnInsufficientBalance() (gas: 37711)\n[PASS] test_transferToZeroAddressReverts() (gas: 30229)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 1.33ms (2.46ms CPU time)\n\nRan 4 tests for test/PanicHook.Atomicity.t.sol:PanicCurrency0AtomicityTest\n[PASS] test_failedBuybackRestoresFeeGrowthAndOracleThenRecoversAfterAnHour() (gas: 1376503)\n[PASS] test_rejectedExactOutputSellCannotPoisonNextExactInputSell() (gas: 892081)\n[PASS] test_rejectedFirstSwapRollsBackObservationAndNextSwapRecovers() (gas: 1555230)\n[PASS] test_zeroSwapsRollbackInBothDirectionsAndDoNotReserveTheBlock() (gas: 985195)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 6.40ms (2.97ms CPU time)\n\nRan 5 tests for test/PanicHook.Atomicity.t.sol:PanicNativeAtomicityTest\n[PASS] test_failedBuybackRestoresFeeGrowthAndOracleThenRecoversAfterAnHour() (gas: 1318060)\n[PASS] test_recipientCannotReenterClaimOrSpendAnotherBucketDuringPayout() (gas: 1346982)\n[PASS] test_rejectedExactOutputSellCannotPoisonNextExactInputSell() (gas: 837228)\n[PASS] test_rejectedFirstSwapRollsBackObservationAndNextSwapRecovers() (gas: 1489307)\n[PASS] test_zeroSwapsRollbackInBothDirectionsAndDoNotReserveTheBlock() (gas: 921307)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 7.28ms (3.48ms CPU time)\n\nRan 6 tests for test/PanicHook.Flipped.t.sol:PanicHookPanicAsCurrency0Test\n[PASS] test_buyWhileDownPays1PercentOfPairedInput() (gas: 620194)\n[PASS] test_buyWhileNotDownIsFree() (gas: 215134)\n[PASS] test_orientationIsDetected() (gas: 17612)\n[PASS] test_outletsWorkWithAnErc20PairedToken() (gas: 3711411)\n[PASS] test_referenceUnmovedByTradesInTheBlock() (gas: 604823)\n[PASS] test_sellTo20PercentDownPays20PercentInThePairedToken() (gas: 458277)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 8.14ms (4.57ms CPU time)\n\nRan 2 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_deployIsRepeatableWithFreshState() (gas: 16938919)\n[PASS] test_deployProducesTokenHookAndPool() (gas: 6929235)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 8.47ms (14.28ms CPU time)\n\nRan 4 tests for test/PanicHook.Atomicity.t.sol:PanicCurrency1AtomicityTest\n[PASS] test_failedBuybackRestoresFeeGrowthAndOracleThenRecoversAfterAnHour() (gas: 1373229)\n[PASS] test_rejectedExactOutputSellCannotPoisonNextExactInputSell() (gas: 886805)\n[PASS] test_rejectedFirstSwapRollsBackObservationAndNextSwapRecovers() (gas: 1548188)\n[PASS] test_zeroSwapsRollbackInBothDirectionsAndDoNotReserveTheBlock() (gas: 990662)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 10.17ms (4.12ms CPU time)\n\nRan 6 tests for test/PanicHook.PriceMath.t.sol:PanicHookPriceMathTest\n[PASS] testFuzz_referenceQuoteMatchesSingleDivision(uint64,uint128) (runs: 256, μ: 13138, ~: 13069)\n[PASS] test_dustBuybackUsesExactReferenceQuoteAndRevertsAtomically() (gas: 862033)\n[PASS] test_referenceQuoteAtExtremeSqrtPrices() (gas: 22408)\n[PASS] test_referenceQuoteHandlesZeroAndMaximumAtParity() (gas: 23525)\n[PASS] test_referenceQuoteRetainsRemainderInBothOrientations() (gas: 12416)\n[PASS] test_referenceQuoteRevertsIfResultOverflows() (gas: 18958)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 10.41ms (6.75ms CPU time)\n\nRan 6 tests for test/PanicHook.Flipped.t.sol:PanicHookPanicAsCurrency1Erc20Test\n[PASS] test_buyWhileDownPays1PercentOfPairedInput() (gas: 615865)\n[PASS] test_buyWhileNotDownIsFree() (gas: 220625)\n[PASS] test_orientationIsDetected() (gas: 17612)\n[PASS] test_outletsWorkWithAnErc20PairedToken() (gas: 3720946)\n[PASS] test_referenceUnmovedByTradesInTheBlock() (gas: 610874)\n[PASS] test_sellTo20PercentDownPays20PercentInThePairedToken() (gas: 453752)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 52.16ms (5.04ms CPU time)\n\nRan 18 tests for test/PanicHook.Buckets.t.sol:PanicHookBucketsTest\n[PASS] testFuzz_splitOfAnyFeeSumsExactly(uint128) (runs: 1000, μ: 348676, ~: 367269)\n[PASS] test_allThreeOutletsDrainEverythingLeavingNoDust() (gas: 3956209)\n[PASS] test_buybackAndBurnSendsEveryTokenBoughtToTheDeadAddress() (gas: 3638146)\n[PASS] test_buybackCannotMoveTheReferenceAndPaysTheDipFee() (gas: 707722)\n[PASS] test_buybackRevertsWhenPriceIsMoreThan2PercentAboveReference() (gas: 790878)\n[PASS] test_buybackRevertsWhenThereIsNothingToSpend() (gas: 539597)\n[PASS] test_buybackRevertsWithTheSpecificErrorWhenTooExpensive() (gas: 691404)\n[PASS] test_buybackSpendsAtMostTheCapPerCall() (gas: 895696)\n[PASS] test_buybackSucceedsAtAFlatPriceWithinTheLpFeeTolerance() (gas: 553033)\n[PASS] test_claimOracleFundIsPermissionlessAndPaysOnlyTheOracleAddress() (gas: 534327)\n[PASS] test_claimToARecipientThatRejectsEthFailsWithoutBlockingSwaps() (gas: 13325902)\n[PASS] test_donateRevertsWhileNoLiquidityIsInRangeAndKeepsTheBucket() (gas: 1231995)\n[PASS] test_donationReachesTheLiquidityProviderOnWithdrawal() (gas: 501681)\n[PASS] test_everyFeeIsSplitExactlyWithNoDust() (gas: 885870)\n[PASS] test_feeBearingBuyWorksOnAFreshManagerWhosePoolHoldsTokensOnly() (gas: 10007566)\n[PASS] test_feeSplitSumsToExactly100Percent() (gas: 26576)\n[PASS] test_smallBucketIsSpentInOneCall() (gas: 510336)\n[PASS] test_swapDonatesImmediatelyToInRangeLiquidityProviders() (gas: 449291)\nSuite result: ok. 18 passed; 0 failed; 0 skipped; finished in 53.03ms (102.18ms CPU time)\n\nRan 16 tests for test/PanicHook.Init.t.sol:PanicHookInitTest\n[PASS] test_anyStaticLpFeeTierIsAccepted() (gas: 20378032)\n[PASS] test_constructorRejectsAddressWithoutFlags() (gas: 10721)\n[PASS] test_constructorRejectsDifferentOracleFund() (gas: 14346027)\n[PASS] test_constructorRejectsZeroAddresses() (gas: 48464444)\n[PASS] test_constructorStoresImmutables() (gas: 19611)\n[PASS] test_disabledCallbacksRevert() (gas: 94771)\n[PASS] test_dynamicFeePoolIsRefused() (gas: 12225174)\n[PASS] test_enabledCallbacksRefuseCallersOtherThanThePoolManager() (gas: 143198)\n[PASS] test_initializationRegistersPoolAndFirstObservation() (gas: 120376)\n[PASS] test_noAdminSurface() (gas: 196333)\n[PASS] test_permissionsMatchDeclaredFlagsAndAddress() (gas: 14417)\n[PASS] test_poolManagerIsTheOnlyPathIntoSwapCallbacks() (gas: 55950)\n[PASS] test_poolWithoutPanicIsRefused() (gas: 13621534)\n[PASS] test_runtimeCodeHasNoEscapeHatchAndFitsEip170() (gas: 6295412)\n[PASS] test_secondPoolCannotBeRegistered() (gas: 49187)\n[PASS] test_unlockCallbackCannotBeDrivenByAnyoneElse() (gas: 35640)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 55.99ms (177.91ms CPU time)\n\nRan 20 tests for test/PanicHook.Fees.t.sol:PanicHookFeesTest\n[PASS] testFuzz_drawdownIsZeroAtOrAboveReferenceAndNeverAbove100Percent(uint160,uint160) (runs: 256, μ: 13416, ~: 13327)\n[PASS] testFuzz_hookFeeNeverExceeds30Percent(uint256) (runs: 256, μ: 22719, ~: 22788)\n[PASS] test_buyIsJudgedOnThePriceBeforeTheBuy() (gas: 1046254)\n[PASS] test_buyTierSwitchesExactlyAt5Percent() (gas: 18473)\n[PASS] test_buyWhileDownPays1PercentOfInput() (gas: 581314)\n[PASS] test_buyWhileNotDownPaysNoHookFee() (gas: 212779)\n[PASS] test_drawdownIsExactAtThresholds() (gas: 193253)\n[PASS] test_exactOutputBuyPaysFeeOnThePairedInput() (gas: 584130)\n[PASS] test_exactOutputBuyWhileNotDownPaysNothing() (gas: 215261)\n[PASS] test_exactOutputSellIsRejected() (gas: 91290)\n[PASS] test_feeEventReportsDrawdownTierAndAmount() (gas: 602628)\n[PASS] test_feesAreTakenOnlyInThePairedCurrency() (gas: 777142)\n[PASS] test_hookFeeCappedAt30PercentEvenInACrash() (gas: 406984)\n[PASS] test_noAddressIsExempt() (gas: 1338601)\n[PASS] test_sellEnding30PercentOrMoreDownPays30PercentAndNoMore() (gas: 406884)\n[PASS] test_sellEndingBetween5And15PercentDownPays10Percent() (gas: 406585)\n[PASS] test_sellMovingPriceFromNotDownTo20PercentDownPays20Percent() (gas: 433760)\n[PASS] test_sellTiersSwitchAtExactBoundaryPrices() (gas: 1795731)\n[PASS] test_sellTiersSwitchExactlyAt5_15_30Percent() (gas: 32225)\n[PASS] test_sellWhileNotDownPays2PercentOfOutput() (gas: 371634)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 58.10ms (55.01ms CPU time)\n\nRan 10 tests for test/PanicHook.Revision.t.sol:PanicHookRevisionTest\n[PASS] testFuzz_fullDipBuyFeeIsAtMostOnePercentOfPoolInput(uint96) (runs: 256, μ: 604747, ~: 606237)\n[PASS] testFuzz_tinyBuybacksAreAtomicAndBurnAllOutput(uint16) (runs: 256, μ: 552020, ~: 554547)\n[PASS] test_dustBuybackRevertsAndPreservesAllFunds() (gas: 539917)\n[PASS] test_exactOutputLimitedDipBuyChargesOnlyRealisedInput() (gas: 615169)\n[PASS] test_jitPositionCannotCaptureAnEarlierSwapsDonation() (gas: 1055153)\n[PASS] test_partialBuyWithoutHookFeeStillWorks() (gas: 205739)\n[PASS] test_partialBuybackReallocatesFeeOnlyOnRealisedInput() (gas: 1211102)\n[PASS] test_partialDipBuyRevertsWithoutChargingOrMovingThePool() (gas: 591368)\n[PASS] test_perCallCapAllowsMultipleBuybacksInOneBlock() (gas: 838321)\n[PASS] test_referenceUsesDocumentedWholeTickRounding() (gas: 445845)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 58.17ms (96.33ms CPU time)\n\nRan 10 tests for test/PanicHook.Oracle.t.sol:PanicHookOracleTest\n[PASS] test_aCrashInThisBlockIsJudgedAgainstTheUntouchedReference() (gas: 704818)\n[PASS] test_afterAnHourDownButFlatThePanicTierNoLongerApplies() (gas: 996933)\n[PASS] test_atMostOneObservationPerBlockTakenBeforeTheFirstSwap() (gas: 814465)\n[PASS] test_blocksSharingATimestampDoNotDuplicateObservations() (gas: 904016)\n[PASS] test_buyAndSellInTheSameBlockCannotMoveTheReference() (gas: 1067600)\n[PASS] test_launchPriceAnchorsTheWindowBeforeTheFirstObservation() (gas: 450891)\n[PASS] test_panicTierStillAppliesBeforeTheHourIsUp() (gas: 715475)\n[PASS] test_referenceIsTheOneHourMeanTick() (gas: 484189)\n[PASS] test_swapsInTheInitializationBlockRecordNothingNew() (gas: 552192)\n[PASS] test_viewMatchesAnIndependentTwapOverManyObservations() (gas: 98150459)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 85.64ms (82.27ms CPU time)\n\nRan 4 tests for test/PanicMonkeys.Properties.t.sol:PanicMonkeysPropertiesTest\n[PASS] invariant_supplyBalancesAndAllowancesMatchIndependentLedger() (runs: 256, calls: 16384, reverts: 0)\n\n╭-------------------+--------------+-------+---------+----------╮\n| Contract          | Selector     | Calls | Reverts | Discards |\n+===============================================================+\n| PanicTokenHandler | approve      | 5518  | 0       | 0        |\n|-------------------+--------------+-------+---------+----------|\n| PanicTokenHandler | transfer     | 5372  | 0       | 0        |\n|-------------------+--------------+-------+---------+----------|\n| PanicTokenHandler | transferFrom | 5494  | 0       | 0        |\n╰-------------------+--------------+-------+---------+----------╯\n\n[PASS] testFuzz_transferFromFailureRestoresFiniteAllowance(uint256) (runs: 1000, μ: 120228, ~: 120109)\n[PASS] test_selfTransferOfFullSupplyAndZeroTransferFrom() (gas: 110214)\n[PASS] test_zeroAddressFailurePreservesBalanceAndAllowance() (gas: 108800)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 2.83s (2.88s CPU time)\n\nRan 3 tests for test/PanicHook.Invariant.t.sol:PanicNativeInvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+----------------+-------+---------+----------╮\n| Contract               | Selector       | Calls | Reverts | Discards |\n+======================================================================+\n| PanicAccountingHandler | advance        | 2026  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | buy            | 2047  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | buyExactOutput | 2036  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | buyback        | 2119  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | claim          | 1942  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | donate         | 2051  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | sell           | 2058  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic  | 2105  | 0       | 0        |\n╰------------------------+----------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2507002)\n[PASS] test_handlerMixesExactOutputAndExactInputAcrossTheHour() (gas: 2668474)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 4.78s (4.78s CPU time)\n\nRan 3 tests for test/PanicHook.Invariant.t.sol:PanicCurrency1InvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+----------------+-------+---------+----------╮\n| Contract               | Selector       | Calls | Reverts | Discards |\n+======================================================================+\n| PanicAccountingHandler | advance        | 2026  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | buy            | 2047  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | buyExactOutput | 2036  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | buyback        | 2119  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | claim          | 1942  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | donate         | 2051  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | sell           | 2058  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic  | 2105  | 0       | 0        |\n╰------------------------+----------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2579468)\n[PASS] test_handlerMixesExactOutputAndExactInputAcrossTheHour() (gas: 2721645)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 4.98s (4.98s CPU time)\n\nRan 3 tests for test/PanicHook.Invariant.t.sol:PanicCurrency0InvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+----------------+-------+---------+----------╮\n| Contract               | Selector       | Calls | Reverts | Discards |\n+======================================================================+\n| PanicAccountingHandler | advance        | 2026  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | buy            | 2047  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | buyExactOutput | 2036  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | buyback        | 2119  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | claim          | 1942  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | donate         | 2051  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | sell           | 2058  | 0       | 0        |\n|------------------------+----------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic  | 2105  | 0       | 0        |\n╰------------------------+----------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2581845)\n[PASS] test_handlerMixesExactOutputAndExactInputAcrossTheHour() (gas: 2720189)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 5.01s (5.01s CPU time)\n\nRan 17 test suites in 5.01s (18.01s CPU time): 129 tests passed, 0 failed, 0 skipped (129 total tests)\n","passed":true},{"durationMs":67,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"PanicHook.afterInitialize(address,(address,address,uint24,int24,address),uint160,int24)\",\"PanicHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"PanicHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"PanicHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"PanicHook.buybackAndBurn()\",\"PanicHook.buybackAndBurn(uint256)\",\"PanicHook.claimOracleFund()\",\"PanicHook.donateToLiquidityProviders()\",\"PanicHook.unlockCallback(bytes)\",\"PanicMonkeys.approve(address,uint256)\",\"PanicMonkeys.transfer(address,uint256)\",\"PanicMonkeys.transferFrom(address,address,uint256)\"],\"files\":{\"README.md\":295,\"foundry.toml\":33,\"launch.json\":32,\"remappings.txt\":3,\"script/DeployPanic.s.sol\":77,\"src/HookFlags.sol\":41,\"src/HookMiner.sol\":48,\"src/PanicHook.sol\":800,\"src/PanicMonkeys.sol\":68,\"test/Deploy.t.sol\":78,\"test/PanicHook.Atomicity.t.sol\":245,\"test/PanicHook.Buckets.t.sol\":417,\"test/PanicHook.Fees.t.sol\":294,\"test/PanicHook.Flipped.t.sol\":104,\"test/PanicHook.Init.t.sol\":260,\"test/PanicHook.Invariant.t.sol\":159,\"test/PanicHook.Oracle.t.sol\":222,\"test/PanicHook.PriceMath.t.sol\":91,\"test/PanicHook.Revision.t.sol\":191,\"test/PanicMonkeys.Properties.t.sol\":137,\"test/PanicMonkeys.t.sol\":96,\"test/README.md\":50,\"test/handlers/PanicAccountingHandler.sol\":325,\"test/mocks/MockERC20.sol\":52,\"test/utils/PanicTestBase.sol\":281},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"d16b52db738289d69e805855c84f9ea3acaa3e9cdc43d1cd7c99cc41678d01d3","verifiedTreeHash":"3b53048569d95460567cf192e07eeb7e08872e0c","verifierVersion":"0.1.0+be003835"},{"checks":[{"durationMs":93557,"exitCode":0,"name":"build","output":"Compiling 92 files with Solc 0.8.26\nSolc 0.8.26 finished in 93.44s\nCompiler run successful!\n","passed":true},{"durationMs":4878,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 9 tests for test/PanicMonkeys.t.sol:PanicMonkeysTest\n[PASS] test_approveAndTransferFrom() (gas: 216975)\n[PASS] test_infiniteAllowanceIsNotDecremented() (gas: 116621)\n[PASS] test_metadata() (gas: 19860)\n[PASS] test_mintsExactlyOneBillionToDeployer() (gas: 16915)\n[PASS] test_noMintOrAdminEntrypoints() (gas: 144962)\n[PASS] test_runtimeHasNoDelegatecallOrSelfdestruct() (gas: 242678)\n[PASS] test_transferMovesExactAmount() (gas: 77743)\n[PASS] test_transferRevertsOnInsufficientBalance() (gas: 37711)\n[PASS] test_transferToZeroAddressReverts() (gas: 30229)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 11.30ms (2.12ms CPU time)\n\nRan 6 tests for test/PanicHook.PriceMath.t.sol:PanicHookPriceMathTest\n[PASS] testFuzz_referenceQuoteMatchesSingleDivision(uint64,uint128) (runs: 256, μ: 13438, ~: 13361)\n[PASS] test_dustBuybackUsesExactReferenceQuoteAndRevertsAtomically() (gas: 930939)\n[PASS] test_referenceQuoteAtExtremeSqrtPrices() (gas: 22988)\n[PASS] test_referenceQuoteHandlesZeroAndMaximumAtParity() (gas: 24273)\n[PASS] test_referenceQuoteRetainsRemainderInBothOrientations() (gas: 12706)\n[PASS] test_referenceQuoteRevertsIfResultOverflows() (gas: 19048)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 28.69ms (6.72ms CPU time)\n\nRan 2 tests for test/PanicHook.Buyback.t.sol:PanicHookBuybackErc20Test\n[PASS] test_capIsAFractionOfThePairedReserveWhenPairedIsCurrency1() (gas: 655687)\n[PASS] test_topUpWithAnErc20PairedCurrency() (gas: 1103410)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 31.20ms (1.60ms CPU time)\n\nRan 6 tests for test/PanicHook.Flipped.t.sol:PanicHookPanicAsCurrency1Erc20Test\n[PASS] test_buyWhileDownPays1PercentOfPairedInput() (gas: 668235)\n[PASS] test_buyWhileNotDownIsFree() (gas: 270399)\n[PASS] test_orientationIsDetected() (gas: 17656)\n[PASS] test_outletsWorkWithAnErc20PairedToken() (gas: 802144)\n[PASS] test_referenceUnmovedByTradesInTheBlock() (gas: 666098)\n[PASS] test_sellTo20PercentDownPays20PercentInThePairedToken() (gas: 501013)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 33.80ms (2.89ms CPU time)\n\nRan 6 tests for test/PanicHook.Flipped.t.sol:PanicHookPanicAsCurrency0Test\n[PASS] test_buyWhileDownPays1PercentOfPairedInput() (gas: 672564)\n[PASS] test_buyWhileNotDownIsFree() (gas: 264908)\n[PASS] test_orientationIsDetected() (gas: 17656)\n[PASS] test_outletsWorkWithAnErc20PairedToken() (gas: 805776)\n[PASS] test_referenceUnmovedByTradesInTheBlock() (gas: 660047)\n[PASS] test_sellTo20PercentDownPays20PercentInThePairedToken() (gas: 505538)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 34.09ms (3.11ms CPU time)\n\nRan 3 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_deployIsRepeatableWithFreshState() (gas: 24320971)\n[PASS] test_deployProducesTokenHookAndPool() (gas: 6025255)\n[PASS] test_deployWithAnErc20PairedCurrencySortsThePool() (gas: 6722101)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 35.38ms (41.48ms CPU time)\n\nRan 9 tests for test/PanicHook.Buyback.t.sol:PanicHookBuybackTest\n[PASS] testFuzz_enforcedMinimumIsTheCeilingOf98PercentOfTheExactQuote(uint64,uint128) (runs: 256, μ: 24125, ~: 24106)\n[PASS] testFuzz_roundingUpQuoteIsTheCeilingInBothOrientations(uint64,uint128) (runs: 256, μ: 23153, ~: 23160)\n[PASS] test_capFollowsLiquidityAndPrice() (gas: 847997)\n[PASS] test_floorIsComputedFromTheExactReferenceQuoteNotItsFloor() (gas: 963983)\n[PASS] test_oneCappedCallMovesThePriceAboutHalfAPercentAndStillPassesAtAFlatPrice() (gas: 693604)\n[PASS] test_topUpBeforeThePoolExistsIsRefused() (gas: 477623)\n[PASS] test_topUpClearsABurnBucketTooSmallToBuyOnePanicUnit() (gas: 1112775)\n[PASS] test_topUpDoesNotTouchTheReferenceOrOtherBuckets() (gas: 549046)\n[PASS] test_topUpRejectsMismatchedValueAndZero() (gas: 102079)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 52.10ms (31.73ms CPU time)\n\nRan 20 tests for test/PanicHook.Fees.t.sol:PanicHookFeesTest\n[PASS] testFuzz_drawdownIsZeroAtOrAboveReferenceAndNeverAbove100Percent(uint160,uint160) (runs: 256, μ: 13658, ~: 13562)\n[PASS] testFuzz_hookFeeNeverExceeds30Percent(uint256) (runs: 256, μ: 23092, ~: 23162)\n[PASS] test_buyIsJudgedOnThePriceBeforeTheBuy() (gas: 1110197)\n[PASS] test_buyTierSwitchesExactlyAt5Percent() (gas: 18737)\n[PASS] test_buyWhileDownPays1PercentOfInput() (gas: 633684)\n[PASS] test_buyWhileNotDownPaysNoHookFee() (gas: 262553)\n[PASS] test_drawdownIsExactAtThresholds() (gas: 195257)\n[PASS] test_exactOutputBuyPaysFeeOnThePairedInput() (gas: 636500)\n[PASS] test_exactOutputBuyWhileNotDownPaysNothing() (gas: 265035)\n[PASS] test_exactOutputSellIsRejected() (gas: 98954)\n[PASS] test_feeEventReportsDrawdownTierAndAmount() (gas: 654998)\n[PASS] test_feesAreTakenOnlyInThePairedCurrency() (gas: 834764)\n[PASS] test_hookFeeCappedAt30PercentEvenInACrash() (gas: 454179)\n[PASS] test_noAddressIsExempt() (gas: 1401739)\n[PASS] test_sellEnding30PercentOrMoreDownPays30PercentAndNoMore() (gas: 454079)\n[PASS] test_sellEndingBetween5And15PercentDownPays10Percent() (gas: 453780)\n[PASS] test_sellMovingPriceFromNotDownTo20PercentDownPays20Percent() (gas: 480977)\n[PASS] test_sellTiersSwitchAtExactBoundaryPrices() (gas: 1956957)\n[PASS] test_sellTiersSwitchExactlyAt5_15_30Percent() (gas: 32577)\n[PASS] test_sellWhileNotDownPays2PercentOfOutput() (gas: 418719)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 52.11ms (23.68ms CPU time)\n\nRan 20 tests for test/PanicHook.Buckets.t.sol:PanicHookBucketsTest\n[PASS] testFuzz_splitOfAnyFeeSumsExactly(uint128) (runs: 1000, μ: 398120, ~: 414458)\n[PASS] test_allThreeOutletsDrainEverythingLeavingNoDust() (gas: 1158809)\n[PASS] test_buybackAndBurnSendsEveryTokenBoughtToTheDeadAddress() (gas: 1241641)\n[PASS] test_buybackCannotMoveTheReferenceAndPaysTheDipFee() (gas: 780280)\n[PASS] test_buybackCapIsAFractionOfTheInRangePairedReserve() (gas: 809489)\n[PASS] test_buybackRevertsWhenPriceIsMoreThan2PercentAboveReference() (gas: 864809)\n[PASS] test_buybackRevertsWhenThereIsNothingToSpend() (gas: 596621)\n[PASS] test_buybackRevertsWithTheSpecificErrorWhenTooExpensive() (gas: 764797)\n[PASS] test_buybackSpendsAtMostTheCapPerCall() (gas: 993283)\n[PASS] test_buybackSucceedsAtAFlatPriceWithinTheLpFeeTolerance() (gas: 615364)\n[PASS] test_claimOracleFundIsPermissionlessAndPaysOnlyTheOracleAddress() (gas: 581811)\n[PASS] test_claimToARecipientThatRejectsEthFailsWithoutBlockingSwaps() (gas: 1933677)\n[PASS] test_donateRevertsWhileNoLiquidityIsInRangeAndKeepsTheBucket() (gas: 1407070)\n[PASS] test_donationReachesTheLiquidityProviderOnWithdrawal() (gas: 548771)\n[PASS] test_everyFeeIsSplitExactlyWithNoDust() (gas: 944465)\n[PASS] test_feeBearingBuyWorksOnAFreshManagerWhosePoolHoldsTokensOnly() (gas: 14510953)\n[PASS] test_feeSplitSumsToExactly100Percent() (gas: 27082)\n[PASS] test_smallBucketIsSpentInOneCall() (gas: 581354)\n[PASS] test_swapDonatesImmediatelyToLiquidityAlreadyInRange() (gas: 496671)\n[PASS] test_swapEndingInLiquidityNewToTheBlockDefersTheShareToALaterBlock() (gas: 1105591)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 81.12ms (102.13ms CPU time)\n\nRan 10 tests for test/PanicHook.Revision.t.sol:PanicHookRevisionTest\n[PASS] testFuzz_fullDipBuyFeeIsAtMostOnePercentOfPoolInput(uint96) (runs: 256, μ: 654946, ~: 658673)\n[PASS] testFuzz_tinyBuybacksAreAtomicAndBurnAllOutput(uint16) (runs: 256, μ: 613207, ~: 616537)\n[PASS] test_dustBuybackRevertsAndPreservesAllFunds() (gas: 601929)\n[PASS] test_exactOutputLimitedDipBuyChargesOnlyRealisedInput() (gas: 667605)\n[PASS] test_jitPositionCannotCaptureAnEarlierSwapsDonation() (gas: 1102231)\n[PASS] test_partialBuyWithoutHookFeeStillWorks() (gas: 255447)\n[PASS] test_partialBuybackReallocatesFeeOnlyOnRealisedInput() (gas: 1285669)\n[PASS] test_partialDipBuyRevertsWithoutChargingOrMovingThePool() (gas: 643283)\n[PASS] test_perCallCapAllowsMultipleBuybacksInOneBlock() (gas: 983264)\n[PASS] test_referenceUsesDocumentedWholeTickRounding() (gas: 493297)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 81.21ms (111.27ms CPU time)\n\nRan 8 tests for test/PanicHook.Donation.t.sol:PanicHookDonationTest\n[PASS] test_deferredShareGoesToResidentsAtTheNextQualifyingSwapAndAReAddFindsNothing() (gas: 2236621)\n[PASS] test_documentedResidual_liquidityHeldAcrossABlockBoundarySharesTheDonation() (gas: 1393903)\n[PASS] test_donationBucketIsAlwaysBackedByClaims() (gas: 1270063)\n[PASS] test_explicitOutletDefersInTheTaxedSwapsBlockAndPaysLater() (gas: 982365)\n[PASS] test_liquidityAddedBeforeABlocksFirstSwapOnlyDelaysThePayout() (gas: 1732498)\n[PASS] test_priceMovingIntoDenserLiquidityDefersOnlyUntilTheNextSampledBlock() (gas: 1222635)\n[PASS] test_removingLiquidityNeverBlocksThePayout() (gas: 1154089)\n[PASS] test_sameTransactionJitLiquidityRecapturesNothingOfTheSellersTax() (gas: 1404246)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 99.83ms (10.36ms CPU time)\n\nRan 16 tests for test/PanicHook.Init.t.sol:PanicHookInitTest\n[PASS] test_anyStaticLpFeeTierIsAccepted() (gas: 7546760)\n[PASS] test_constructorRejectsAddressWithoutFlags() (gas: 10721)\n[PASS] test_constructorRejectsDifferentOracleFund() (gas: 12344588)\n[PASS] test_constructorRejectsZeroAddresses() (gas: 190515613)\n[PASS] test_constructorStoresImmutables() (gas: 19809)\n[PASS] test_disabledCallbacksRevert() (gas: 95079)\n[PASS] test_dynamicFeePoolIsRefused() (gas: 497971)\n[PASS] test_enabledCallbacksRefuseCallersOtherThanThePoolManager() (gas: 143572)\n[PASS] test_initializationRegistersPoolAndFirstObservation() (gas: 120948)\n[PASS] test_noAdminSurface() (gas: 197565)\n[PASS] test_permissionsMatchDeclaredFlagsAndAddress() (gas: 14549)\n[PASS] test_poolManagerIsTheOnlyPathIntoSwapCallbacks() (gas: 56082)\n[PASS] test_poolWithoutPanicIsRefused() (gas: 1894578)\n[PASS] test_runtimeCodeHasNoEscapeHatchAndFitsEip170() (gas: 8246135)\n[PASS] test_secondPoolCannotBeRegistered() (gas: 49319)\n[PASS] test_unlockCallbackCannotBeDrivenByAnyoneElse() (gas: 35706)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 99.90ms (131.96ms CPU time)\n\nRan 10 tests for test/PanicHook.Oracle.t.sol:PanicHookOracleTest\n[PASS] test_aCrashInThisBlockIsJudgedAgainstTheUntouchedReference() (gas: 757430)\n[PASS] test_afterAnHourDownButFlatThePanicTierNoLongerApplies() (gas: 1058888)\n[PASS] test_atMostOneObservationPerBlockTakenBeforeTheFirstSwap() (gas: 872131)\n[PASS] test_blocksSharingATimestampDoNotDuplicateObservations() (gas: 965210)\n[PASS] test_buyAndSellInTheSameBlockCannotMoveTheReference() (gas: 1133724)\n[PASS] test_launchPriceAnchorsTheWindowBeforeTheFirstObservation() (gas: 498020)\n[PASS] test_panicTierStillAppliesBeforeTheHourIsUp() (gas: 771098)\n[PASS] test_referenceIsTheOneHourMeanTick() (gas: 531384)\n[PASS] test_swapsInTheInitializationBlockRecordNothingNew() (gas: 604540)\n[PASS] test_viewMatchesAnIndependentTwapOverManyObservations() (gas: 101670746)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 119.46ms (91.11ms CPU time)\n\nRan 4 tests for test/PanicMonkeys.Properties.t.sol:PanicMonkeysPropertiesTest\n[PASS] invariant_supplyBalancesAndAllowancesMatchIndependentLedger() (runs: 256, calls: 16384, reverts: 0)\n\n╭-------------------+--------------+-------+---------+----------╮\n| Contract          | Selector     | Calls | Reverts | Discards |\n+===============================================================+\n| PanicTokenHandler | approve      | 5403  | 0       | 0        |\n|-------------------+--------------+-------+---------+----------|\n| PanicTokenHandler | transfer     | 5434  | 0       | 0        |\n|-------------------+--------------+-------+---------+----------|\n| PanicTokenHandler | transferFrom | 5547  | 0       | 0        |\n╰-------------------+--------------+-------+---------+----------╯\n\n[PASS] testFuzz_transferFromFailureRestoresFiniteAllowance(uint256) (runs: 1000, μ: 120257, ~: 120157)\n[PASS] test_selfTransferOfFullSupplyAndZeroTransferFrom() (gas: 110214)\n[PASS] test_zeroAddressFailurePreservesBalanceAndAllowance() (gas: 108800)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 2.90s (2.91s CPU time)\n\nRan 2 tests for test/PanicHook.Invariant.t.sol:PanicNativeInvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+---------------+-------+---------+----------╮\n| Contract               | Selector      | Calls | Reverts | Discards |\n+=====================================================================+\n| PanicAccountingHandler | advance       | 2341  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buy           | 2332  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buyback       | 2374  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | claim         | 2352  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | donate        | 2347  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | sell          | 2362  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic | 2276  | 0       | 0        |\n╰------------------------+---------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2618210)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.53s (4.49s CPU time)\n\nRan 2 tests for test/PanicHook.Invariant.t.sol:PanicCurrency1InvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+---------------+-------+---------+----------╮\n| Contract               | Selector      | Calls | Reverts | Discards |\n+=====================================================================+\n| PanicAccountingHandler | advance       | 2341  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buy           | 2332  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buyback       | 2374  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | claim         | 2352  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | donate        | 2347  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | sell          | 2362  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic | 2276  | 0       | 0        |\n╰------------------------+---------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2690582)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.74s (4.71s CPU time)\n\nRan 2 tests for test/PanicHook.Invariant.t.sol:PanicCurrency0InvariantTest\n[PASS] invariant_conservationReferenceAndSupply() (runs: 256, calls: 16384, reverts: 0)\n\n╭------------------------+---------------+-------+---------+----------╮\n| Contract               | Selector      | Calls | Reverts | Discards |\n+=====================================================================+\n| PanicAccountingHandler | advance       | 2341  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buy           | 2332  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | buyback       | 2374  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | claim         | 2352  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | donate        | 2347  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | sell          | 2362  | 0       | 0        |\n|------------------------+---------------+-------+---------+----------|\n| PanicAccountingHandler | transferPanic | 2276  | 0       | 0        |\n╰------------------------+---------------+-------+---------+----------╯\n\n[PASS] test_handlerExercisesFundedAndRejectedOperations() (gas: 2692887)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.77s (4.73s CPU time)\n\nRan 17 test suites in 4.77s (17.70s CPU time): 135 tests passed, 0 failed, 0 skipped (135 total tests)\n","passed":true},{"durationMs":96,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"PanicHook.afterInitialize(address,(address,address,uint24,int24,address),uint160,int24)\",\"PanicHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"PanicHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"PanicHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"PanicHook.buybackAndBurn()\",\"PanicHook.buybackAndBurn(uint256)\",\"PanicHook.claimOracleFund()\",\"PanicHook.donateToLiquidityProviders()\",\"PanicHook.topUpBurnBucket(uint256)\",\"PanicHook.unlockCallback(bytes)\",\"PanicMonkeys.approve(address,uint256)\",\"PanicMonkeys.transfer(address,uint256)\",\"PanicMonkeys.transferFrom(address,address,uint256)\"],\"files\":{\"README.md\":364,\"foundry.toml\":33,\"launch.json\":32,\"remappings.txt\":3,\"script/DeployPanic.s.sol\":84,\"src/HookFlags.sol\":41,\"src/HookMiner.sol\":48,\"src/PanicHook.sol\":972,\"src/PanicMonkeys.sol\":68,\"test/Deploy.t.sol\":97,\"test/PanicHook.Buckets.t.sol\":494,\"test/PanicHook.Buyback.t.sol\":267,\"test/PanicHook.Donation.t.sol\":256,\"test/PanicHook.Fees.t.sol\":294,\"test/PanicHook.Flipped.t.sol\":106,\"test/PanicHook.Init.t.sol\":260,\"test/PanicHook.Invariant.t.sol\":143,\"test/PanicHook.Oracle.t.sol\":222,\"test/PanicHook.PriceMath.t.sol\":94,\"test/PanicHook.Revision.t.sol\":195,\"test/PanicMonkeys.Properties.t.sol\":137,\"test/PanicMonkeys.t.sol\":96,\"test/README.md\":52,\"test/handlers/PanicAccountingHandler.sol\":307,\"test/mocks/MockERC20.sol\":52,\"test/utils/PanicTestBase.sol\":281},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":2913,"exitCode":0,"name":"slither","output":"[high/high] arbitrary-send-erc20 at src/PanicHook.sol:593: PanicHook.unlockCallback(bytes) (src/PanicHook.sol#593-653) uses arbitrary from in transferFrom: ! IERC20Minimal(Currency.unwrap(paired)).transferFrom(payer,address(poolManager),amount) (src/PanicHook.sol#613)\n[high/medium] weak-prng at src/PanicHook.sol:713: PanicHook.drawdownBps(uint160,uint160,bool) (src/PanicHook.sol#713-727) uses a weak PRNG: \"dropped = mulmod(uint256,uint256,uint256)(scaled,num,den) | (t % den) (src/PanicHook.sol#724)\"\n[high/medium] weak-prng at src/PanicHook.sol:955: PanicHook._meanTick(int56,uint32) (src/PanicHook.sol#955-959) uses a weak PRNG: \"cumulativeDelta < 0 && cumulativeDelta % int56(uint56(duration)) != 0 (src/PanicHook.sol#957)\"\n[high/medium] weak-prng at src/PanicHook.sol:753: PanicHook._pairedToPanic(uint256,uint160,bool) (src/PanicHook.sol#753-765) uses a weak PRNG: \"exact = carry % den == 0 && mulmod(uint256,uint256,uint256)(r,num,den) == 0 (src/PanicHook.sol#764)\"\n[medium/medium] divide-before-multiply at src/PanicHook.sol:890: PanicHook._reference() (src/PanicHook.sol#890-923) performs a multiplication on the result of a division:\n[medium/high] incorrect-equality at src/PanicHook.sol:868: PanicHook._observe() (src/PanicHook.sol#868-885) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:713: PanicHook.drawdownBps(uint160,uint160,bool) (src/PanicHook.sol#713-727) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:503: PanicHook.donateToLiquidityProviders() (src/PanicHook.sol#503-515) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:518: PanicHook.donationIsDue() (src/PanicHook.sol#518-522) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:868: PanicHook._observe() (src/PanicHook.sol#868-885) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:890: PanicHook._reference() (src/PanicHook.sol#890-923) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:753: PanicHook._pairedToPanic(uint256,uint160,bool) (src/PanicHook.sol#753-765) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:890: PanicHook._reference() (src/PanicHook.sol#890-923) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:565: PanicHook._buybackAndBurn(uint256) (src/PanicHook.sol#565-590) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:927: PanicHook._prevailingTick() (src/PanicHook.sol#927-930) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:840: PanicHook._sampleLiquidity(uint128) (src/PanicHook.sol#840-849) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:821: PanicHook._notePreSwapLiquidity() (src/PanicHook.sol#821-823) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:814: PanicHook._baselineLiquidity() (src/PanicHook.sol#814-818) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:840: PanicHook._sampleLiquidity(uint128) (src/PanicHook.sol#840-849) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:868: PanicHook._observe() (src/PanicHook.sol#868-885) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/PanicHook.sol:828: PanicHook._flushDonationIfDue() (src/PanicHook.sol#828-836) uses a dangerous strict equality:\n[medium/medium] reentrancy-no-eth at src/PanicHook.sol:801: Reentrancy in PanicHook._settleAfterSwap() (src/PanicHook.sol#801-810):\n[medium/medium] reentrancy-no-eth at src/PanicHook.sol:565: Reentrancy in PanicHook._buybackAndBurn(uint256) (src/PanicHook.sol#565-590):\n[medium/medium] reentrancy-no-eth at src/PanicHook.sol:593: Reentrancy in PanicHook.unlockCallback(bytes) (src/PanicHook.sol#593-653):\n[medium/medium] uninitialized-local at src/PanicHook.sol:376: PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes).feeBps (src/PanicHook.sol#376) is a local variable never initialized\n[medium/medium] uninitialized-local at src/PanicHook.sol:379: PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes).isBuy (src/PanicHook.sol#379) is a local variable never initialized\n[medium/medium] uninitialized-local at src/PanicHook.sol:378: PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes).unspecifiedDelta (src/PanicHook.sol#378) is a local variable never initialized\n[medium/medium] uninitialized-local at src/PanicHook.sol:375: PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes).drawdown (src/PanicHook.sol#375) is a local variable never initialized\n[medium/medium] uninitialized-local at src/PanicHook.sol:377: PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes).feeAmount (src/PanicHook.sol#377) is a local variable never initialized\n[medium/medium] unused-return at src/PanicHook.sol:324: PanicHook.beforeSwap(address,PoolKey,SwapParams,bytes) (src/PanicHook.sol#324-360) ignores return value by (sqrtPriceX96,None,None,None) = poolManager.getSlot0(poolId) (src/PanicHook.sol#337)\n[medium/medium] unused-return at src/PanicHook.sol:554: PanicHook.maxBuybackSpend() (src/PanicHook.sol#554-563) ignores return value by (sqrtPriceX96,None,None,None) = poolManager.getSlot0(poolId) (src/PanicHook.sol#556)\n[medium/medium] unused-return at src/PanicHook.sol:677: PanicHook.currentDrawdownBps() (src/PanicHook.sol#677-681) ignores return value by (sqrtPriceX96,None,None,None) = poolManager.getSlot0(poolId) (src/PanicHook.sol#679)\n[medium/medium] unused-return at src/PanicHook.sol:488: PanicHook.claimOracleFund() (src/PanicHook.sol#488-494) ignores return value by poolManager.unlock(abi.encode(ACTION_CLAIM,amount,address(0))) (src/PanicHook.sol#492)\n[medium/medium] unused-return at src/PanicHook.sol:503: PanicHook.donateToLiquidityProviders() (src/PanicHook.sol#503-515) ignores return value by poolManager.unlock(abi.encode(ACTION_DONATE,amount,address(0))) (src/PanicHook.sol#513)\n[medium/medium] unused-return at src/PanicHook.sol:927: PanicHook._prevailingTick() (src/PanicHook.sol#927-930) ignores return value by (None,tick,None,None) = poolManager.getSlot0(poolId) (src/PanicHook.sol#929)\n[medium/medium] unused-return at src/PanicHook.sol:593: PanicHook.unlockCallback(bytes) (src/PanicHook.sol#593-653) ignores return value by (sqrtPriceX96,None,None,None) = poolManager.getSlot0(poolId) (src/PanicHook.sol#624)\n[medium/medium] unused-return at src/PanicHook.sol:851: PanicHook._donate(uint256) (src/PanicHook.sol#851-856) ignores return value by poolManager.donate(poolKey,amount0,amount1,) (src/PanicHook.sol#853)\n[medium/medium] unused-return at src/PanicHook.sol:868: PanicHook._observe() (src/PanicHook.sol#868-885) ignores return value by (None,tick,None,None) = poolManager.getSlot0(poolId) (src/PanicHook.sol#872)\n[medium/medium] unused-return at src/PanicHook.sol:363: PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/PanicHook.sol#363-419) ignores return value by (sqrtPriceAfter,None,None,None) = poolManager.getSlot0(poolId) (src/PanicHook.sol#399)\n[low/medium] reentrancy-benign at src/PanicHook.sol:851: Reentrancy in PanicHook._donate(uint256) (src/PanicHook.sol#851-856):\n[low/medium] reentrancy-benign at src/PanicHook.sol:363: Reentrancy in PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/PanicHook.sol#363-419):\n[low/medium] reentrancy-benign at src/PanicHook.sol:542: Reentrancy in PanicHook.topUpBurnBucket(uint256) (src/PanicHook.sol#542-550):\n[low/medium] reentrancy-benign at src/PanicHook.sol:593: Reentrancy in PanicHook.unlockCallback(bytes) (src/PanicHook.sol#593-653):\n[low/medium] reentrancy-events at src/PanicHook.sol:542: Reentrancy in PanicHook.topUpBurnBucket(uint256) (src/PanicHook.sol#542-550):\n[low/medium] reentrancy-events at src/PanicHook.sol:503: Reentrancy in PanicHook.donateToLiquidityProviders() (src/PanicHook.sol#503-515):\n[low/medium] reentrancy-events at src/PanicHook.sol:593: Reentrancy in PanicHook.unlockCallback(bytes) (src/PanicHook.sol#593-653):\n[low/medium] reentrancy-events at src/PanicHook.sol:801: Reentrancy in PanicHook._settleAfterSwap() (src/PanicHook.sol#801-810):\n[low/medium] reentrancy-events at src/PanicHook.sol:363: Reentrancy in PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/PanicHook.sol#363-419):\n[low/medium] reentrancy-events at src/PanicHook.sol:593: Reentrancy in PanicHook.unlockCallback(bytes) (src/PanicHook.sol#593-653):\n[low/medium] reentrancy-events at src/PanicHook.sol:363: Reentrancy in PanicHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/PanicHook.sol#363-419):\n[low/medium] reentrancy-events at src/PanicHook.sol:828: Reentrancy in PanicHook._flushDonationIfDue() (src/PanicHook.sol#828-836):\n[low/medium] reentrancy-events at src/PanicHook.sol:488: Reentrancy in PanicHook.claimOracleFund() (src/PanicHook.sol#488-494):\n[low/medium] reentrancy-events at src/PanicHook.sol:565: Reentrancy in PanicHook._buybackAndBurn(uint256) (src/PanicHook.sol#565-590):\n[low/medium] timestamp at src/PanicHook.sol:753: PanicHook._pairedToPanic(uint256,uint160,bool) (src/PanicHook.sol#753-765) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:703: PanicHook.sellFeeBps(uint256) (src/PanicHook.sol#703-708) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:868: PanicHook._observe() (src/PanicHook.sol#868-885) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:698: PanicHook.buyFeeBps(uint256) (src/PanicHook.sol#698-700) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:955: PanicHook._meanTick(int56,uint32) (src/PanicHook.sol#955-959) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:565: PanicHook._buybackAndBurn(uint256) (src/PanicHook.sol#565-590) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:860: PanicHook._observeAndReference() (src/PanicHook.sol#860-865) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:713: PanicHook.drawdownBps(uint160,uint160,bool) (src/PanicHook.sol#713-727) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:890: PanicHook._reference() (src/PanicHook.sol#890-923) uses timestamp for comparisons\n[low/medium] timestamp at src/PanicHook.sol:934: PanicHook._findWindowStart(uint32,uint256) (src/PanicHook.sol#934-952) uses timestamp for comparisons","passed":false}],"detail":"static analysis found arbitrary-send-erc20 at src/PanicHook.sol:593: PanicHook.unlockCallback(bytes) (src/PanicHook.sol#593-653) uses arbitrary from in transferFrom: ! IERC20Minimal(Currency.unwrap(paired)).transferFrom(payer,address(poolManager),amount) (src/PanicHook.sol#613)","evaluation":"checks","profile":"foundry","status":"rejected","submissionHash":"fe4775484ae429b57252eccdc0eb89801b0710e65baa05162355198f08504a67","verifiedTreeHash":"669047a93aa53f145e5eb292d0a7749de24b72e6","verifierVersion":"0.1.0+be003835"}]}