{"assessments":[],"deployments":[],"fuzz":[],"identity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"interpretation":"Records acceptance and evidence. Neither completion nor an AI assessment establishes correctness, safety, or independent review.","jobId":"be36186c-e7ba-40a2-88be-61b57e5f897f","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"c6ed97e5349ed052696d4a6b214fbfcc1650883da9cba16905a0917aae05ff44","dependsOn":["build_contract_project","write_foundry_tests","manifest"],"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":"97ff4fcf7a12b538e6712be69dfb4e583bae52de298bdd82dc2ddcf0ec9f1062","dependsOn":["build_contract_project","write_foundry_tests","manifest"],"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":"9046df7bbf72a0ed36a75968f189138d52e6b8aa03143e87288b55123de6c485","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":"5272e2a1b7560ad42a0dfbe301412a91b2f0418edc90b34976b131ec337f13e0","dependsOn":["build_contract_project","write_foundry_tests","manifest"],"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":"49d2865ca264c14a6ddf08649656a18a59364b9bd0a34e6eb78cb33edf394453","dependsOn":["build_contract_project","write_foundry_tests","manifest"],"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":"969f52ef760b9a341b1633f04459042b3000699a911030ec77ba004c83b3ca7d","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"587567a5ef71546b5973ceaf6ef1dbbd590f49503b5ac9a6973ed86b89584857","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"587567a5ef71546b5973ceaf6ef1dbbd590f49503b5ac9a6973ed86b89584857","skillId":"build-contract-project","state":"accepted"},{"acceptedSubmissionHash":"46812928ce69805b1f55bd936f56664f2bd22c608ec01b254e126621a1d4ddb6","dependsOn":["build_contract_project","write_foundry_tests"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"e1af35fe6c25b24aef0255f95ab993d1c37f9a66dfdebff5a724361d65fcfa9b","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":"[SIMD-LAUNCH]\nToken name: SIMDTEST\nToken symbol: SIMDTEST\n\nThis launch deploys the SIMDTEST standard ERC-20 token (1 billion supply, 18 decimals, no taxes) and a Uniswap v4 hook named SIMDTESTHook that applies an additional dynamic fee on swaps in the paired IMD currency. The fee starts at 4000 basis points (40%) at pool initialization and linearly decreases with elapsed time to a steady-state fee of 300 bps (3%) after 3600 seconds (60 minutes). The pool fee remains constant at 12500 units (1.25%) per Uniswap v4 policy. The entire dynamic fee accrues in the hook contract, held in the paired currency (IMD), and can be swept by anyone to the immutable treasury address 0x3dd5f73dd1a4e62630fad3909673f130ad429985 supporting the SIMD Hackathon fund. No ownership or admin controls exist; all parameters, including fees and treasury, are constants fixed on deployment. The launch mints the full 1,000,000,000 tokens to the deployer; 90% of supply seeds the pool, with no remainder or burn address as all tokens are allocated to the pool. The hook exposes view functions feeNow(), openedAt(), pending(), and collected() for transparency. Swaps incur the hook fee on the paired currency side only, never on transfers involving the pool to prevent settlement errors. This launch implements the proven live pattern from launch #909 for opening and standing fee schedules with treasury funding, providing a fair and transparent mechanism to support the SIMD ecosystem via the swap fees. TESTS AND REVIEW include immutable parameter checks, fee calculation accuracy over the 60-minute schedule, accrual and sweep functionality, interaction correctness with Uniswap v4 swaps on mainnet-fork, and security review confirming no ownership or upgrade paths.\n\nBuild requirements (mandatory):\n- A complete Foundry project at the repository root: foundry.toml with solc 0.8.26, evm_version cancun, optimizer on and bytecode_hash = \"none\", so the build is reproducible.\n- Contracts: SIMDTESTHook. The hook is the hook of this launch's pool; keep its creation code within the EIP-3860 size limit.\n- No selfdestruct and no delegatecall anywhere in runtime code. No proxies, no owner, no upgradeability.\n- Chain: Ethereum mainnet (chainId 1). Uniswap v4 PoolManager: 0x000000000004444c5dc75cB358380D2e3dE08A90 (pass it to the hook constructor).\n- Paired currency: IMD, the ERC-20 at 0xd34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7 on Ethereum mainnet (18 decimals).\n- Every address the hook needs is known now and fixed at deployment; nothing may require an owner or a setter after launch.\n- Supply distribution is done by the launch factory: it mints the supply, seeds the pool, sends the swarm's 10% through its Merkle distributor and any remainder to remainderTo. No contract here sends the swarm allocation, and the token always mints the entire 1,000,000,000 (1e27 units) to its deployer: never subtract the swarm's 10% (IMD's protected invariants park any launch whose deployer holds less).\n- Hook fees are collected through beforeSwap/afterSwap return deltas, on top of the pool's static 1.25% LP fee (fee tier 12500). Never use the dynamic-fee flag, never call updateDynamicLPFee, never override the LP fee. The hook never reverts a swap.\n- The hook is a plain immutable contract deployed directly at a CREATE2-mined address with the right permission bits, and launch.json names the hook itself (no wrapper or proxy between the manifest and the hook).\n- Tests: Foundry unit, fuzz and mainnet-fork tests that swap through the real PoolManager with the hook (exact-input and exact-output, buys and sells), plus permission bits matching the hook address.\n- launch.json pool: pairedCurrency 0xd34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7, fee 12500, tickSpacing 60, initialPrice \"79228162514264337593543950336\" (provenance only; the launch factory sets the opening price from the economics).","parentJobId":null,"planHash":"80f27bf488f9a2931bdb1eb4cf918cd3edd06fbcc2092a36af9962d018ab0df3","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"be36186c-e7ba-40a2-88be-61b57e5f897f","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-997-simdtest"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"52271","feedbackHash":"81b8f25bf0d7bdb92fc40882ef5ecd03655f9cd7ebcdef206cd38db5436900de","nodeKey":"audit_economics","submissionHash":"c6ed97e5349ed052696d4a6b214fbfcc1650883da9cba16905a0917aae05ff44","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51024","feedbackHash":"9269023837211eb91c8dbe18d08723c76936abf48eebd581257e8f5123df15de","nodeKey":"audit_flow","submissionHash":"97ff4fcf7a12b538e6712be69dfb4e583bae52de298bdd82dc2ddcf0ec9f1062","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52114","feedbackHash":"3c5b9eb90c704759f6bd88cde9c710d60e280bae2b31610d96266c1aacaca9af","nodeKey":"audit_judge","submissionHash":"9046df7bbf72a0ed36a75968f189138d52e6b8aa03143e87288b55123de6c485","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51022","feedbackHash":"bed286d28684d50be7f3c12e941bccbe7a843fef6cbf9155503b4148c491caa0","nodeKey":"audit_math","submissionHash":"5272e2a1b7560ad42a0dfbe301412a91b2f0418edc90b34976b131ec337f13e0","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51508","feedbackHash":"cb21e2557a0c8d87e1b946c0c827866c8affdd9e2faef8f27b8787934a9456b8","nodeKey":"audit_permissions","submissionHash":"49d2865ca264c14a6ddf08649656a18a59364b9bd0a34e6eb78cb33edf394453","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52140","feedbackHash":"34e7731b296a45be6472e37a9826cddecd73a6cf9c489c5fffdfa2033cca4f17","nodeKey":"build_contract_project","submissionHash":"969f52ef760b9a341b1633f04459042b3000699a911030ec77ba004c83b3ca7d","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51752","feedbackHash":"4799dc5db7d24e46a70ba34c7f9233b407c87103b0d8c0f89ca9b0f77e2cfdd1","nodeKey":"build_contract_project","submissionHash":"c33d9c7a885324dc05f8324da269ed6764db0fd96d99ac23a67c87eb2da2db9f","tag1":"verification:checks","tag2":"acceptance-v2","value":0},{"agentId":"51030","feedbackHash":"f4e395644d99709c159bd54435ba44905ec553f025ad571bdb4a18d7a8edf465","nodeKey":"manifest","submissionHash":"46812928ce69805b1f55bd936f56664f2bd22c608ec01b254e126621a1d4ddb6","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51040","feedbackHash":"4c42cb67a6573806c658beee576bb44e790a5237247eb017611b2327e087f24d","nodeKey":"write_foundry_tests","submissionHash":"e1af35fe6c25b24aef0255f95ab993d1c37f9a66dfdebff5a724361d65fcfa9b","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"244d10b028dc77fde6a0e6356cb9c546c1909f9a6df4fe3103c39d0ff3f6b1d3","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"8139bad577dafeeeeaf69673fdc20fb90a75441d1b26392518826ff4c5339837","device":"06486f6fefb50394","findings":[],"hash":"46812928ce69805b1f55bd936f56664f2bd22c608ec01b254e126621a1d4ddb6","nodeId":"7b2415d3-eee2-46fe-82d9-fa1f9f1d18cb","outcome":"completed","summary":"Updated [launch.json](/home/imd-worker/.identitymd/work/be36186c-e7ba-40a2-88be-61b57e5f897f/7b2415d3-eee2-46fe-82d9-fa1f9f1d18cb/launch.json) to describe the existing implementation accurately.\n\n- Schema, constructor ABI, permissions, and pool checks passed.\n- `forge build` passed.\n- `forge test`: 83 passed, 0 failed; two mainnet-fork suites skipped without a selected fork.\n- Only `launch.json` changed outside permitted scratch files.","treeHash":"3f995356240ef333be30b327fbf206ee437449a9","usage":{"cachedInputTokens":1271808,"inputTokens":73181,"model":"gpt-6-astra","outputTokens":5644,"runtime":"codex","turns":5,"wallClockMs":298391}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"3516474d8a268bd8","findings":[{"citation":"resolved","description":"The `sender` argument of beforeInitialize is discarded, so the only guards on opening the pool are the caller being PoolManager and the key matching token/IMD, fee 12500, spacing 60. Whoever submits PoolManager.initialize first for that key wins: they choose the opening sqrtPriceX96 (the hook does not constrain it) and set openedAt, which starts the 60-minute 40%->3% decay. The factory's own initialize then reverts (AlreadyInitialized, wrapped by the manager's hook-call error) and cannot reset the clock. Under the launch factory described in the assignment this is unreachable, because the factory deploys the hook and initializes the pool in one transaction and nothing else can initialize a pool against a hook address with no code. The README and docs/SECURITY_REVIEW.md record the same assumption. This is reported as a trust assumption for the judge, not a defect under the atomic factory; the reference guide offers `$factory` as a constructor argument for hooks that want to pin the initializer, which would close the gap at the cost of one more constructor argument in launch.json.","line":69,"path":"src/SIMDTESTHook.sol","reproduction":"Local PoolManager; SIMDTEST deployed; hook CREATE2-deployed at an address with mask 0x20cc; no initialize yet. vm.warp(1_000_000); vm.prank(0xBAD); manager.initialize({token/IMD sorted, fee 12500, tickSpacing 60, hooks: hook}, 79228162514264337593543950336 * 1000) -> succeeds; hook.initialized() == true; hook.openedAt() == 1_000_000. vm.warp(1_000_000 + 3600); hook.feeNow() == 300 (opening schedule fully consumed). Then manager.initialize(sameKey, 79228162514264337593543950336) from the factory address -> reverts; hook.openedAt() still 1_000_000. Expected under the launch design: only the factory's atomic transaction opens the pool, at the price it computes. Actual: any address can, if a non-atomic path ever exists. Verified with a scratch Foundry test (test/scratch/OpenInit.t.sol, not kept).","severity":"info","snippet":"    function beforeInitialize(address, PoolKey calldata key, uint160)","title":"beforeInitialize does not bind the initializer: anyone may open the launch pool and start the fee clock if hook deployment and initialize are ever split across transactions"}],"hash":"49d2865ca264c14a6ddf08649656a18a59364b9bd0a34e6eb78cb33edf394453","nodeId":"4bc5c9f6-51a7-4c30-a657-7c08444c8be2","outcome":"completed","summary":"The review is complete. The findings file is written and no source files were changed.\n\n**Outcome.** I found no defect in the Access Control, Trust Gap or Asymmetry areas that opens a revision. The hook's permission model is sound, and its paired code paths are economically symmetric. One info-level trust assumption is recorded with a reproduction.\n\n**What I verified.**\n- Every callback and `unlockCallback` refuse any caller but the PoolManager, and `unlockCallback` additionally requires the hook's own sweep to be in progress. PoolManager only calls back its unlocker, so nobody else can reach it.\n- The beforeInitialize permission bit forces every pool using this hook through the one-shot key check, so exactly one SIMDTEST/IMD pool at fee 12500 and spacing 60 can ever exist.\n- In both swap callbacks the claim minted to the hook equals the delta returned, so the hook's manager delta always nets to zero. Each swap is charged on exactly one side, and the four modes all take the same share of gross IMD.\n- The sweep path can route value only to the constant treasury. The reentrancy flag and the unlocked check make reentry a no-op, and a failed treasury transfer reverts the sweep without touching swaps. No operator or approval lets a third party burn or move the hook's ERC-6909 claims.\n- The token is unmodified OpenZeppelin ERC-20 with a single constructor mint, and the manifest's constructor arguments and permission list match the implementation.\n\n**The one recorded item.** `beforeInitialize` ignores its `sender`, so if hook deployment and pool initialization were ever split across transactions, any address could open the pool at its own price and start the 60-minute fee clock. My scratch test confirmed this: a stranger's initialize succeeded, the fee had already decayed to 3% an hour later, and the factory's own initialize then reverted. Under the atomic launch factory the assignment describes this is unreachable, and the author documents the assumption, so it is filed as info only.\n\n**Coverage.** All eight listed entry points have rows, plus three invariant rows. Seven entry points hold and one carries the info finding. The static-analysis leads on strict equality, reentrancy ordering and timestamp use were each traced and do not produce a failing input. Not reached within this review: a live mainnet-fork run, which the project's own records also report as still owed.","treeHash":null,"usage":{"cachedInputTokens":1356845,"inputTokens":322,"model":"claude-fable-5-1","outputTokens":36748,"runtime":"claude","turns":33,"wallClockMs":581375}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"c35be49d2f8f8def","findings":[],"hash":"5272e2a1b7560ad42a0dfbe301412a91b2f0418edc90b34976b131ec337f13e0","nodeId":"f37b9929-d7d5-4c88-b314-5cf3b15d0df9","outcome":"completed","summary":"Review complete. The findings file is written with an empty defect list and a 12-row coverage record.\n\n**Outcome: no defect found in the Math Precision, Boundary or Numerical Gap areas.** The fee arithmetic in `src/SIMDTESTHook.sol` and the read-only fill quote in `src/SpecifiedAmount.sol` hold under every edge I could construct.\n\nWhat I verified, beyond reading the code against the three guides:\n\n- **Quote equals manager fill.** I compared `SpecifiedAmount.filled` line by line with the vendored Pool.swap loop and fuzzed 1,500 four-swap sequences on a hookless pool. Sequences start from states a prior swap left exactly on a tick boundary, use limits on and adjacent to initialized ticks, and run with protocol fees on. Quote and fill agreed to the wei every time.\n- **Fee tightness in all four modes.** Across 3,000 fuzzed sequences in both currency orderings, the fee never exceeded gross IMD times rate over ten thousand and never fell more than one wei below it. I also proved on paper that the exact-out sell path cannot overcharge even on partial fills.\n- **Schedule boundaries.** The closed form, the rounding toward the trader, the 3599-to-3600 step, timestamp zero, and the divisor floor of 6000 all behave as the README states.\n- **Casts and caps.** Fees stay under two thirds of int128.max. Requests of int128.max minus one and int128.max charge the exact fee. One above that reverts inside the manager's SafeCast, which the README documents as out of domain.\n- **Dust threshold.** At the 3% standing rate, 33 wei of gross IMD pays no fee and 34 wei pays one wei. This is documented and uneconomic to farm, so I did not report it.\n- **Real IMD token and live fork.** Through a public RPC I read the mainnet IMD contract: a LayerZero OFT over a standard OpenZeppelin ERC-20 with no pause, blacklist or transfer-fee selectors. The repository's five mainnet fork tests, which the README says had never completed, passed against block 26145700 with the real PoolManager and IMD.\n\nStatic-analysis leads were all benign: the strict equalities are deliberate fast paths, the sweep reentrancy guard holds because the only external calls are to the manager and a hookless ERC-20, and the ignored `liquidityGross` return is unused by design.\n\nNot reached: nothing in my area. The remaining release responsibility is outside it, namely the factory's atomic deploy, initialize and seed, which the fee clock assumes.","treeHash":null,"usage":{"cachedInputTokens":2208767,"inputTokens":482,"model":"claude-fable-5-1","outputTokens":57317,"runtime":"claude","turns":42,"wallClockMs":1680790}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"918f8261a6fd589c","findings":[{"citation":"resolved","description":"Settles the audit_economics finding (medium) at low. It reproduces: the hook charges only inside beforeSwap/afterSwap and enables no liquidity callbacks, so modifyLiquidity on the launch pool is never charged. A SIMDTEST holder can park tokens as a position whose whole range sits above the current tick (funded with SIMDTEST only), wait for buyers to push the price through it, then remove the position and leave with IMD, and the hook accrues nothing on that side. The mirror (an IMD-only range just below spot filled by sellers) lets a buyer acquire SIMDTEST without the buy fee. During the opening hour, when the rate is 40% falling to 3%, the saving dwarfs the 1.25% LP fee the position additionally earns, so a patient seller is rationally pushed onto this route and the treasury receives less than the schedule implies. The same root cause also covers routing around the hook through any hookless SIMDTEST pool seeded from the 10% distributor allocation. Severity is recalibrated to low rather than medium because nothing held by anyone is lost, no funds go to a wrong party, and the brief and build requirements mandate exactly this design: the fee is 'on swaps', collected 'through beforeSwap/afterSwap return deltas', the token has no transfer tax, and the #909 pattern is required; README line 44 already states that liquidity addition/removal is never charged. Enabling liquidity callbacks (afterRemoveLiquidity + afterRemoveLiquidityReturnDelta with per-position IMD accounting, or beforeAddLiquidity refusing one-sided ranges during OPENING_SECONDS) would change the mandated permission set, HookFlags.SIMDTEST, launch.json permissions and the mined mask 0x20cc, so it is a requester design decision, not an author fix. The expected resolution is a plain statement in README and launch.json notes that range orders and other pools are not charged, so the treasury's revenue expectation is set correctly. The existing suite only round-trips a two-sided in-range position (testLiquidityAndDonationsAreNeverCharged); the one-sided route is untested.","line":61,"path":"src/SIMDTESTHook.sol","reproduction":"Local PoolManager, SIMDTEST deployed at IMD-1 (so SIMDTEST is currency0, IMD currency1; the other ordering behaves the same), hook CREATE2-deployed at mask 0x20cc, pool initialized at sqrtPrice 2^96 with 1e24 liquidity in [-6000, 6000], block.timestamp == openedAt so feeNow() == 4000. Seller holds 1e22 SIMDTEST and 0 IMD. Route A (swap): seller swaps exact-input 1e22 SIMDTEST zeroForOne with limit MIN_SQRT_PRICE+1 -> seller receives 5867062755291496472336 IMD and hook.collected() == 3911375170194330981556. Route B (range order) from the same snapshot: seller calls modifyLiquidity(tickLower 60, tickUpper 120, liquidityDelta = 1e22*sa/2^96*sb/(sb-sa)) which needs 0 IMD; a buyer swaps exact-input 5e23 IMD oneForZero with limit at tick 200 (pays its own buy fee; tick ends above 120); seller removes the full position. Expected under a fee-on-every-conversion reading: the seller's IMD exit is charged feeNow() on IMD withdrawn (about 4087251312348188824475 at 40%). Actual: hook.collected() is unchanged by the exit (fee on exit == 0) and the seller's IMD balance is 10218128280870472061189, 74% more than the taxed sell. Verified by running the economics specialist's proof unchanged as test/scratch/RangeOrderBypass.t.sol with `forge test --match-path test/scratch/RangeOrderBypass.t.sol -vv`: it fails on this tree with 'range exit paid no hook fee on IMD withdrawn: 0 < 4087251312348188824475'. No proof is attached to this finding on purpose: a test that only passes once liquidity is charged would force the design change the brief forbids.","severity":"low","snippet":"    function getHookPermissions() public pure returns (Hooks.Permissions memory p) {\n        p.beforeInitialize = true;\n        p.beforeSwap = true;\n        p.afterSwap = true;\n        p.beforeSwapReturnDelta = true;\n        p.afterSwapReturnDelta = true;\n    }","title":"Sellers (and buyers) can convert through the launch pool without paying the hook fee by using a one-sided range order instead of a swap; the swap-only fee design is a documented limit of the mandated "},{"citation":"resolved","description":"Confirms the audit_flow finding (info). Documentation only, no code impact. The verification record predates the extended suites (HookAdversarial, InvariantExtended, SpecifiedAmount, MainnetForkExtended): the default `forge test` on this tree reports 83 passed, 0 failed, 2 skipped across 12 suites, not 28/1. The same file's line 12 ('Mainnet-fork attempt: Not executed successfully ... HTTP 504') and README line 25 ('This assignment's attempted fork run failed at the RPC with HTTP 504; no successful live-fork result is claimed') are also out of date: during this review the fork suite ran against the real PoolManager 0x000000000004444c5dc75cB358380D2e3dE08A90, the real IMD token and the real treasury contract at mainnet block 26146246 and all 12 fork tests passed (buys and sells, exact-input and exact-output, partial fills, token-only seed, an hour of trading then sweep, treasury contract receipt). The author should refresh both files so a later reviewer does not rely on the statement that no fork result exists.","line":8,"path":"docs/VERIFICATION.md","reproduction":"Run `forge test` at the repository root: output ends with '83 tests passed, 0 failed, 2 skipped (85 total tests)' (12 suites). Run `forge test --match-contract MainnetFork --fork-url https://ethereum-rpc.publicnode.com`: '12 tests passed, 0 failed, 0 skipped' (MainnetForkTest 5, MainnetForkExtendedTest 7) at block 26146246. Expected: VERIFICATION.md line 8 and line 12 and README line 25 reflect the current suite and the successful fork result. Actual: they state 28 passed / 1 skipped and that no fork run succeeded.","severity":"info","snippet":"| `forge test -vv` | **28 passed, 0 failed, 1 skipped**. The skip is the mainnet-fork suite when no fork is selected. |","title":"docs/VERIFICATION.md and README record a stale test count and claim no successful fork run; the tree now has 83 offline tests and the fork suite passes against live mainnet"},{"citation":"resolved","description":"Confirms the audit_permissions finding at info; it is a trust assumption, not a defect under the launch design. The only guards on opening the pool are the caller being PoolManager, the key matching token/IMD at fee 12500 and spacing 60, and the hook being this contract; the initializer and the sqrtPriceX96 are not constrained. Whoever submits PoolManager.initialize first for that key sets openedAt and the opening price, and the factory's own initialize then reverts (AlreadyInitialized wrapped by the manager's hook-call error) with no way to reset the clock. Under the launch factory described in the assignment this path does not exist: the factory deploys the hook and initializes the pool in one transaction, and a pool cannot be initialized against a hook address that has no code (the manager calls beforeInitialize, which has to return the selector). README line 89 and docs/SECURITY_REVIEW.md line 27 record the same atomicity requirement. The reference offers a `$factory` constructor argument for hooks that want to pin the initializer; adopting it is optional and would add one constructor argument to launch.json. No code change is required for admission.","line":69,"path":"src/SIMDTESTHook.sol","reproduction":"Already exercised by the tree's own test test/Hook.t.sol testInvalidInitializationAndNoReset (lines 100-129): a fresh SIMDTESTHook is CREATE2-deployed at mask 0x20cc; vm.warp(1000); the test contract (not a factory) calls manager.initialize(key with token/IMD, 12500, 60, hooks = fresh, Q96) -> succeeds; fresh.openedAt() == 1000; a later beforeInitialize from the manager at warp 2000 reverts AlreadyInitialized and openedAt stays 1000. Expected under the launch design: only the factory's atomic transaction opens the pool, which is what happens because the hook has no code before that transaction. Actual if a non-atomic path were ever used: any address can open the pool and start the clock. Verified locally; no scratch test needed.","severity":"info","snippet":"    function beforeInitialize(address, PoolKey calldata key, uint160)\n        external\n        onlyPoolManager\n        returns (bytes4)\n    {","title":"beforeInitialize ignores its sender: if hook deployment and PoolManager.initialize were ever split across transactions, anyone could open the launch pool, choose its opening price and start the 60-min"}],"hash":"9046df7bbf72a0ed36a75968f189138d52e6b8aa03143e87288b55123de6c485","nodeId":"a2fe2e93-cdb6-4106-8288-95db094f5815","outcome":"completed","summary":"The review is complete. The findings file is written, the snippets match the tree, no repository file was changed, and the scratch directory is removed.\n\n**Outcome.** The SIMDTEST launch code has no fund-loss or correctness defect. I kept three of the four specialists' reports after reproducing each, recalibrated one, and found nothing new in my own pass.\n\n**Findings written to .imd-findings.json**\n\n- **Low: range-order fee avoidance.** The economics specialist's proof fails on this tree exactly as stated. A seller who parks SIMDTEST as a one-sided position above spot and withdraws after buyers cross it leaves with 74% more IMD than a taxed sell, and the treasury gets nothing on that side. I lowered it from medium because no held funds are lost and the brief mandates a swap-only fee through beforeSwap and afterSwap deltas. Any code fix would change the required permission set and mined mask. The expected resolution is documentation. I attached no proof so the author is not forced into a design change the brief forbids.\n- **Info: stale verification record.** The default suite now reports 83 passed and 2 skipped, not 28 and 1. I also ran the fork suite myself against live mainnet at block 26146246 through the real PoolManager, IMD and treasury. All 12 fork tests passed, so the \"no successful fork run\" statements in VERIFICATION.md and the README are out of date.\n- **Info: beforeInitialize does not bind its sender.** Reproduced by the tree's own test, where a non-factory caller opens a fresh hook's pool and starts the clock. Unreachable under the atomic factory, so it is recorded as a trust assumption, not a defect.\n\n**Dropped.** Nothing from the specialists was unreproducible. The static-analysis leads all resolved as benign after tracing: the strict equalities are intentional, the sweep reentrancy is guarded by the sweeping flag and the unlocked check, and the ERC-20 transfer goes through v4's checked Currency library.\n\n**My own pass.** I traced the read-only quote in SpecifiedAmount line by line against the vendored Pool.swap loop, confirmed the four swap modes are mutually exclusive between the two callbacks, bounded the fee so HookDeltaExceedsSwapAmount and int128 casts cannot trigger, and checked the live contracts. The treasury contract exposes withdraw and withdrawAll, so swept IMD is recoverable, and IMD is a plain LayerZero OFT with no blocklist or pause.\n\n**Coverage.** All eight entry points are answered, plus three invariant rows. Seven hold. beforeInitialize points at the informational finding.","treeHash":null,"usage":{"cachedInputTokens":1074219,"inputTokens":258,"model":"claude-fable-5-1","outputTokens":46144,"runtime":"claude","turns":33,"wallClockMs":727539}},{"artifacts":[],"attempt":2,"bundleHash":"ced77d2389507b191e1f6a2b0ea4a44502a8cb668bba6b3986f098dcde060df4","device":"04cf70660d4946e6","findings":[],"hash":"969f52ef760b9a341b1633f04459042b3000699a911030ec77ba004c83b3ca7d","nodeId":"09d6e224-ad78-447f-b31a-bb15468a8104","outcome":"completed","summary":"Implemented SIMDTEST, the immutable fee hook, vendored dependencies, tests, documentation, and the corrected `univ4_hook` manifest.\n\nLocal verification passed: `forge build`, `forge fmt --check`, 28 project tests, and all 11 supplied protected checks.\n\nMainnet-fork tests are included, but live verification remains pending: the RPC returned HTTP 504. The offline suite skips them explicitly.","treeHash":"509aaa03406263f076e7ea556214eca42d7938ee","usage":{"cachedInputTokens":2721152,"inputTokens":120754,"model":"gpt-6-astra","outputTokens":32052,"runtime":"codex","turns":8,"wallClockMs":1090446}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"e6de8d4c6cf97551","findings":[{"citation":"resolved","description":"Documentation only, no code impact. The verification record predates the extended test suites: `forge test` on this tree reports 83 passed, 0 failed, 2 skipped (12 suites), and the same file's 'Mainnet-fork attempt: Not executed successfully' row is also out of date. During this review `forge test --match-contract MainnetFork --fork-url <public mainnet RPC>` ran at block 26145740 against the real PoolManager 0x000000000004444c5dc75cB358380D2e3dE08A90, the real IMD token and the real treasury contract: 12 passed, 0 failed (buy/sell, exact-input/exact-output, partial fills, token-only seed, an hour of trading then sweep, treasury contract receipt). The supplied protected Hook and Token gate tests (11) also pass against the compiled creation code with the manifest's pool terms. The author should refresh the record so reviewers do not rely on the stale 'no fork result' statement.","line":8,"path":"docs/VERIFICATION.md","reproduction":"Run `forge test` at the repository root: output ends with '83 tests passed, 0 failed, 2 skipped (85 total tests)', not 28/1. Run `forge test --match-contract MainnetFork --fork-url https://ethereum-rpc.publicnode.com`: 12 passed. Expected: VERIFICATION.md reflects the current suite and the fork result. Actual: it states 28 passed and that no fork run succeeded.","severity":"info","snippet":"| `forge test -vv` | **28 passed, 0 failed, 1 skipped**. The skip is the mainnet-fork suite when no fork is selected. |","title":"docs/VERIFICATION.md records a stale test count and an unexecuted fork run; the current tree has 83 offline tests and the fork suite passes against live mainnet"}],"hash":"97ff4fcf7a12b538e6712be69dfb4e583bae52de298bdd82dc2ddcf0ec9f1062","nodeId":"39bb27a3-d5e7-4ea2-9cd3-85307ab72808","outcome":"completed","summary":"The review is complete. I found no reproducible defect in the SIMDTEST hook or token, and the findings file at `.imd-findings.json` records one informational note plus a full coverage record.\n\n**What I checked, per my assigned guides**\n\n- **Execution Trace.** Traced every swap mode in both currency orderings through the vendored `PoolManager.swap`, `Hooks.beforeSwap` and `Hooks.afterSwap`. The hook charges exactly once per swap. Its specified-currency fee never exceeds the amount it reserves, so the manager's `HookDeltaExceedsSwapAmount` check is unreachable. I confirmed that bound exhaustively for every rate from 300 to 4000 bps. The ERC-6909 mint in the callback is exactly offset by the manager's hook-delta credit, so the hook always ends the unlock at zero delta.\n- **Periphery.** Compared `SpecifiedAmount.filled` line by line against the vendored `Pool.swap` loop: fee composition including protocol fees, bitmap mask math, tick clamps, step bounds and tick transitions all match. Its one structural difference, an extra tick recompute, only happens when the loop is about to exit. The 1500-run fuzz equality against the real manager passes. `HookDeployer` and `HookFlags` are correct and outside the launch path.\n- **First Principles.** Checked the implicit assumptions: the real IMD token at `0xd34a…63b7` is a verified LayerZero OFT built on a plain OpenZeppelin ERC-20 with no tax, pause or blocklist. The treasury is an owned contract that receives ERC-20 transfers without a hook. The sweep's reentrancy and in-unlock paths return zero. A failed treasury transfer only reverts the sweep.\n\n**Evidence gathered**\n\n| Check | Result |\n|---|---|\n| `forge test` offline | 83 passed, 0 failed, 2 skipped |\n| Fork suite against live mainnet, block 26145740 | 12 passed, 0 failed |\n| Supplied protected Hook and Token gate tests | 11 passed, 0 failed |\n| `forge fmt --check` | clean |\n\n**Static-analysis leads.** All examined and none promoted: the strict equalities are intentional full-fill and zero checks, the sweep reentrancy is guarded by the `sweeping` flag and the manager lock, the unused return is a tuple destructure, and the timestamp use is the specified fee schedule.\n\n**The one note.** `docs/VERIFICATION.md` still states 28 tests and no successful fork run. Both are stale now. I reported this as informational so the author refreshes the record.\n\n**Coverage.** All eight listed entry points are marked `holds`, along with rows for the quote library, the deployer helper, the fee-schedule and accounting invariants, and the manifest-to-implementation match. Nothing was left unreached. My scratch directory has been removed and no other files were changed.","treeHash":null,"usage":{"cachedInputTokens":1962429,"inputTokens":418,"model":"claude-fable-5-1","outputTokens":48071,"runtime":"claude","turns":49,"wallClockMs":993141}},{"artifacts":[],"attempt":1,"bundleHash":"e54d8ed2f196b49fb30b3cac7dabbb4e4657eccd66cc0c9b2926252c9a8be0e9","device":"7143d892ed24d728","findings":[],"hash":"c33d9c7a885324dc05f8324da269ed6764db0fd96d99ac23a67c87eb2da2db9f","nodeId":"09d6e224-ad78-447f-b31a-bb15468a8104","outcome":"completed","summary":"Implemented the token, immutable hook, manifest, vendored dependencies, deployment helper, tests, and review documentation.\n\n- `forge build`, `forge test`, and `forge fmt --check` pass.\n- 64 tests passed; invariant testing completed 8,192 operations without reverts.\n- Mainnet fork tests are included but remain unverified: RPC requests failed with HTTP 403/504.\n\nDeployment details and limitations are in [README.md](/root/.identitymd/work/be36186c-e7ba-40a2-88be-61b57e5f897f/09d6e224-ad78-447f-b31a-bb15468a8104/README.md).","treeHash":"56f444df7cda73353355ee6a9187ad55bb285f9d","usage":{"cachedInputTokens":2823296,"inputTokens":123190,"model":"gpt-6-astra","outputTokens":45899,"runtime":"codex","turns":7,"wallClockMs":2236524}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"b414b10f97bca557","findings":[{"citation":"resolved","description":"The launch's economics rest on every conversion between SIMDTEST and IMD through the launch pool paying the hook fee (40% of gross IMD at opening, decaying to 3%). The hook only charges inside beforeSwap/afterSwap; it enables no liquidity callbacks, so modifyLiquidity on the same pool is free of hook fees (README line 44 states this as intended). A holder who wants IMD does not need to swap: they add a position whose range lies entirely above the current tick (it is funded with SIMDTEST only, zero IMD), wait for buyers to push the price through the range, and remove the position, which is now entirely IMD. The holder received IMD from the pool for SIMDTEST and the hook accrued nothing on their side; the buyers who filled them paid their own buy fee, which is unchanged. The mirror route works for buyers: an IMD-only range just below spot is filled by sellers and withdrawn as SIMDTEST, paying no buy fee. The cost of the route is only waiting, and during the first hour, when the fee is 40% to 3%, the saving is far above the 1.25% LP fee the LP even earns on top. The treasury is the identifiable loser: it was promised the fee on IMD leaving the pool to sellers and receives none of it on this route. Seams: execution x first principles (every step is a correct v4 operation, the end state contradicts the fee guarantee) and Economic Security 'legitimate features turned against the protocol'. The existing suite only tests a two-sided round trip that stays in range (testLiquidityAndDonationsAreNeverCharged), so the route is untested. This is inherent to the #909 pattern of charging swaps only; if the requester accepts it as a design limit, the README/launch notes should say so plainly ('sellers can avoid the fee with a range order'). Otherwise the fix is a design change the requester must choose: (a) enable afterRemoveLiquidity + afterRemoveLiquidityReturnDelta and charge feeNow() on IMD withdrawn in excess of the IMD the same position deposited (needs per-position IMD accounting and changes the mined permission mask 0x20cc), or (b) enable beforeAddLiquidity and, during OPENING_SECONDS, refuse positions whose range does not straddle the current tick (one-sided range orders) unless the sender is the factory, which also changes the mask. Either way getHookPermissions, HookFlags.SIMDTEST, launch.json permissions and the CREATE2 salt all move together.","line":61,"path":"src/SIMDTESTHook.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {SIMDTEST} from \"src/SIMDTEST.sol\";\nimport {SIMDTESTHook} from \"src/SIMDTESTHook.sol\";\nimport {HookFlags} from \"src/HookFlags.sol\";\nimport {PoolManager} from \"v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"v4-core/src/interfaces/IPoolManager.sol\";\nimport {IUnlockCallback} from \"v4-core/src/interfaces/callback/IUnlockCallback.sol\";\nimport {IHooks} from \"v4-core/src/interfaces/IHooks.sol\";\nimport {PoolKey} from \"v4-core/src/types/PoolKey.sol\";\nimport {Currency} from \"v4-core/src/types/Currency.sol\";\nimport {SwapParams, ModifyLiquidityParams} from \"v4-core/src/types/PoolOperation.sol\";\nimport {BalanceDelta} from \"v4-core/src/types/BalanceDelta.sol\";\nimport {TickMath} from \"v4-core/src/libraries/TickMath.sol\";\nimport {StateLibrary} from \"v4-core/src/libraries/StateLibrary.sol\";\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract Mock is ERC20 {\n    constructor() ERC20(\"IMD\", \"IMD\") {}\n\n    function mint(address to, uint256 a) external {\n        _mint(to, a);\n    }\n}\n\ncontract Router is IUnlockCallback {\n    IPoolManager immutable m;\n\n    constructor(IPoolManager m_) {\n        m = m_;\n    }\n\n    function swap(PoolKey memory k, SwapParams memory p) external returns (BalanceDelta) {\n        return abi.decode(m.unlock(abi.encode(true, msg.sender, k, abi.encode(p))), (BalanceDelta));\n    }\n\n    function liquidity(PoolKey memory k, ModifyLiquidityParams memory p) external returns (BalanceDelta) {\n        return abi.decode(m.unlock(abi.encode(false, msg.sender, k, abi.encode(p))), (BalanceDelta));\n    }\n\n    function unlockCallback(bytes calldata data) external returns (bytes memory) {\n        require(msg.sender == address(m));\n        (bool isSwap, address payer, PoolKey memory k, bytes memory payload) =\n            abi.decode(data, (bool, address, PoolKey, bytes));\n        BalanceDelta d;\n        if (isSwap) d = m.swap(k, abi.decode(payload, (SwapParams)), \"\");\n        else (d,) = m.modifyLiquidity(k, abi.decode(payload, (ModifyLiquidityParams)), \"\");\n        settle(k.currency0, payer, d.amount0());\n        settle(k.currency1, payer, d.amount1());\n        return abi.encode(d);\n    }\n\n    function settle(Currency c, address payer, int128 d) private {\n        if (d < 0) {\n            m.sync(c);\n            ERC20(Currency.unwrap(c)).transferFrom(payer, address(m), uint256(-int256(d)));\n            m.settle();\n        } else if (d > 0) {\n            m.take(c, payer, uint128(d));\n        }\n    }\n}\n\n/// @notice A SIMDTEST holder converts tokens to IMD through the launch pool without paying the\n/// hook's sell fee, by parking the tokens as single-sided liquidity above the price and letting\n/// buyers (who still pay) fill the range, then withdrawing IMD. Fails on the current hook.\ncontract RangeOrderBypassTest is Test {\n    using StateLibrary for IPoolManager;\n\n    address constant IMD = address(bytes20(hex\"d34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7\"));\n    uint160 constant Q96 = 79228162514264337593543950336;\n\n    PoolManager manager;\n    SIMDTEST token;\n    SIMDTESTHook hook;\n    Router router;\n    PoolKey key;\n    address seller = makeAddr(\"seller\");\n    address buyer = makeAddr(\"buyer\");\n\n    function setUp() public {\n        manager = new PoolManager(address(this));\n        vm.etch(IMD, address(new Mock()).code);\n        Mock(IMD).mint(address(this), 1e30);\n        Mock(IMD).mint(buyer, 1e30);\n        address tokenAt = address(uint160(IMD) - 1);\n        deployCodeTo(\"SIMDTEST.sol:SIMDTEST\", tokenAt);\n        token = SIMDTEST(tokenAt);\n        router = new Router(manager);\n        bytes memory creation = abi.encodePacked(type(SIMDTESTHook).creationCode, abi.encode(manager, tokenAt));\n        bytes32 h = keccak256(creation);\n        for (uint256 i;; ++i) {\n            address predicted =\n                address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), bytes32(i), h)))));\n            if (!HookFlags.matches(predicted, HookFlags.SIMDTEST)) continue;\n            bytes32 salt = bytes32(i);\n            address at;\n            assembly (\"memory-safe\") {\n                at := create2(0, add(creation, 0x20), mload(creation), salt)\n            }\n            hook = SIMDTESTHook(at);\n            break;\n        }\n        key = PoolKey(Currency.wrap(tokenAt), Currency.wrap(IMD), 12500, 60, IHooks(address(hook)));\n        manager.initialize(key, Q96);\n        ERC20(IMD).approve(address(router), type(uint256).max);\n        token.approve(address(router), type(uint256).max);\n        router.liquidity(key, ModifyLiquidityParams(-6000, 6000, 1e24, 0));\n        token.transfer(seller, 1e22);\n        vm.prank(seller);\n        token.approve(address(router), type(uint256).max);\n        vm.prank(buyer);\n        ERC20(IMD).approve(address(router), type(uint256).max);\n    }\n\n    function test_sellerConvertsTokenToIMDWithoutPayingTheSellFee() public {\n        // token is currency0, so a sell is zeroForOne and a buy is oneForZero.\n        uint256 amount = 1e22;\n        uint256 snapshot = vm.snapshotState();\n\n        // Route 1: ordinary exact-input sell at the opening rate (40% of gross IMD).\n        vm.prank(seller);\n        router.swap(key, SwapParams(true, -int256(amount), TickMath.MIN_SQRT_PRICE + 1));\n        uint256 viaSwap = ERC20(IMD).balanceOf(seller);\n        uint256 feeViaSwap = hook.collected();\n        assertGt(feeViaSwap, 0);\n        vm.revertToState(snapshot);\n\n        // Route 2: park the same tokens as a one-sided range just above the price. The seller\n        // deposits only SIMDTEST (position is entirely above the current tick).\n        int24 lower = 60;\n        int24 upper = 120;\n        uint160 sa = TickMath.getSqrtPriceAtTick(lower);\n        uint160 sb = TickMath.getSqrtPriceAtTick(upper);\n        // liquidity L such that amount0 = L * (sb - sa) / (sa * sb) * Q96 <= amount\n        uint256 L = amount * uint256(sa) / Q96 * uint256(sb) / (uint256(sb) - uint256(sa));\n        vm.prank(seller);\n        try router.liquidity(key, ModifyLiquidityParams(lower, upper, int256(L), 0)) {}\n        catch {\n            // A fix that gates one-sided liquidity during the fee window closes the route.\n            return;\n        }\n        assertEq(ERC20(IMD).balanceOf(seller), 0, \"no IMD was needed to open the range\");\n\n        // A buyer sweeps the price through the range; the buyer pays the hook fee on its own buy.\n        vm.prank(buyer);\n        router.swap(key, SwapParams(false, -int256(5e23), TickMath.getSqrtPriceAtTick(200)));\n        (, int24 tick,,) = IPoolManager(address(manager)).getSlot0(key.toId());\n        assertGt(tick, upper, \"the range was fully crossed\");\n\n        // Seller withdraws: the position is now entirely IMD.\n        uint256 collectedBeforeExit = hook.collected();\n        vm.prank(seller);\n        router.liquidity(key, ModifyLiquidityParams(lower, upper, -int256(L), 0));\n        uint256 viaRange = ERC20(IMD).balanceOf(seller);\n        uint256 feeOnExit = hook.collected() - collectedBeforeExit;\n\n        emit log_named_uint(\"IMD via taxed swap      \", viaSwap);\n        emit log_named_uint(\"IMD via range order      \", viaRange);\n        emit log_named_uint(\"hook fee on taxed swap   \", feeViaSwap);\n        emit log_named_uint(\"hook fee on range exit   \", feeOnExit);\n        // The guarantee under test: converting SIMDTEST into IMD through the launch pool pays the\n        // hook's sell-side rate on the IMD taken out. On this code the exit accrues nothing while\n        // the seller leaves with more IMD than the taxed sell paid out.\n        assertGt(viaRange, viaSwap);\n        assertGe(feeOnExit, viaRange * hook.feeNow() / 10_000, \"range exit paid no hook fee on IMD withdrawn\");\n    }\n}","reproduction":"Local PoolManager, SIMDTEST as currency0 and IMD as currency1 (same result for the other ordering), pool initialized at sqrtPrice 2^96 with 1e24 liquidity in [-6000, 6000], block.timestamp == openedAt so feeNow() == 4000. Seller holds 1e22 SIMDTEST and 0 IMD. Route A (taxed): seller swaps exact-input 1e22 SIMDTEST (zeroForOne, limit MIN_SQRT_PRICE+1) -> receives 5867062755291496472336 IMD, hook.collected() == 3911375170194330981556. Route B (untaxed): from the same state the seller calls modifyLiquidity with tickLower 60, tickUpper 120 and liquidityDelta 1e22*sa/2^96*sb/(sb-sa) ~ 3.3e24 (position funded with SIMDTEST only; seller's IMD balance stays 0). A buyer swaps exact-input 5e23 IMD (oneForZero, limit at tick 200), which moves the tick above 120 and pays its own buy fee. The seller removes the full position: hook.collected() is unchanged (fee on exit == 0) and the seller's IMD balance is 10218128280870472061189. Expected under the fee design: the seller's IMD exit pays feeNow() on the IMD withdrawn (~4087251312348188824475 at 40%). Actual: 0 to the treasury on the seller side, and the seller leaves with 74% more IMD than the taxed sell. Run test/scratch/RangeOrderBypass.t.sol: fails on this code with 'range exit paid no hook fee on IMD withdrawn: 0 < 4087251312348188824475'.","severity":"medium","snippet":"    function getHookPermissions() public pure returns (Hooks.Permissions memory p) {\n        p.beforeInitialize = true;\n        p.beforeSwap = true;\n        p.afterSwap = true;\n        p.beforeSwapReturnDelta = true;\n        p.afterSwapReturnDelta = true;\n    }","title":"Sell-side (and buy-side) hook fee is fully avoidable by converting through a one-sided liquidity position instead of a swap"}],"hash":"c6ed97e5349ed052696d4a6b214fbfcc1650883da9cba16905a0917aae05ff44","nodeId":"b857ed88-0db9-4620-bcb2-1ce027a726b7","outcome":"completed","summary":"Review complete. The findings file is written and no tracked file changed.\n\n**Outcome**\n\nOne finding, medium, with a proof test. The rest of my area holds.\n\n- **Hook fee is avoidable through liquidity positions.** The hook charges only in beforeSwap and afterSwap and enables no liquidity callbacks. A holder adds a SIMDTEST-only range just above spot, lets buyers fill it, and removes it as IMD with zero hook fee on their side. The mirror route lets buyers avoid the buy fee. Reproduced locally at the opening rate: the taxed sell of 1e22 SIMDTEST returned 5,867 IMD and paid 3,911 IMD of fee, while the range route returned 10,218 IMD and paid nothing. The treasury loses the sell-side revenue whenever a seller is willing to wait. The proof is at test/scratch/RangeOrderBypass.t.sol and fails on the current code. I flagged plainly that this is inherent to the #909 pattern, so the requester may accept it as a documented limit rather than change the permission mask.\n\n**What I verified holds**\n\n- Fee arithmetic in all four swap modes equals the rate on gross IMD, partial fills charge only the filled part, and the hook's claim mint cancels its credited delta inside every swap.\n- Sweep pays only the constant treasury. On a mainnet fork the treasury's withdrawer pulled plain-transferred IMD back out, so swept fees are not stranded. IMD is a LayerZero OFT with ordinary transfers and no blocklist or tax.\n- The README said no mainnet-fork run had ever succeeded. I ran the project's 12 fork tests against the live PoolManager at block 26146070 through a public RPC and all passed.\n\n**Not reached**\n\nPer-step rounding of the fill quote against SwapMath and TickMath. I traced its loop structure to match Pool.swap and relied on the 1500-run equality fuzz, and left the arithmetic to the math specialist.\n\nCoverage rows are written for all eight entry points plus five invariants in .imd-findings.json.","treeHash":null,"usage":{"cachedInputTokens":1949384,"inputTokens":450,"model":"claude-fable-5-1","outputTokens":56700,"runtime":"claude","turns":49,"wallClockMs":1104436}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"8b35536ee4821baa","findings":[],"hash":"d5b6e17fbfc5138a9e52fc262796251b431d0d611bb21c90c947d35bc81338a4","nodeId":"0f81905f-38f5-4f7c-b1dc-10e0368b7886","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/settings/organization/status-and-access before retrying.","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":"gpt-6-astra","outputTokens":0,"runtime":"codex","turns":4,"wallClockMs":605619}},{"artifacts":[],"attempt":2,"bundleHash":"a0335ddfd1ae44f29d424dc18ad24e5349f4639077857cf01254db65e2c229ab","device":"df74f6c887684f20","findings":[],"hash":"e1af35fe6c25b24aef0255f95ab993d1c37f9a66dfdebff5a724361d65fcfa9b","nodeId":"0f81905f-38f5-4f7c-b1dc-10e0368b7886","outcome":"completed","summary":"The deliverable is complete. Five new files under `test/`, nothing else touched, and no defect found to report.\n\n**Outcome**\n\n- `forge test` passes offline: 83 tests, 0 failures, 2 skips (the two fork suites skip without a fork URL, as the verifier requires).\n- Both fork suites pass against live mainnet state at block 26145519 via a public RPC, including the real PoolManager, the real IMD token and the real treasury contract.\n- The repo's own manifest checker and `forge fmt --check` pass.\n- I searched for defects adversarially and found none, so no `.imd-findings.json` was written. Every property I could think of held.\n\n**What I added** (building on the existing suite, not rewriting it)\n\n- `test/HookAdversarial.t.sol`: exact fee arithmetic per swap mode against the README formulas at opening, halfway and steady state plus a 1000-run fuzz; closed-form check of `feeNow` for every second; the one-second boundary at 3599 vs 3600; `Opened`, `FeeAccrued` and `Swept` events; constructor guards for zero or colliding addresses and for an address without the permission bits; the hook refusing a second pool and refusing to re-open; a 1500-run fuzz over amounts up to 2^255, random and invalid price limits and time, asserting any revert comes from the manager and never from the hook; fee independence from sender and hook data; liquidity and donations never charged; LP fees staying with LPs; outsider-pushed ERC-6909 claims forwarded to treasury without revert; partial fills across twelve uneven initialized ticks. Everything runs with IMD as currency0 and currency1.\n- `test/SpecifiedAmount.t.sol`: the hook's read-only fill quote compared to the manager's actual fill on a hookless pool, 1500 runs over random liquidity shapes, gaps, protocol fees, start prices, directions, exactness, limits and amounts, plus whole-bitmap-word gaps and `int256.min` requests. It agrees to the wei.\n- `test/InvariantExtended.t.sol`: a handler with all swap modes with and without limits, liquidity in and out, pool donations, loose IMD and claim donations to the hook, time and sweeps, classifying reverts so a hook-caused revert fails the run. Invariants cover claims backed and conserved, treasury the only recipient, monotone fee and collected, fixed clock and LP fee, zero manager deltas and zero reverts of any kind. Runs for both currency orderings at 96 runs by 48 depth.\n- `test/MainnetForkExtended.t.sol`: real IMD transfer semantics, the treasury contract as sweep recipient, partial fills in all modes, a token-only seed on the live manager, an hour of trading then sweep, and the live manager's rejections.\n- `test/helpers/Actors.sol`: the hook-data router, claim donor, pool donor and contract sweeper shared by the suites.\n\n**Still owed outside this task**: the README's statement that no successful live-fork run was recorded is now out of date, but README edits are outside my write scope. The fork command that worked is in my summary above for whoever updates it.","treeHash":"a4f7e8347e0ae37f6f4d8555ca8ada48ce0f3763","usage":{"cachedInputTokens":2842116,"inputTokens":610,"model":"claude-fable-5-1","outputTokens":83481,"runtime":"claude","turns":50,"wallClockMs":1363285}}],"verification":[{"checks":[{"durationMs":89748,"exitCode":0,"name":"build","output":"Compiling 88 files with Solc 0.8.26\nSolc 0.8.26 finished in 89.57s\nCompiler run successful!\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SIMDTESTHook.sol:25:48\n   │\n25 │     address public constant treasury = address(bytes20(hex\"3dd5f73dd1a4e62630fad3909673f130ad429985\"));\n   │                                                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes20' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SpecifiedAmount.sol:58:51\n   │\n58 │                 remaining = exactIn ? remaining + int256(input + lpAmount) : remaining - int256(output);\n   │                                                   ━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'int256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SpecifiedAmount.sol:58:90\n   │\n58 │                 remaining = exactIn ? remaining + int256(input + lpAmount) : remaining - int256(output);\n   │                                                                                          ━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'int256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SpecifiedAmount.sol:72:19\n   │\n72 │                 ? uint256(remaining - params.amountSpecified)\n   │                   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SpecifiedAmount.sol:73:19\n   │\n73 │                 : uint256(params.amountSpecified - remaining);\n   │                   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SIMDTESTHook.sol:29:31\n   │\n29 │         Currency.wrap(address(bytes20(hex\"d34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7\")));\n   │                               ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes20' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/SIMDTESTHook.sol:89:29\n   │\n89 │         if (!initialized || block.timestamp <= openedAt) return OPENING_FEE;\n   │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/SIMDTESTHook.sol:91:13\n   │\n91 │         if (elapsed >= OPENING_SECONDS) return STEADY_FEE;\n   │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:108:35\n    │\n108 │             requested = exactIn ? uint256(-params.amountSpecified) : uint256(params.amountSpecified);\n    │                                   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:108:70\n    │\n108 │             requested = exactIn ? uint256(-params.amountSpecified) : uint256(params.amountSpecified);\n    │                                                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:113:25\n    │\n113 │             requested > uint256(uint128(type(int128).max)) ? uint256(uint128(type(int128).max)) : requested;\n    │                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:113:33\n    │\n113 │             requested > uint256(uint128(type(int128).max)) ? uint256(uint128(type(int128).max)) : requested;\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:113:62\n    │\n113 │             requested > uint256(uint128(type(int128).max)) ? uint256(uint128(type(int128).max)) : requested;\n    │                                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:113:70\n    │\n113 │             requested > uint256(uint128(type(int128).max)) ? uint256(uint128(type(int128).max)) : requested;\n    │                                                                      ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:116:44\n    │\n116 │         quote.amountSpecified = exactIn ? -int256(budget - reserve) : int256(budget + reserve);\n    │                                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:116:71\n    │\n116 │         quote.amountSpecified = exactIn ? -int256(budget - reserve) : int256(budget + reserve);\n    │                                                                       ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:126:63\n    │\n126 │         return (IHooks.beforeSwap.selector, toBeforeSwapDelta(int128(int256(fee)), 0), 0);\n    │                                                               ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:126:70\n    │\n126 │         return (IHooks.beforeSwap.selector, toBeforeSwapDelta(int128(int256(fee)), 0), 0);\n    │                                                                      ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:143:36\n    │\n143 │         uint256 fee = amount < 0 ? uint256(-amount) * rate / (10_000 - rate) : uint256(amount) * rate / 10_000;\n    │                                    ━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:143:80\n    │\n143 │         uint256 fee = amount < 0 ? uint256(-amount) * rate / (10_000 - rate) : uint256(amount) * rate / 10_000;\n    │                                                                                ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:145:44\n    │\n145 │         return (IHooks.afterSwap.selector, int128(int256(fee)));\n    │                                            ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:145:51\n    │\n145 │         return (IHooks.afterSwap.selector, int128(int256(fee)));\n    │                                                   ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/SIMDTESTHook.sol:152:9\n    │\n152 │         emit FeeAccrued(fee);\n    │         ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `sweeping` is updated\n    ╭▸ src/SIMDTESTHook.sol:164:29\n    │\n164 │         amount = abi.decode(poolManager.unlock(\"\"), (uint256));\n    │                             ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/SIMDTESTHook.sol:169:9\n    │\n169 │         emit Swept(amount);\n    │         ━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\n","passed":true},{"durationMs":1233,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/MainnetForkExtended.t.sol:MainnetForkExtendedTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 557.91µs (0.00ns CPU time)\n\nRan 1 test for test/MainnetFork.t.sol:MainnetForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 487.96µs (0.00ns CPU time)\n\nRan 1 test for test/Hook.t.sol:OppositeOrderingTest\n[PASS] testBothDirectionsAndExactnessWithIMDCurrency0() (gas: 1279518)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.66ms (1.43ms CPU time)\n\nRan 2 tests for test/Hook.t.sol:FreshManagerTest\n[PASS] testEmptyPoolChargesNothingInAllModes() (gas: 2734753)\n[PASS] testTokenOnlySeedNeedsNoPrefundedIMD() (gas: 697578)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 27.69ms (4.36ms CPU time)\n\nRan 20 tests for test/Hook.t.sol:HookTest\n[PASS] testAllSwapModesOpeningAndSteady() (gas: 2399554)\n[PASS] testFeeScheduleBoundaries() (gas: 92657)\n[PASS] testFuzzFeeOnRealSwaps(bool,bool,uint96,uint16) (runs: 1000, μ: 350108, ~: 349357)\n[PASS] testFuzzPartialFills(bool,bool,uint8,uint16) (runs: 256, μ: 375318, ~: 374847)\n[PASS] testFuzzScheduleMonotonic(uint32,uint32) (runs: 1000, μ: 33618, ~: 33469)\n[PASS] testHugeRequestedInputOnlyChargesTheSmallFilledAmount() (gas: 345514)\n[PASS] testImmutableConfigurationAndPermissions() (gas: 44119)\n[PASS] testInvalidInitializationAndNoReset() (gas: 14667282)\n[PASS] testInvalidSwapInputsAreManagerFailures() (gas: 108865)\n[PASS] testNoAdminPathsAndRuntimeLimits() (gas: 2036025)\n[PASS] testProtocolFeesDoNotDesynchronizePartialFillQuote() (gas: 1555720)\n[PASS] testReentryAndUnlockedSweepAreHarmless() (gas: 573391)\n[PASS] testRevertingSettlementRollsBackFeesAndPrice() (gas: 249958)\n[PASS] testRevertingSweepPreservesClaimsAndDoesNotBlockSwaps() (gas: 925356)\n[PASS] testSweepPermissionlessAndConservesAllFees() (gas: 896951)\n[PASS] testTickCrossingsAndLiquidityGaps() (gas: 1732813)\n[PASS] testTinySwapsDoNotConsumeEntireInputAsFee() (gas: 1104650)\n[PASS] testUnauthorizedCallbacks() (gas: 147630)\n[PASS] testWrongPermissionBitsRefuseDeployment() (gas: 2746623)\n[PASS] testZeroTimestampInitializationDoesNotResetClock() (gas: 14524506)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 265.03ms (375.84ms CPU time)\n\nRan 4 tests for test/SIMDTEST.t.sol:SIMDTESTTest\n[PASS] testAllowanceAndFailureAreAtomic() (gas: 300366)\n[PASS] testFuzzTransfersConserveSupply(uint256) (runs: 1000, μ: 112167, ~: 112421)\n[PASS] testLaunchSupplyAndMetadata() (gas: 35050)\n[PASS] testNoPrivilegedEntrypoints() (gas: 189660)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 360.11ms (354.14ms CPU time)\n\nRan 24 tests for test/HookAdversarial.t.sol:HookAdversarialTest\n[PASS] testCollectedIsTheSumOfPerSwapFeesAcrossTheSchedule() (gas: 2011470)\n[PASS] testConstructorRejectsAnAddressWithoutThePermissionBits() (gas: 9908)\n[PASS] testConstructorRejectsMissingOrCollidingAddresses() (gas: 6848)\n[PASS] testEventsOpenedAccruedSwept() (gas: 14800148)\n[PASS] testExactFeesAtOpening() (gas: 1482686)\n[PASS] testExactFeesHalfway() (gas: 1497227)\n[PASS] testExactFeesSteadyState() (gas: 1494594)\n[PASS] testFeeIsIndependentOfSenderAndHookData() (gas: 1338722)\n[PASS] testFeeNowRoundsDownAtEveryStep() (gas: 7044618)\n[PASS] testFreshHookRejectsForeignPoolsWithClearReasons() (gas: 14468427)\n[PASS] testFreshHookReportsOpeningRateAndNothingPending() (gas: 14468136)\n[PASS] testFuzzExactFeesOnFullFills(bool,bool,uint72,uint16) (runs: 1000, μ: 373682, ~: 374722)\n[PASS] testFuzzFeeNowMatchesClosedForm(uint64) (runs: 2000, μ: 20779, ~: 20720)\n[PASS] testFuzzHookNeverCausesASwapRevert(bool,bool,uint256,uint160,bool,uint32) (runs: 1500, μ: 232371, ~: 278418)\n[PASS] testFuzzPartialFillsAcrossManyInitializedTicks(bool,bool,uint8,uint16) (runs: 256, μ: 2865768, ~: 2858193)\n[PASS] testGrossFortyPercentIsTwoThirdsOfNet() (gas: 367799)\n[PASS] testHookCannotBeSharedWithASecondPool() (gas: 1385272)\n[PASS] testHookNeverHoldsLaunchTokenClaims() (gas: 1236194)\n[PASS] testLiquidityAndDonationsAreNeverCharged() (gas: 1137878)\n[PASS] testLpFeesStayWithLiquidityProvidersNotTheHook() (gas: 546348)\n[PASS] testManagerIMDAlwaysBacksTheClaims() (gas: 1944578)\n[PASS] testOneSecondBoundaryChangesTheCharge() (gas: 705475)\n[PASS] testSweepByContractCallerPaysOnlyTreasury() (gas: 610276)\n[PASS] testUnexpectedClaimsAreForwardedToTreasuryWithoutRevert() (gas: 966767)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 360.14ms (993.41ms CPU time)\n\nRan 5 tests for test/SpecifiedAmount.t.sol:SpecifiedAmountTest\n[PASS] testFuzzQuoteEqualsManagerFill(uint256,uint8,bool,bool,uint96,uint16,bool,uint16,uint16,int16) (runs: 1500, μ: 987744, ~: 916622)\n[PASS] testQuoteIsZeroOnAnEmptyPoolAndUninitializedPool() (gas: 1658391)\n[PASS] testQuoteIsZeroWhenTheManagerWouldRejectTheLimit() (gas: 934329)\n[PASS] testQuoteOnRequestsFarBeyondInt128() (gas: 1368670)\n[PASS] testQuoteWalksGapsAndWholeBitmapWords() (gas: 2761768)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 360.27ms (371.29ms CPU time)\n\nRan 24 tests for test/HookAdversarial.t.sol:HookAdversarialIMDFirstTest\n[PASS] testCollectedIsTheSumOfPerSwapFeesAcrossTheSchedule() (gas: 2012295)\n[PASS] testConstructorRejectsAnAddressWithoutThePermissionBits() (gas: 9908)\n[PASS] testConstructorRejectsMissingOrCollidingAddresses() (gas: 6848)\n[PASS] testEventsOpenedAccruedSwept() (gas: 9058772)\n[PASS] testExactFeesAtOpening() (gas: 1484041)\n[PASS] testExactFeesHalfway() (gas: 1498590)\n[PASS] testExactFeesSteadyState() (gas: 1496435)\n[PASS] testFeeIsIndependentOfSenderAndHookData() (gas: 1360302)\n[PASS] testFeeNowRoundsDownAtEveryStep() (gas: 7044618)\n[PASS] testFreshHookRejectsForeignPoolsWithClearReasons() (gas: 8716332)\n[PASS] testFreshHookReportsOpeningRateAndNothingPending() (gas: 8716197)\n[PASS] testFuzzExactFeesOnFullFills(bool,bool,uint72,uint16) (runs: 1000, μ: 373820, ~: 370664)\n[PASS] testFuzzFeeNowMatchesClosedForm(uint64) (runs: 1000, μ: 20776, ~: 20720)\n[PASS] testFuzzHookNeverCausesASwapRevert(bool,bool,uint256,uint160,bool,uint32) (runs: 1000, μ: 228529, ~: 282152)\n[PASS] testFuzzPartialFillsAcrossManyInitializedTicks(bool,bool,uint8,uint16) (runs: 1000, μ: 2866111, ~: 2860949)\n[PASS] testGrossFortyPercentIsTwoThirdsOfNet() (gas: 359855)\n[PASS] testHookCannotBeSharedWithASecondPool() (gas: 1385272)\n[PASS] testHookNeverHoldsLaunchTokenClaims() (gas: 1237478)\n[PASS] testLiquidityAndDonationsAreNeverCharged() (gas: 1137878)\n[PASS] testLpFeesStayWithLiquidityProvidersNotTheHook() (gas: 556961)\n[PASS] testManagerIMDAlwaysBacksTheClaims() (gas: 1946503)\n[PASS] testOneSecondBoundaryChangesTheCharge() (gas: 726715)\n[PASS] testSweepByContractCallerPaysOnlyTreasury() (gas: 604538)\n[PASS] testUnexpectedClaimsAreForwardedToTreasuryWithoutRevert() (gas: 977395)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 360.31ms (1.06s CPU time)\n\nRan 1 test for test/Invariant.t.sol:HookInvariantTest\n[PASS] invariantFeesRemainBackedAndOnlyTreasuryReceives() (runs: 64, calls: 2048, reverts: 0)\n\n╭-------------+----------+-------+---------+----------╮\n| Contract    | Selector | Calls | Reverts | Discards |\n+=====================================================+\n| SwapHandler | advance  | 694   | 0       | 0        |\n|-------------+----------+-------+---------+----------|\n| SwapHandler | sweep    | 668   | 0       | 0        |\n|-------------+----------+-------+---------+----------|\n| SwapHandler | trade    | 686   | 0       | 0        |\n╰-------------+----------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 408.04ms (381.17ms CPU time)\n\nRan 1 test for test/InvariantExtended.t.sol:ExtendedInvariantIMDFirstTest\n[PASS]\nExtendedInvariantIMDFirstTest invariants:\n[PASS] invariantFeesAreBackedAndReachOnlyTreasury\n[PASS] invariantHookNeverRevertsAndManagerSettles\n[PASS] invariantScheduleClockAndPoolTermsAreFixed\n ExtendedInvariantIMDFirstTest invariants (runs: 96, calls: 4608, reverts: 0)\n\n╭-----------------+-----------------+-------+---------+----------╮\n| Contract        | Selector        | Calls | Reverts | Discards |\n+================================================================+\n| ExtendedHandler | addLiquidity    | 430   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | advance         | 434   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | donate          | 466   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | donateClaims    | 469   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | donateLoose     | 506   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | removeLiquidity | 445   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | swap            | 1392  | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | sweep           | 466   | 0       | 0        |\n╰-----------------+-----------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.04s (1.04s CPU time)\n\nRan 1 test for test/InvariantExtended.t.sol:ExtendedInvariantIMDSecondTest\n[PASS]\nExtendedInvariantIMDSecondTest invariants:\n[PASS] invariantFeesAreBackedAndReachOnlyTreasury\n[PASS] invariantHookNeverRevertsAndManagerSettles\n[PASS] invariantScheduleClockAndPoolTermsAreFixed\n ExtendedInvariantIMDSecondTest invariants (runs: 96, calls: 4608, reverts: 0)\n\n╭-----------------+-----------------+-------+---------+----------╮\n| Contract        | Selector        | Calls | Reverts | Discards |\n+================================================================+\n| ExtendedHandler | addLiquidity    | 430   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | advance         | 434   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | donate          | 466   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | donateClaims    | 469   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | donateLoose     | 506   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | removeLiquidity | 445   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | swap            | 1392  | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | sweep           | 466   | 0       | 0        |\n╰-----------------+-----------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.12s (1.08s CPU time)\n\nRan 12 test suites in 1.12s (4.31s CPU time): 83 tests passed, 0 failed, 2 skipped (85 total tests)\n","passed":true},{"durationMs":74,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"SIMDTEST.approve(address,uint256)\",\"SIMDTEST.transfer(address,uint256)\",\"SIMDTEST.transferFrom(address,address,uint256)\",\"SIMDTESTHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"SIMDTESTHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"SIMDTESTHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"SIMDTESTHook.sweep()\",\"SIMDTESTHook.unlockCallback(bytes)\"],\"files\":{\".gitignore\":3,\"DEPENDENCIES.md\":8,\"LICENSE\":25,\"README.md\":95,\"docs/PROVENANCE.md\":3,\"docs/REFERENCE_LICENSE\":24,\"docs/SECURITY_REVIEW.md\":31,\"docs/SOURCE_SHA256SUMS.txt\":89,\"docs/VERIFICATION.md\":29,\"foundry.toml\":21,\"launch.json\":30,\"remappings.txt\":4,\"script/HookDeployer.sol\":33,\"src/HookFlags.sol\":30,\"src/SIMDTEST.sol\":11,\"src/SIMDTESTHook.sol\":181,\"src/SpecifiedAmount.sol\":101,\"test/Hook.t.sol\":355,\"test/HookAdversarial.t.sol\":496,\"test/Invariant.t.sol\":92,\"test/InvariantExtended.t.sol\":302,\"test/MainnetFork.t.sol\":68,\"test/MainnetForkExtended.t.sol\":154,\"test/SIMDTEST.t.sol\":74,\"test/SpecifiedAmount.t.sol\":180,\"test/helpers/Actors.sol\":111,\"test/helpers/HookFixture.sol\":123,\"test/helpers/TestRouter.sol\":66,\"test/mocks/MockERC20.sol\":36,\"tools/check_launch.py\":31},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"46812928ce69805b1f55bd936f56664f2bd22c608ec01b254e126621a1d4ddb6","verifiedTreeHash":"3f995356240ef333be30b327fbf206ee437449a9","verifierVersion":"0.1.0+ad90ce4c"},{"checks":[{"durationMs":35568,"exitCode":0,"name":"build","output":"Compiling 83 files with Solc 0.8.26\nSolc 0.8.26 finished in 35.42s\nCompiler run successful!\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SIMDTESTHook.sol:25:48\n   │\n25 │     address public constant treasury = address(bytes20(hex\"3dd5f73dd1a4e62630fad3909673f130ad429985\"));\n   │                                                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes20' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SIMDTESTHook.sol:29:31\n   │\n29 │         Currency.wrap(address(bytes20(hex\"d34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7\")));\n   │                               ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes20' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SpecifiedAmount.sol:58:51\n   │\n58 │                 remaining = exactIn ? remaining + int256(input + lpAmount) : remaining - int256(output);\n   │                                                   ━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'int256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SpecifiedAmount.sol:58:90\n   │\n58 │                 remaining = exactIn ? remaining + int256(input + lpAmount) : remaining - int256(output);\n   │                                                                                          ━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'int256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SpecifiedAmount.sol:72:19\n   │\n72 │                 ? uint256(remaining - params.amountSpecified)\n   │                   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SpecifiedAmount.sol:73:19\n   │\n73 │                 : uint256(params.amountSpecified - remaining);\n   │                   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/SIMDTESTHook.sol:89:29\n   │\n89 │         if (!initialized || block.timestamp <= openedAt) return OPENING_FEE;\n   │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/SIMDTESTHook.sol:91:13\n   │\n91 │         if (elapsed >= OPENING_SECONDS) return STEADY_FEE;\n   │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:108:35\n    │\n108 │             requested = exactIn ? uint256(-params.amountSpecified) : uint256(params.amountSpecified);\n    │                                   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:108:70\n    │\n108 │             requested = exactIn ? uint256(-params.amountSpecified) : uint256(params.amountSpecified);\n    │                                                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:113:25\n    │\n113 │             requested > uint256(uint128(type(int128).max)) ? uint256(uint128(type(int128).max)) : requested;\n    │                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:113:33\n    │\n113 │             requested > uint256(uint128(type(int128).max)) ? uint256(uint128(type(int128).max)) : requested;\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:113:62\n    │\n113 │             requested > uint256(uint128(type(int128).max)) ? uint256(uint128(type(int128).max)) : requested;\n    │                                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:113:70\n    │\n113 │             requested > uint256(uint128(type(int128).max)) ? uint256(uint128(type(int128).max)) : requested;\n    │                                                                      ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:116:44\n    │\n116 │         quote.amountSpecified = exactIn ? -int256(budget - reserve) : int256(budget + reserve);\n    │                                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:116:71\n    │\n116 │         quote.amountSpecified = exactIn ? -int256(budget - reserve) : int256(budget + reserve);\n    │                                                                       ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:126:63\n    │\n126 │         return (IHooks.beforeSwap.selector, toBeforeSwapDelta(int128(int256(fee)), 0), 0);\n    │                                                               ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:126:70\n    │\n126 │         return (IHooks.beforeSwap.selector, toBeforeSwapDelta(int128(int256(fee)), 0), 0);\n    │                                                                      ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:143:36\n    │\n143 │         uint256 fee = amount < 0 ? uint256(-amount) * rate / (10_000 - rate) : uint256(amount) * rate / 10_000;\n    │                                    ━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:143:80\n    │\n143 │         uint256 fee = amount < 0 ? uint256(-amount) * rate / (10_000 - rate) : uint256(amount) * rate / 10_000;\n    │                                                                                ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:145:44\n    │\n145 │         return (IHooks.afterSwap.selector, int128(int256(fee)));\n    │                                            ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:145:51\n    │\n145 │         return (IHooks.afterSwap.selector, int128(int256(fee)));\n    │                                                   ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/SIMDTESTHook.sol:152:9\n    │\n152 │         emit FeeAccrued(fee);\n    │         ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `sweeping` is updated\n    ╭▸ src/SIMDTESTHook.sol:164:29\n    │\n164 │         amount = abi.decode(poolManager.unlock(\"\"), (uint256));\n    │                             ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/SIMDTESTHook.sol:169:9\n    │\n169 │         emit Swept(amount);\n    │         ━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\n","passed":true},{"durationMs":415,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/MainnetFork.t.sol:MainnetForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 397.85µs (0.00ns CPU time)\n\nRan 1 test for test/Hook.t.sol:OppositeOrderingTest\n[PASS] testBothDirectionsAndExactnessWithIMDCurrency0() (gas: 1279518)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.51ms (903.49µs CPU time)\n\nRan 2 tests for test/Hook.t.sol:FreshManagerTest\n[PASS] testEmptyPoolChargesNothingInAllModes() (gas: 2734753)\n[PASS] testTokenOnlySeedNeedsNoPrefundedIMD() (gas: 697578)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 28.58ms (5.81ms CPU time)\n\nRan 20 tests for test/Hook.t.sol:HookTest\n[PASS] testAllSwapModesOpeningAndSteady() (gas: 2399554)\n[PASS] testFeeScheduleBoundaries() (gas: 92657)\n[PASS] testFuzzFeeOnRealSwaps(bool,bool,uint96,uint16) (runs: 1000, μ: 350202, ~: 349555)\n[PASS] testFuzzPartialFills(bool,bool,uint8,uint16) (runs: 256, μ: 376234, ~: 374975)\n[PASS] testFuzzScheduleMonotonic(uint32,uint32) (runs: 1000, μ: 33631, ~: 33469)\n[PASS] testHugeRequestedInputOnlyChargesTheSmallFilledAmount() (gas: 345514)\n[PASS] testImmutableConfigurationAndPermissions() (gas: 44119)\n[PASS] testInvalidInitializationAndNoReset() (gas: 14667282)\n[PASS] testInvalidSwapInputsAreManagerFailures() (gas: 108865)\n[PASS] testNoAdminPathsAndRuntimeLimits() (gas: 2036025)\n[PASS] testProtocolFeesDoNotDesynchronizePartialFillQuote() (gas: 1555720)\n[PASS] testReentryAndUnlockedSweepAreHarmless() (gas: 573391)\n[PASS] testRevertingSettlementRollsBackFeesAndPrice() (gas: 249958)\n[PASS] testRevertingSweepPreservesClaimsAndDoesNotBlockSwaps() (gas: 925356)\n[PASS] testSweepPermissionlessAndConservesAllFees() (gas: 896951)\n[PASS] testTickCrossingsAndLiquidityGaps() (gas: 1732813)\n[PASS] testTinySwapsDoNotConsumeEntireInputAsFee() (gas: 1104650)\n[PASS] testUnauthorizedCallbacks() (gas: 147630)\n[PASS] testWrongPermissionBitsRefuseDeployment() (gas: 2746623)\n[PASS] testZeroTimestampInitializationDoesNotResetClock() (gas: 14524506)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 56.05ms (144.94ms CPU time)\n\nRan 4 tests for test/SIMDTEST.t.sol:SIMDTESTTest\n[PASS] testAllowanceAndFailureAreAtomic() (gas: 300366)\n[PASS] testFuzzTransfersConserveSupply(uint256) (runs: 1000, μ: 112125, ~: 112409)\n[PASS] testLaunchSupplyAndMetadata() (gas: 35050)\n[PASS] testNoPrivilegedEntrypoints() (gas: 189660)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 56.05ms (56.27ms CPU time)\n\nRan 1 test for test/Invariant.t.sol:HookInvariantTest\n[PASS] invariantFeesRemainBackedAndOnlyTreasuryReceives() (runs: 64, calls: 2048, reverts: 0)\n\n╭-------------+----------+-------+---------+----------╮\n| Contract    | Selector | Calls | Reverts | Discards |\n+=====================================================+\n| SwapHandler | advance  | 680   | 0       | 0        |\n|-------------+----------+-------+---------+----------|\n| SwapHandler | sweep    | 714   | 0       | 0        |\n|-------------+----------+-------+---------+----------|\n| SwapHandler | trade    | 654   | 0       | 0        |\n╰-------------+----------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 314.69ms (291.33ms CPU time)\n\nRan 6 test suites in 316.19ms (458.28ms CPU time): 28 tests passed, 0 failed, 1 skipped (29 total tests)\n","passed":true},{"durationMs":62,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"SIMDTEST.approve(address,uint256)\",\"SIMDTEST.transfer(address,uint256)\",\"SIMDTEST.transferFrom(address,address,uint256)\",\"SIMDTESTHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"SIMDTESTHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"SIMDTESTHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"SIMDTESTHook.sweep()\",\"SIMDTESTHook.unlockCallback(bytes)\"],\"files\":{\".gitignore\":3,\"DEPENDENCIES.md\":8,\"LICENSE\":25,\"README.md\":95,\"docs/PROVENANCE.md\":3,\"docs/REFERENCE_LICENSE\":24,\"docs/SECURITY_REVIEW.md\":31,\"docs/SOURCE_SHA256SUMS.txt\":89,\"docs/VERIFICATION.md\":29,\"foundry.toml\":21,\"launch.json\":30,\"remappings.txt\":4,\"script/HookDeployer.sol\":33,\"src/HookFlags.sol\":30,\"src/SIMDTEST.sol\":11,\"src/SIMDTESTHook.sol\":181,\"src/SpecifiedAmount.sol\":101,\"test/Hook.t.sol\":355,\"test/Invariant.t.sol\":92,\"test/MainnetFork.t.sol\":68,\"test/SIMDTEST.t.sol\":74,\"test/helpers/HookFixture.sol\":123,\"test/helpers/TestRouter.sol\":66,\"test/mocks/MockERC20.sol\":36,\"tools/check_launch.py\":31},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":2698,"exitCode":0,"name":"slither","output":"[medium/high] incorrect-equality at src/SIMDTESTHook.sol:148: SIMDTESTHook._accrue(uint256) (src/SIMDTESTHook.sol#148-153) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/SIMDTESTHook.sol:95: SIMDTESTHook.beforeSwap(address,PoolKey,SwapParams,bytes) (src/SIMDTESTHook.sol#95-127) uses a dangerous strict equality:\n[medium/medium] reentrancy-no-eth at src/SIMDTESTHook.sol:161: Reentrancy in SIMDTESTHook.sweep() (src/SIMDTESTHook.sol#161-170):\n[medium/medium] unused-return at src/SpecifiedAmount.sol:24: SpecifiedAmount.filled(IPoolManager,PoolKey,SwapParams) (src/SpecifiedAmount.sol#24-75) ignores return value by (None,net) = manager.getTickLiquidity(id,next) (src/SpecifiedAmount.sol#62)\n[low/medium] reentrancy-events at src/SIMDTESTHook.sol:148: Reentrancy in SIMDTESTHook._accrue(uint256) (src/SIMDTESTHook.sol#148-153):\n[low/medium] reentrancy-events at src/SIMDTESTHook.sol:161: Reentrancy in SIMDTESTHook.sweep() (src/SIMDTESTHook.sol#161-170):\n[low/medium] timestamp at src/SIMDTESTHook.sol:88: SIMDTESTHook.feeNow() (src/SIMDTESTHook.sol#88-93) uses timestamp for comparisons\n[low/medium] timestamp at src/SIMDTESTHook.sol:95: SIMDTESTHook.beforeSwap(address,PoolKey,SwapParams,bytes) (src/SIMDTESTHook.sol#95-127) uses timestamp for comparisons\n[low/medium] timestamp at src/SIMDTESTHook.sol:148: SIMDTESTHook._accrue(uint256) (src/SIMDTESTHook.sol#148-153) uses timestamp for comparisons","passed":true},{"durationMs":450,"exitCode":0,"name":"aderyn","output":"[high] reentrancy-state-change at src/SIMDTESTHook.sol:164: Reentrancy: State change after external call\n[low] internal-function-used-once at src/HookFlags.sol:23: Internal Function Used Only Once\n[low] large-numeric-literal at src/SIMDTEST.sol:9: Large Numeric Literal (7 places)\n[low] literal-instead-of-constant at src/SIMDTESTHook.sol:114: Literal Instead of Constant (8 places)\n[low] require-revert-in-loop at src/SpecifiedAmount.sol:44: Loop Contains `require`/`revert`\n[low] unsafe-erc20-operation at src/SIMDTESTHook.sol:166: Unsafe ERC20 Operation","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"969f52ef760b9a341b1633f04459042b3000699a911030ec77ba004c83b3ca7d","verifiedTreeHash":"509aaa03406263f076e7ea556214eca42d7938ee","verifierVersion":"0.1.0+ad90ce4c"},{"checks":[{"durationMs":3435,"exitCode":0,"name":"build","output":"Compiling 86 files with Solc 0.8.26\nSolc 0.8.26 finished in 3.27s\nCompiler run successful!\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/SIMDTESTHook.sol:53:40\n   │\n53 │     constructor(IPoolManager manager_, address token_) {\n   │                                        ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/SIMDTESTHook.sol:99:29\n   │\n99 │         if (!initialized || block.timestamp <= openedAt) return OPENING_FEE_BPS;\n   │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/SIMDTESTHook.sol:101:13\n    │\n101 │         if (elapsed >= DECAY_SECONDS) return STANDING_FEE_BPS;\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/SIMDTESTHook.sol:114:9\n    │\n114 │         nonReentrant\n    │         ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/SIMDTESTHook.sol:206:13\n    │\n206 │             emit FeeAccrued(fee, rate, false);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/SIMDTESTHook.sol:209:13\n    │\n209 │             emit FeeAccrued(fee, rate, true);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:125:25\n    │\n125 │         fee = _min(fee, uint256(uint128(type(int128).max)));\n    │                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:125:33\n    │\n125 │         fee = _min(fee, uint256(uint128(type(int128).max)));\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:136:64\n    │\n136 │             probe.amountSpecified = !exactInput && requested > uint256(type(int256).max) - fee\n    │                                                                ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:138:44\n    │\n138 │                 : params.amountSpecified + int256(fee);\n    │                                            ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:145:63\n    │\n145 │         return (IHooks.beforeSwap.selector, toBeforeSwapDelta(int128(int256(fee)), 0), 0);\n    │                                                               ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:145:70\n    │\n145 │         return (IHooks.beforeSwap.selector, toBeforeSwapDelta(int128(int256(fee)), 0), 0);\n    │                                                                      ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/SIMDTESTHook.sol:154:32\n    │\n154 │     ) external onlyPoolManager nonReentrant returns (bytes4, int128) {\n    │                                ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:164:44\n    │\n164 │         return (IHooks.afterSwap.selector, int128(int256(fee)));\n    │                                            ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:164:51\n    │\n164 │         return (IHooks.afterSwap.selector, int128(int256(fee)));\n    │                                                   ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/SIMDTESTHook.sol:188:9\n    │\n188 │         emit Swept(msg.sender, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:178:31\n    │\n178 │         claims = _min(claims, uint256(uint128(type(int128).max)));\n    │                               ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:178:39\n    │\n178 │         claims = _min(claims, uint256(uint128(type(int128).max)));\n    │                                       ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/SIMDTESTHook.sol:181:13\n    │\n181 │             poolManager.unlock(abi.encode(claims));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:220:40\n    │\n220 │             if (reason.length != 36 || bytes4(reason) != SwapQuote.selector) {\n    │                                        ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'bytes4' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:237:27\n    │\n237 │         uint256 maximum = uint256(uint128(type(int128).max));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:237:35\n    │\n237 │         uint256 maximum = uint256(uint128(type(int128).max));\n    │                                   ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:242:28\n    │\n242 │         return value < 0 ? uint256(-(value + 1)) + 1 : uint256(value);\n    │                            ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:242:56\n    │\n242 │         return value < 0 ? uint256(-(value + 1)) + 1 : uint256(value);\n    │                                                        ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\n","passed":true},{"durationMs":1383,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/MainnetFork.t.sol:MainnetForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 410.50µs (0.00ns CPU time)\n\nRan 3 tests for test/Swaps.t.sol:PairCurrency0EmptyAndSingleSidedTest\n[PASS] test_emptyPoolChargesNothingInEveryMode() (gas: 913604)\n[PASS] test_firstBuyWithZeroIMDInventoryUsesClaims() (gas: 819325)\n[PASS] test_firstExactOutputBuyWithZeroIMDInventoryUsesClaims() (gas: 706862)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 5.97ms (4.39ms CPU time)\n\nRan 4 tests for test/Token.t.sol:TokenTest\n[PASS] testFuzz_transfersConserveSupply(uint256) (runs: 1000, μ: 91328, ~: 91423)\nLogs:\n  Bound result 65667129021284927494590601\n\n[PASS] test_allowanceAndInsufficientFunds() (gas: 208944)\n[PASS] test_fullSupplyBelongsToDeployer() (gas: 52752)\n[PASS] test_noMintAdminOrUpgradeEntrypoints() (gas: 177114)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 12.52ms (13.04ms CPU time)\n\nRan 3 tests for test/Swaps.t.sol:EmptyAndSingleSidedTest\n[PASS] test_emptyPoolChargesNothingInEveryMode() (gas: 913510)\n[PASS] test_firstBuyWithZeroIMDInventoryUsesClaims() (gas: 800633)\n[PASS] test_firstExactOutputBuyWithZeroIMDInventoryUsesClaims() (gas: 696161)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 22.33ms (2.18ms CPU time)\n\nRan 9 tests for test/Hook.t.sol:HookTest\n[PASS] testFuzz_scheduleIsMonotoneAndBounded(uint64,uint64) (runs: 1000, μ: 150046, ~: 150100)\nLogs:\n  Bound result 242\n\n[PASS] test_allCallbacksAuthenticateCaller() (gas: 180655)\n[PASS] test_constantsInitializationAndPermissions() (gas: 328817)\n[PASS] test_constructorRejectsInvalidInputsAndUnminedAddress() (gas: 7576)\n[PASS] test_creationAndRuntimeLimitsAndNoForbiddenOpcodes() (gas: 5112746)\n[PASS] test_initializationAtTimestampZero() (gas: 119090)\n[PASS] test_noAdminOrUpgradeEntrypoints() (gas: 171589)\n[PASS] test_rejectsWrongPoolTerms() (gas: 268385)\n[PASS] test_scheduleBoundaries() (gas: 191811)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 94.29ms (92.73ms CPU time)\n\nRan 22 tests for test/Swaps.t.sol:PairCurrency0SwapsTest\n[PASS] testFuzz_fourModesAtAnyFee(bool,bool,uint96,uint32) (runs: 256, μ: 472583, ~: 491243)\nLogs:\n  Bound result 1709801287471445232\n  Bound result 1379\n\n[PASS] testFuzz_partialFillsAtAnyFee(bool,bool,uint96,uint32) (runs: 256, μ: 472737, ~: 490605)\nLogs:\n  Bound result 84\n  Bound result 7539671089448955102813\n\n[PASS] test_claimSweepFailurePreservesClaims() (gas: 571874)\n[PASS] test_directIMDDonationSweepsWithoutInflatingCollected() (gas: 171470)\n[PASS] test_exactInputBuy() (gas: 485697)\n[PASS] test_exactInputSell() (gas: 419171)\n[PASS] test_exactOutputBuy() (gas: 425275)\n[PASS] test_exactOutputSell() (gas: 472891)\n[PASS] test_failedTakeFallsBackToClaimsThenRedeems() (gas: 1965803)\n[PASS] test_failedTreasuryTransferCannotBlockTrading() (gas: 893445)\n[PASS] test_invalidPriceLimitPreservesPoolAndAccounting() (gas: 208360)\n[PASS] test_liquidityTransfersHaveNoHookFee() (gas: 248971)\n[PASS] test_maximalExactOutputCannotBypassFeesWithPartialFill() (gas: 296501)\n[PASS] test_minimalSignedExactInputStillPaysOnActualPartialFill() (gas: 398606)\n[PASS] test_partialExactInputBuy() (gas: 485331)\n[PASS] test_partialExactInputSell() (gas: 419667)\n[PASS] test_partialExactOutputBuy() (gas: 425821)\n[PASS] test_partialExactOutputSell() (gas: 471533)\n[PASS] test_permissionlessSweepAndRepeatedSweep() (gas: 832354)\n[PASS] test_reentryCannotSweepDuringAccrualOrSweep() (gas: 694944)\n[PASS] test_rejectedSwapRollsBackFeeAccrual() (gas: 419715)\n[PASS] test_tinyAmountsDoNotBlockAnySwapMode() (gas: 960665)\nSuite result: ok. 22 passed; 0 failed; 0 skipped; finished in 94.31ms (192.33ms CPU time)\n\nRan 22 tests for test/Swaps.t.sol:SwapsTest\n[PASS] testFuzz_fourModesAtAnyFee(bool,bool,uint96,uint32) (runs: 1000, μ: 469663, ~: 490316)\nLogs:\n  Bound result 56204283101628\n  Bound result 4320\n\n[PASS] testFuzz_partialFillsAtAnyFee(bool,bool,uint96,uint32) (runs: 1000, μ: 470153, ~: 491330)\nLogs:\n  Bound result 3875\n  Bound result 9000000000117728759464\n\n[PASS] test_claimSweepFailurePreservesClaims() (gas: 558812)\n[PASS] test_directIMDDonationSweepsWithoutInflatingCollected() (gas: 171470)\n[PASS] test_exactInputBuy() (gas: 472699)\n[PASS] test_exactInputSell() (gas: 425687)\n[PASS] test_exactOutputBuy() (gas: 420210)\n[PASS] test_exactOutputSell() (gas: 483433)\n[PASS] test_failedTakeFallsBackToClaimsThenRedeems() (gas: 1965087)\n[PASS] test_failedTreasuryTransferCannotBlockTrading() (gas: 887250)\n[PASS] test_invalidPriceLimitPreservesPoolAndAccounting() (gas: 208386)\n[PASS] test_liquidityTransfersHaveNoHookFee() (gas: 248971)\n[PASS] test_maximalExactOutputCannotBypassFeesWithPartialFill() (gas: 302516)\n[PASS] test_minimalSignedExactInputStillPaysOnActualPartialFill() (gas: 385751)\n[PASS] test_partialExactInputBuy() (gas: 473116)\n[PASS] test_partialExactInputSell() (gas: 425882)\n[PASS] test_partialExactOutputBuy() (gas: 419886)\n[PASS] test_partialExactOutputSell() (gas: 483630)\n[PASS] test_permissionlessSweepAndRepeatedSweep() (gas: 827370)\n[PASS] test_reentryCannotSweepDuringAccrualOrSweep() (gas: 681946)\n[PASS] test_rejectedSwapRollsBackFeeAccrual() (gas: 424656)\n[PASS] test_tinyAmountsDoNotBlockAnySwapMode() (gas: 948551)\nSuite result: ok. 22 passed; 0 failed; 0 skipped; finished in 94.38ms (172.49ms CPU time)\n\nRan 1 test for test/Invariant.t.sol:FeeInvariantTest\n[PASS] invariant_feesBackedAndEveryDeltaSettled() (runs: 128, calls: 8192, reverts: 0)\n\n╭-------------+------------+-------+---------+----------╮\n| Contract    | Selector   | Calls | Reverts | Discards |\n+=======================================================+\n| SwapHandler | claimsMode | 2037  | 0       | 0        |\n|-------------+------------+-------+---------+----------|\n| SwapHandler | elapse     | 2088  | 0       | 0        |\n|-------------+------------+-------+---------+----------|\n| SwapHandler | sweep      | 2019  | 0       | 0        |\n|-------------+------------+-------+---------+----------|\n| SwapHandler | trade      | 2048  | 0       | 0        |\n╰-------------+------------+-------+---------+----------╯\n\nLogs:\n  Bound result 9999999999999000470\n  Bound result 1000003\n  Bound result 488\n  Bound result 714\n  Bound result 18\n  Bound result 2\n  Bound result 10763457105107\n  Bound result 552\n  Bound result 9999999999999007546\n  Bound result 1850481318\n  Bound result 2\n  Bound result 9999999999999003135\n  Bound result 0\n  Bound result 528\n  Bound result 9999999999999004944\n  Bound result 180\n  Bound result 16635278\n  Bound result 930\n  Bound result 0\n  Bound result 9999999999999003136\n  Bound result 9999999999999000006\n  Bound result 242\n  Bound result 893\n  Bound result 118\n  Bound result 731\n  Bound result 499370035118071305\n  Bound result 374\n  Bound result 617\n  Bound result 9999999999999001327\n  Bound result 8508935170403613976\n  Bound result 8\n  Bound result 9999999999999017977\n  Bound result 801\n  Bound result 901\n  Bound result 605\n  Bound result 9999999999999001166\n  Bound result 757\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.28s (1.26s CPU time)\n\nRan 8 test suites in 1.28s (1.61s CPU time): 64 tests passed, 0 failed, 1 skipped (65 total tests)\n","passed":true},{"durationMs":48,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"SIMDTEST.approve(address,uint256)\",\"SIMDTEST.transfer(address,uint256)\",\"SIMDTEST.transferFrom(address,address,uint256)\",\"SIMDTESTHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"SIMDTESTHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"SIMDTESTHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"SIMDTESTHook.quoteSwap((address,address,uint24,int24,address),(bool,int256,uint160))\",\"SIMDTESTHook.sweep()\",\"SIMDTESTHook.unlockCallback(bytes)\"],\"files\":{\".gitignore\":3,\"DEPENDENCIES.json\":30,\"DEPENDENCIES.sha256\":86,\"README.md\":197,\"SECURITY_REVIEW.md\":117,\"foundry.toml\":21,\"launch.json\":27,\"script/HookMiner.sol\":29,\"script/MineHook.s.sol\":19,\"src/SIMDTEST.sol\":11,\"src/SIMDTESTHook.sol\":248,\"test/Hook.t.sol\":175,\"test/Invariant.t.sol\":92,\"test/MainnetFork.t.sol\":70,\"test/Swaps.t.sol\":360,\"test/Token.t.sol\":66,\"test/helpers/HookFixture.sol\":100,\"test/helpers/MockIMD.sol\":37,\"test/helpers/SettlementRouter.sol\":62},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":1145,"exitCode":0,"name":"slither","output":"[medium/high] incorrect-equality at src/SIMDTESTHook.sol:200: SIMDTESTHook._accrue(uint256,uint256) (src/SIMDTESTHook.sol#200-211) uses a dangerous strict equality:\n[medium/medium] unused-return at src/SIMDTESTHook.sol:175: SIMDTESTHook.sweep() (src/SIMDTESTHook.sol#175-189) ignores return value by poolManager.unlock(abi.encode(claims)) (src/SIMDTESTHook.sol#181)\n[low/medium] reentrancy-benign at src/SIMDTESTHook.sol:175: Reentrancy in SIMDTESTHook.sweep() (src/SIMDTESTHook.sol#175-189):\n[low/medium] timestamp at src/SIMDTESTHook.sol:98: SIMDTESTHook.feeNow() (src/SIMDTESTHook.sol#98-103) uses timestamp for comparisons\n[low/medium] timestamp at src/SIMDTESTHook.sol:245: SIMDTESTHook._min(uint256,uint256) (src/SIMDTESTHook.sol#245-247) uses timestamp for comparisons\n[low/medium] timestamp at src/SIMDTESTHook.sol:111: SIMDTESTHook.beforeSwap(address,PoolKey,SwapParams,bytes) (src/SIMDTESTHook.sol#111-146) uses timestamp for comparisons\n[low/medium] timestamp at src/SIMDTESTHook.sol:200: SIMDTESTHook._accrue(uint256,uint256) (src/SIMDTESTHook.sol#200-211) uses timestamp for comparisons\n[low/medium] timestamp at src/SIMDTESTHook.sol:175: SIMDTESTHook.sweep() (src/SIMDTESTHook.sol#175-189) uses timestamp for comparisons","passed":true},{"durationMs":364,"exitCode":0,"name":"aderyn","output":"[high] reentrancy-state-change at src/SIMDTESTHook.sol:176: Reentrancy: State change after external call (2 places)\n[low] large-numeric-literal at src/SIMDTEST.sol:9: Large Numeric Literal (2 places)\n[low] non-reentrant-not-first at src/SIMDTESTHook.sol:114: `nonReentrant` is Not the First Modifier (2 places)\n[low] unchecked-return at src/SIMDTESTHook.sol:181: Unchecked Return\n[low] unsafe-erc20-operation at src/SIMDTESTHook.sol:186: Unsafe ERC20 Operation\n[low] unused-public-function at src/SIMDTESTHook.sol:106: Public Function Not Used Internally","passed":true}],"detail":"launch.json is not a valid launch manifest: kind: Invalid discriminator value. Expected 'univ4_hook' | 'evm_project' | 'custom_token' | 'evm_contracts'","evaluation":"checks","profile":"foundry","status":"rejected","submissionHash":"c33d9c7a885324dc05f8324da269ed6764db0fd96d99ac23a67c87eb2da2db9f","verifiedTreeHash":"56f444df7cda73353355ee6a9187ad55bb285f9d","verifierVersion":"0.1.0+ad90ce4c"},{"checks":[{"durationMs":94252,"exitCode":0,"name":"build","output":"Compiling 88 files with Solc 0.8.26\nSolc 0.8.26 finished in 94.08s\nCompiler run successful!\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SpecifiedAmount.sol:58:51\n   │\n58 │                 remaining = exactIn ? remaining + int256(input + lpAmount) : remaining - int256(output);\n   │                                                   ━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'int256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SIMDTESTHook.sol:25:48\n   │\n25 │     address public constant treasury = address(bytes20(hex\"3dd5f73dd1a4e62630fad3909673f130ad429985\"));\n   │                                                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes20' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SIMDTESTHook.sol:29:31\n   │\n29 │         Currency.wrap(address(bytes20(hex\"d34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7\")));\n   │                               ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes20' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SpecifiedAmount.sol:58:90\n   │\n58 │                 remaining = exactIn ? remaining + int256(input + lpAmount) : remaining - int256(output);\n   │                                                                                          ━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'int256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SpecifiedAmount.sol:72:19\n   │\n72 │                 ? uint256(remaining - params.amountSpecified)\n   │                   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SpecifiedAmount.sol:73:19\n   │\n73 │                 : uint256(params.amountSpecified - remaining);\n   │                   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/SIMDTESTHook.sol:89:29\n   │\n89 │         if (!initialized || block.timestamp <= openedAt) return OPENING_FEE;\n   │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/SIMDTESTHook.sol:91:13\n   │\n91 │         if (elapsed >= OPENING_SECONDS) return STEADY_FEE;\n   │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:108:35\n    │\n108 │             requested = exactIn ? uint256(-params.amountSpecified) : uint256(params.amountSpecified);\n    │                                   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:108:70\n    │\n108 │             requested = exactIn ? uint256(-params.amountSpecified) : uint256(params.amountSpecified);\n    │                                                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:113:25\n    │\n113 │             requested > uint256(uint128(type(int128).max)) ? uint256(uint128(type(int128).max)) : requested;\n    │                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:113:33\n    │\n113 │             requested > uint256(uint128(type(int128).max)) ? uint256(uint128(type(int128).max)) : requested;\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:113:62\n    │\n113 │             requested > uint256(uint128(type(int128).max)) ? uint256(uint128(type(int128).max)) : requested;\n    │                                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:113:70\n    │\n113 │             requested > uint256(uint128(type(int128).max)) ? uint256(uint128(type(int128).max)) : requested;\n    │                                                                      ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:116:44\n    │\n116 │         quote.amountSpecified = exactIn ? -int256(budget - reserve) : int256(budget + reserve);\n    │                                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:116:71\n    │\n116 │         quote.amountSpecified = exactIn ? -int256(budget - reserve) : int256(budget + reserve);\n    │                                                                       ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:126:63\n    │\n126 │         return (IHooks.beforeSwap.selector, toBeforeSwapDelta(int128(int256(fee)), 0), 0);\n    │                                                               ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:126:70\n    │\n126 │         return (IHooks.beforeSwap.selector, toBeforeSwapDelta(int128(int256(fee)), 0), 0);\n    │                                                                      ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:143:36\n    │\n143 │         uint256 fee = amount < 0 ? uint256(-amount) * rate / (10_000 - rate) : uint256(amount) * rate / 10_000;\n    │                                    ━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:143:80\n    │\n143 │         uint256 fee = amount < 0 ? uint256(-amount) * rate / (10_000 - rate) : uint256(amount) * rate / 10_000;\n    │                                                                                ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:145:44\n    │\n145 │         return (IHooks.afterSwap.selector, int128(int256(fee)));\n    │                                            ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SIMDTESTHook.sol:145:51\n    │\n145 │         return (IHooks.afterSwap.selector, int128(int256(fee)));\n    │                                                   ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/SIMDTESTHook.sol:152:9\n    │\n152 │         emit FeeAccrued(fee);\n    │         ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `sweeping` is updated\n    ╭▸ src/SIMDTESTHook.sol:164:29\n    │\n164 │         amount = abi.decode(poolManager.unlock(\"\"), (uint256));\n    │                             ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/SIMDTESTHook.sol:169:9\n    │\n169 │         emit Swept(amount);\n    │         ━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\n","passed":true},{"durationMs":1296,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/MainnetForkExtended.t.sol:MainnetForkExtendedTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 575.30µs (0.00ns CPU time)\n\nRan 1 test for test/MainnetFork.t.sol:MainnetForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 569.00µs (0.00ns CPU time)\n\nRan 1 test for test/Hook.t.sol:OppositeOrderingTest\n[PASS] testBothDirectionsAndExactnessWithIMDCurrency0() (gas: 1279518)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.88ms (1.29ms CPU time)\n\nRan 2 tests for test/Hook.t.sol:FreshManagerTest\n[PASS] testEmptyPoolChargesNothingInAllModes() (gas: 2734753)\n[PASS] testTokenOnlySeedNeedsNoPrefundedIMD() (gas: 697578)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 32.25ms (6.08ms CPU time)\n\nRan 24 tests for test/HookAdversarial.t.sol:HookAdversarialTest\n[PASS] testCollectedIsTheSumOfPerSwapFeesAcrossTheSchedule() (gas: 2011470)\n[PASS] testConstructorRejectsAnAddressWithoutThePermissionBits() (gas: 9908)\n[PASS] testConstructorRejectsMissingOrCollidingAddresses() (gas: 6848)\n[PASS] testEventsOpenedAccruedSwept() (gas: 14800148)\n[PASS] testExactFeesAtOpening() (gas: 1482686)\n[PASS] testExactFeesHalfway() (gas: 1497227)\n[PASS] testExactFeesSteadyState() (gas: 1494594)\n[PASS] testFeeIsIndependentOfSenderAndHookData() (gas: 1338722)\n[PASS] testFeeNowRoundsDownAtEveryStep() (gas: 7044618)\n[PASS] testFreshHookRejectsForeignPoolsWithClearReasons() (gas: 14468427)\n[PASS] testFreshHookReportsOpeningRateAndNothingPending() (gas: 14468136)\n[PASS] testFuzzExactFeesOnFullFills(bool,bool,uint72,uint16) (runs: 1000, μ: 372299, ~: 374236)\n[PASS] testFuzzFeeNowMatchesClosedForm(uint64) (runs: 2000, μ: 20781, ~: 20720)\n[PASS] testFuzzHookNeverCausesASwapRevert(bool,bool,uint256,uint160,bool,uint32) (runs: 1500, μ: 235158, ~: 278372)\n[PASS] testFuzzPartialFillsAcrossManyInitializedTicks(bool,bool,uint8,uint16) (runs: 256, μ: 2866775, ~: 2858266)\n[PASS] testGrossFortyPercentIsTwoThirdsOfNet() (gas: 367799)\n[PASS] testHookCannotBeSharedWithASecondPool() (gas: 1385272)\n[PASS] testHookNeverHoldsLaunchTokenClaims() (gas: 1236194)\n[PASS] testLiquidityAndDonationsAreNeverCharged() (gas: 1137878)\n[PASS] testLpFeesStayWithLiquidityProvidersNotTheHook() (gas: 546348)\n[PASS] testManagerIMDAlwaysBacksTheClaims() (gas: 1944578)\n[PASS] testOneSecondBoundaryChangesTheCharge() (gas: 705475)\n[PASS] testSweepByContractCallerPaysOnlyTreasury() (gas: 610276)\n[PASS] testUnexpectedClaimsAreForwardedToTreasuryWithoutRevert() (gas: 966767)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 366.17ms (695.08ms CPU time)\n\nRan 20 tests for test/Hook.t.sol:HookTest\n[PASS] testAllSwapModesOpeningAndSteady() (gas: 2399554)\n[PASS] testFeeScheduleBoundaries() (gas: 92657)\n[PASS] testFuzzFeeOnRealSwaps(bool,bool,uint96,uint16) (runs: 1000, μ: 349771, ~: 349033)\n[PASS] testFuzzPartialFills(bool,bool,uint8,uint16) (runs: 256, μ: 376320, ~: 375028)\n[PASS] testFuzzScheduleMonotonic(uint32,uint32) (runs: 1000, μ: 33616, ~: 33469)\n[PASS] testHugeRequestedInputOnlyChargesTheSmallFilledAmount() (gas: 345514)\n[PASS] testImmutableConfigurationAndPermissions() (gas: 44119)\n[PASS] testInvalidInitializationAndNoReset() (gas: 14667282)\n[PASS] testInvalidSwapInputsAreManagerFailures() (gas: 108865)\n[PASS] testNoAdminPathsAndRuntimeLimits() (gas: 2036025)\n[PASS] testProtocolFeesDoNotDesynchronizePartialFillQuote() (gas: 1555720)\n[PASS] testReentryAndUnlockedSweepAreHarmless() (gas: 573391)\n[PASS] testRevertingSettlementRollsBackFeesAndPrice() (gas: 249958)\n[PASS] testRevertingSweepPreservesClaimsAndDoesNotBlockSwaps() (gas: 925356)\n[PASS] testSweepPermissionlessAndConservesAllFees() (gas: 896951)\n[PASS] testTickCrossingsAndLiquidityGaps() (gas: 1732813)\n[PASS] testTinySwapsDoNotConsumeEntireInputAsFee() (gas: 1104650)\n[PASS] testUnauthorizedCallbacks() (gas: 147630)\n[PASS] testWrongPermissionBitsRefuseDeployment() (gas: 2746623)\n[PASS] testZeroTimestampInitializationDoesNotResetClock() (gas: 14524506)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 369.95ms (677.92ms CPU time)\n\nRan 5 tests for test/SpecifiedAmount.t.sol:SpecifiedAmountTest\n[PASS] testFuzzQuoteEqualsManagerFill(uint256,uint8,bool,bool,uint96,uint16,bool,uint16,uint16,int16) (runs: 1500, μ: 971362, ~: 910557)\n[PASS] testQuoteIsZeroOnAnEmptyPoolAndUninitializedPool() (gas: 1658391)\n[PASS] testQuoteIsZeroWhenTheManagerWouldRejectTheLimit() (gas: 934329)\n[PASS] testQuoteOnRequestsFarBeyondInt128() (gas: 1368670)\n[PASS] testQuoteWalksGapsAndWholeBitmapWords() (gas: 2761768)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 370.07ms (379.48ms CPU time)\n\nRan 4 tests for test/SIMDTEST.t.sol:SIMDTESTTest\n[PASS] testAllowanceAndFailureAreAtomic() (gas: 300366)\n[PASS] testFuzzTransfersConserveSupply(uint256) (runs: 1000, μ: 112251, ~: 112409)\n[PASS] testLaunchSupplyAndMetadata() (gas: 35050)\n[PASS] testNoPrivilegedEntrypoints() (gas: 189660)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 371.70ms (370.14ms CPU time)\n\nRan 24 tests for test/HookAdversarial.t.sol:HookAdversarialIMDFirstTest\n[PASS] testCollectedIsTheSumOfPerSwapFeesAcrossTheSchedule() (gas: 2012295)\n[PASS] testConstructorRejectsAnAddressWithoutThePermissionBits() (gas: 9908)\n[PASS] testConstructorRejectsMissingOrCollidingAddresses() (gas: 6848)\n[PASS] testEventsOpenedAccruedSwept() (gas: 9058772)\n[PASS] testExactFeesAtOpening() (gas: 1484041)\n[PASS] testExactFeesHalfway() (gas: 1498590)\n[PASS] testExactFeesSteadyState() (gas: 1496435)\n[PASS] testFeeIsIndependentOfSenderAndHookData() (gas: 1360302)\n[PASS] testFeeNowRoundsDownAtEveryStep() (gas: 7044618)\n[PASS] testFreshHookRejectsForeignPoolsWithClearReasons() (gas: 8716332)\n[PASS] testFreshHookReportsOpeningRateAndNothingPending() (gas: 8716197)\n[PASS] testFuzzExactFeesOnFullFills(bool,bool,uint72,uint16) (runs: 1000, μ: 373329, ~: 370668)\n[PASS] testFuzzFeeNowMatchesClosedForm(uint64) (runs: 1000, μ: 20781, ~: 20720)\n[PASS] testFuzzHookNeverCausesASwapRevert(bool,bool,uint256,uint160,bool,uint32) (runs: 1000, μ: 232606, ~: 282126)\n[PASS] testFuzzPartialFillsAcrossManyInitializedTicks(bool,bool,uint8,uint16) (runs: 1000, μ: 2865821, ~: 2861013)\n[PASS] testGrossFortyPercentIsTwoThirdsOfNet() (gas: 359855)\n[PASS] testHookCannotBeSharedWithASecondPool() (gas: 1385272)\n[PASS] testHookNeverHoldsLaunchTokenClaims() (gas: 1237478)\n[PASS] testLiquidityAndDonationsAreNeverCharged() (gas: 1137878)\n[PASS] testLpFeesStayWithLiquidityProvidersNotTheHook() (gas: 556961)\n[PASS] testManagerIMDAlwaysBacksTheClaims() (gas: 1946503)\n[PASS] testOneSecondBoundaryChangesTheCharge() (gas: 726715)\n[PASS] testSweepByContractCallerPaysOnlyTreasury() (gas: 604538)\n[PASS] testUnexpectedClaimsAreForwardedToTreasuryWithoutRevert() (gas: 977395)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 372.01ms (1.11s CPU time)\n\nRan 1 test for test/Invariant.t.sol:HookInvariantTest\n[PASS] invariantFeesRemainBackedAndOnlyTreasuryReceives() (runs: 64, calls: 2048, reverts: 0)\n\n╭-------------+----------+-------+---------+----------╮\n| Contract    | Selector | Calls | Reverts | Discards |\n+=====================================================+\n| SwapHandler | advance  | 680   | 0       | 0        |\n|-------------+----------+-------+---------+----------|\n| SwapHandler | sweep    | 687   | 0       | 0        |\n|-------------+----------+-------+---------+----------|\n| SwapHandler | trade    | 681   | 0       | 0        |\n╰-------------+----------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 475.62ms (435.75ms CPU time)\n\nRan 1 test for test/InvariantExtended.t.sol:ExtendedInvariantIMDFirstTest\n[PASS]\nExtendedInvariantIMDFirstTest invariants:\n[PASS] invariantFeesAreBackedAndReachOnlyTreasury\n[PASS] invariantHookNeverRevertsAndManagerSettles\n[PASS] invariantScheduleClockAndPoolTermsAreFixed\n ExtendedInvariantIMDFirstTest invariants (runs: 96, calls: 4608, reverts: 0)\n\n╭-----------------+-----------------+-------+---------+----------╮\n| Contract        | Selector        | Calls | Reverts | Discards |\n+================================================================+\n| ExtendedHandler | addLiquidity    | 478   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | advance         | 456   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | donate          | 460   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | donateClaims    | 436   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | donateLoose     | 456   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | removeLiquidity | 474   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | swap            | 1362  | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | sweep           | 486   | 0       | 0        |\n╰-----------------+-----------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.17s (1.16s CPU time)\n\nRan 1 test for test/InvariantExtended.t.sol:ExtendedInvariantIMDSecondTest\n[PASS]\nExtendedInvariantIMDSecondTest invariants:\n[PASS] invariantFeesAreBackedAndReachOnlyTreasury\n[PASS] invariantHookNeverRevertsAndManagerSettles\n[PASS] invariantScheduleClockAndPoolTermsAreFixed\n ExtendedInvariantIMDSecondTest invariants (runs: 96, calls: 4608, reverts: 0)\n\n╭-----------------+-----------------+-------+---------+----------╮\n| Contract        | Selector        | Calls | Reverts | Discards |\n+================================================================+\n| ExtendedHandler | addLiquidity    | 478   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | advance         | 456   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | donate          | 460   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | donateClaims    | 436   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | donateLoose     | 456   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | removeLiquidity | 474   | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | swap            | 1362  | 0       | 0        |\n|-----------------+-----------------+-------+---------+----------|\n| ExtendedHandler | sweep           | 486   | 0       | 0        |\n╰-----------------+-----------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.18s (1.14s CPU time)\n\nRan 12 test suites in 1.18s (4.71s CPU time): 83 tests passed, 0 failed, 2 skipped (85 total tests)\n","passed":true},{"durationMs":79,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"SIMDTEST.approve(address,uint256)\",\"SIMDTEST.transfer(address,uint256)\",\"SIMDTEST.transferFrom(address,address,uint256)\",\"SIMDTESTHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"SIMDTESTHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"SIMDTESTHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"SIMDTESTHook.sweep()\",\"SIMDTESTHook.unlockCallback(bytes)\"],\"files\":{\".gitignore\":3,\"DEPENDENCIES.md\":8,\"LICENSE\":25,\"README.md\":95,\"docs/PROVENANCE.md\":3,\"docs/REFERENCE_LICENSE\":24,\"docs/SECURITY_REVIEW.md\":31,\"docs/SOURCE_SHA256SUMS.txt\":89,\"docs/VERIFICATION.md\":29,\"foundry.toml\":21,\"launch.json\":30,\"remappings.txt\":4,\"script/HookDeployer.sol\":33,\"src/HookFlags.sol\":30,\"src/SIMDTEST.sol\":11,\"src/SIMDTESTHook.sol\":181,\"src/SpecifiedAmount.sol\":101,\"test/Hook.t.sol\":355,\"test/HookAdversarial.t.sol\":496,\"test/Invariant.t.sol\":92,\"test/InvariantExtended.t.sol\":302,\"test/MainnetFork.t.sol\":68,\"test/MainnetForkExtended.t.sol\":154,\"test/SIMDTEST.t.sol\":74,\"test/SpecifiedAmount.t.sol\":180,\"test/helpers/Actors.sol\":111,\"test/helpers/HookFixture.sol\":123,\"test/helpers/TestRouter.sol\":66,\"test/mocks/MockERC20.sol\":36,\"tools/check_launch.py\":31},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"e1af35fe6c25b24aef0255f95ab993d1c37f9a66dfdebff5a724361d65fcfa9b","verifiedTreeHash":"a4f7e8347e0ae37f6f4d8555ca8ada48ce0f3763","verifierVersion":"0.1.0+ad90ce4c"}]}