{"assessments":[],"deployments":[{"attestationHash":"516283450ad6e600e2834d890959ab9056f4244da87236d7c162f7c6aea41fbd","chainId":11155111,"contracts":[],"id":"0150f619-56e8-4421-aad4-bfb6f3de473b","manifestHash":"941ad56bade92bba3085d801ab1cbc7bc77d6e561319f2d6275d521d58496d12","status":"parked"}],"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":"d8c77885-cfb8-4bf6-b33d-96b9aa10e0d9","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"06decf1e8cac83822d92916c6d1852272b3ff25e822a4b2f8abf08bc4fc30c01","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_economics","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"e8c9a58b4190b9f3e7f9aff2e945cad3f7f413ca814ee618257d1ce1a5c576ca","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_flow","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"3868f6f844c08067972e3193615b38b25fe081f2dd7eba0a6e9affc0805ef45b","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":"75d905c2cef6e15f5771d8d8ee258e6760dbdb12f493b95506f81850128e9875","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_math","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"62b27d4fa56e591539a30206a86d4b7d6cfb6871818288f55aa4dd041802f454","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_permissions","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"eb8cf80113b2bbc5e34c7ad35c71d51cbc1d2b693d1bddce64c5209cf35f1ff9","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"47381b166d1f406a34f0ebdc740ee21bc0383e56e7ad9084b26abf1bf7570904","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"47381b166d1f406a34f0ebdc740ee21bc0383e56e7ad9084b26abf1bf7570904","skillId":"build-contract-project","state":"accepted"},{"acceptedSubmissionHash":"19b5e14072d2ed41ce471eb6756e4a9b31d771bea2b030c15ed3e438ad1caca1","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"0ccc0c568ee031c706915ad07c7aecc009f86a46641cccd965546536ab94943e","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":"An anti-snipe hook: the pool's LP fee is 1% for the first hour after the pool is initialized and 0.3% afterwards, set through the dynamic fee in beforeSwap. No owner and no other state changes.","parentJobId":null,"planHash":"7c4a31deaeb4db0afb7b06f2a3eb79682046d09afd294f42904e429273500965","previousHash":"423e2081d8347507ea7dc26fb6ed65e4a430c00a39b74384565b515880ed4f33","projectId":"d8c77885-cfb8-4bf6-b33d-96b9aa10e0d9","publication":{"commit":"389127f5d1f9ee28cf768f192d0b15fbb365b988","deliveredAt":"2026-10-01T06:38:19.132Z","repoUrl":"https://github.com/identity-md-launches/launch-552-anti-snipe-hook-pool-s-lp"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[],"site":null,"snapshotHash":"eec5d51bece18a41a0b45f6cd4e4aacd7ec10bf6b7549293995246e0a93ac461","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"41f7c1458e1278ad","findings":[{"citation":"resolved","description":"Flow Gap (execution x first principles). The 1% period starts in afterInitialize and is never re-anchored. Trading is impossible until liquidity exists, so every second between initialize and the first liquidity add is anti-snipe time with nobody to deter. If the launcher seeds liquidity in a later transaction (README step 5 lists seeding as a separate step after the one-transaction deploy+initialize) the effective window is 3600s minus that delay, and zero if the delay reaches one hour. This matches the stated spec (\"first hour after the pool is initialized\") and is reported as a design/operational note, not a code defect: the fix, if wanted, is procedural (seed in the same transaction as initialize) or a spec change (anchor to first liquidity), which would add state the brief forbids.","line":53,"path":"src/AntiSnipeHook.sol","reproduction":"State: fresh PoolManager, hook at a 0x1080 address, dynamic-fee key. Calls: (1) manager.initialize(key, 2^96) at t=1_000_000; (2) vm.warp(1_003_600); (3) modifyLiquidity(-600,600,+1e24); (4) swap exactIn 1e18 token0. Expected by the anti-snipe intent: the first-ever trade on the pool pays 1% (fees.amount0 ~ 1e16). Actual: LP fee collected on that swap is 2_999_999_999_999_999 wei (0.3%); hook.antiSnipeEndsAt(poolId) == 1_003_600 and beforeSwap returns 3000|0x400000. Verified with a Foundry test against this tree.","severity":"info","snippet":"        uint256 endsAt = block.timestamp + ANTI_SNIPE_DURATION;\n        antiSnipeEndsAt[poolId] = endsAt;","title":"Anti-snipe window is anchored to pool initialization, so any delay between initialize and liquidity seeding consumes the protection"},{"citation":"resolved","description":"Economic Security (\"legitimate features turned against the protocol\"). The override fee is credited to feeGrowthGlobal and therefore pro rata to whatever liquidity is in range at swap time. Liquidity provision is ungated (no beforeAddLiquidity permission, by spec). During the window a participant can post a tight-range position far larger than the launcher's wide seed, let the next buyer pay 1%, and withdraw: the surcharge intended to tax snipers is redirected to one. The launcher's seed position earns a proportionally smaller share. This is standard concentrated-liquidity behaviour amplified 3.3x by the higher fee, and the brief rules out owner/state additions that would mitigate it, so it is recorded as a trust/design assumption, not a defect.","line":70,"path":"src/AntiSnipeHook.sol","reproduction":"State: pool initialized at t0, launcher adds liquidity 1e24 on [-600,600]. In the window (t0+1s): attacker adds 1e26 on [-60,60] with position salt 1; victim swaps exactIn 1e18 token0 (pays ~1e16 fee). Then both positions call modifyLiquidity with liquidityDelta 0 to collect. Actual: attacker position receives 9_900_990_099_009_900 wei of token0 fee, launcher receives 99_009_900_990_099 wei (~1%). Expected by the anti-snipe intent: the surcharge accrues to launch liquidity. Verified with a Foundry test against this tree.","severity":"info","snippet":"        uint24 fee = block.timestamp < endsAt ? INITIAL_LP_FEE : STANDARD_LP_FEE;","title":"The 1% anti-snipe fee is an ordinary LP fee, so a sniper who adds just-in-time liquidity captures it from other early buyers"}],"hash":"06decf1e8cac83822d92916c6d1852272b3ff25e822a4b2f8abf08bc4fc30c01","nodeId":"f4dd207d-a7bb-49b0-b963-95b0d15fcc6b","outcome":"completed","summary":"Review complete. The findings file is written at `.imd-findings.json` with two info-level observations and a full coverage record. No source files were changed.\n\n**Outcome:** no fund-loss, misdirected-payment, or breakage defect in the economics of the hook. The 1%/0.3% schedule is applied exactly as specified on every swap path I traced through v4-core's fee-override logic, including both directions, exact-input and exact-output, the 3599/3600 second boundary, and composition with a protocol fee. The existing 37-test suite passes, and my scratch probes confirmed the mechanics before I deleted them.\n\n**Findings reported, both info and spec-compliant:**\n\n- **Window anchored to initialize, not liquidity.** Initialize at t, seed liquidity at t+3600, and the first trade ever pays 0.3%. The deadline is set once in `afterInitialize` and never re-anchored. This is what the brief asked for, so it is an operational note: seed liquidity in the same transaction as initialize.\n- **The 1% surcharge is an ordinary LP fee, so JIT liquidity captures it.** A tight-range position added inside the window took 99% of the fee paid by the next buyer, leaving the launcher's seed position about 1%. Mitigating this would need LP gating or state the brief forbids, so it is recorded as a design assumption.\n\n**Checked and holding:** the stored slot0 fee is zero, but the only path that skips the override requires the hook itself to be the swapper, and the hook has no code that can call the pool manager. The deadline is write-once with no reset path. Disabled callbacks are unreachable from the pool manager and revert if called. The token is stock OpenZeppelin ERC20 with a fixed supply. The slither timestamp lead shifts the boundary by validator seconds on a one-hour window and carries no extractable value, so I did not report it.\n\n**Not reached:** nothing in my assigned area. One note outside it for the judge: the constructor rejects a manager address with no code, so the protected harness must etch the real manager at `IMD_POOL_MANAGER` for the attested creation code to deploy. The harness comments indicate it does, and I could not verify the verifier's environment, so it is not a finding.","treeHash":null,"usage":{"cachedInputTokens":824279,"inputTokens":258,"model":"claude-fable-5-1","outputTokens":19127,"runtime":"claude","turns":24,"wallClockMs":303739}},{"artifacts":[],"attempt":1,"bundleHash":"e4ce1330ec08a592d91c2648c0968c1241892744fd70a490212092a8ecd01d82","device":"35c52a5b502e847c","findings":[],"hash":"0ccc0c568ee031c706915ad07c7aecc009f86a46641cccd965546536ab94943e","nodeId":"ebe9aef9-621e-4626-b60b-a0c5aaed2280","outcome":"completed","summary":"Added stateful invariants and edge-case tests covering fee transitions, rejected operations, settlement, token balances, and allowances.\n\nOffline verification passed: **44 tests, 0 failures**, including **65,536 randomized handler calls**.\n\nOnly `test/` changed. No reproducible defects found.","treeHash":"66ab41a948e4ac720fde964eb105d1d6d352b7c8","usage":{"cachedInputTokens":2018560,"inputTokens":96436,"model":"gpt-6-astra","outputTokens":14502,"runtime":"codex","turns":7,"wallClockMs":530141}},{"artifacts":[],"attempt":1,"bundleHash":"50d2abfa30d9d22af4bb9442645cd1b8f537f16c6d6185300cf4bbf0b6796dc2","device":"40aae51ff9854f9f","findings":[],"hash":"19b5e14072d2ed41ce471eb6756e4a9b31d771bea2b030c15ed3e438ad1caca1","nodeId":"46faf5f6-18ac-43be-b4c2-549a524b6830","outcome":"completed","summary":"Created [launch.json](/home/debian/.identitymd/work/d8c77885-cfb8-4bf6-b33d-96b9aa10e0d9/46faf5f6-18ac-43be-b4c2-549a524b6830/launch.json) with matching contracts, permissions, `$poolManager`, and native ETH pairing. Only the manifest is submitted.\n\n**Deployment remains blocked:** the hook requires fee `8388608`, but the supplied schema permits at most `1000000`. Notes explicitly identify `3000` as a non-deployable placeholder.\n\nChecks completed:\n\n- Supplied schema validation passed; notes: 1,597/4,000 characters.\n- `forge build` passed.\n- `forge test` passed: 48 tests, including protected checks and reproduction of the incompatibility.\n\nFoundry artifacts were directed to `test/scratch/`.","treeHash":"510e4efae45ccd8cb71dcb6329c6dbf5c028c46b","usage":{"cachedInputTokens":293376,"inputTokens":55173,"model":"gpt-6-astra","outputTokens":6165,"runtime":"codex","turns":4,"wallClockMs":216658}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"0256823ae36e7900","findings":[],"hash":"1dfcc87b46e31fc88851b7d163dd4501a4c747decb06f81221f000c558fa8862","nodeId":"46faf5f6-18ac-43be-b4c2-549a524b6830","outcome":"no_change","summary":"Reproduced the blocker: the hook requires fee `8388608`, but the schema caps it at `1000000`. No compliant manifest-only fix exists.\n\nLeft `launch.json` unchanged and recorded the evidence in `.imd-responses.json`, using `disputed` only for in-scope fixability.\n\nOffline `forge build` succeeded; all 39 local tests passed. Deployment remains blocked pending schema/deployer support.","treeHash":null,"usage":{"cachedInputTokens":391808,"inputTokens":42354,"model":"gpt-6-astra","outputTokens":4624,"runtime":"codex","turns":4,"wallClockMs":195088}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"0256823ae36e7900","findings":[{"citation":"resolved","description":"Prior finding 775217f696b17bbfae5e78f2759ac056b53cbb2ff409c29f4aecc8252ed666b9 remains reproducible. The author explicitly acknowledges the unresolved blocker and disputes only whether a manifest-only assignment can fix it; that scope limitation is valid, but does not establish deployability. launch.json still supplies fee 3000. AntiSnipeHook._afterInitialize calls _validatePool, whose src/AntiSnipeHook.sol:81 guard correctly requires a dynamic-fee pool. lib/v4-core/src/libraries/LPFeeLibrary.sol:15,30-31 accepts exactly 0x800000 (8388608), whereas the supplied LaunchManifest schema permits only 0..1000000. The accepted sets do not intersect. The BLOCKED notes disclose the problem but cannot override deployment fields. Initialization reverts atomically; this is a launch-compatibility blocker, not a loss-of-funds issue or a defect in the correct hook guard. No authorized deployment translation or revised schema/policy is supplied. Resolution requires separately authorized schema/policy and deployment-path support for 8388608, followed by a manifest using it, or an explicitly authorized and verified deployment translation. Preserve the hook guard. Merges the prior finding and audit_permissions duplicate.","line":16,"path":"launch.json","reproduction":"Re-ran forge test --offline --out /tmp/antisnipe-review-6a764074-out --cache-path /tmp/antisnipe-review-6a764074-cache --match-test test_staticFeeInitializationRevertsAndRollsBack -vvvv: 1 passed, 0 failed, 0 skipped. test/HookFixture.sol sets timestamp 1000000, deploys a real PoolManager and CREATE2 AntiSnipeHook with permission bits 0x1080, sorted SNIPE/QUOTE currencies, tickSpacing 60 and sqrtPriceX96 79228162514264337593543950336. test/AntiSnipeHook.t.sol:93 sets key.fee=3000 and calls manager.initialize. Actual trace: PoolManager.initialize -> afterInitialize -> DynamicFeeRequired, wrapped in CustomRevert.WrappedError(hook, IHooks.afterInitialize.selector, abi.encodeWithSelector(AntiSnipeHook.DynamicFeeRequired.selector), abi.encodeWithSelector(Hooks.HookCallFailed.selector)); antiSnipeEndsAt remains 0. Changing only fee to 8388608 succeeds, sets deadline 1003600 and returns beforeSwap fee 10000|0x400000. The test passes because it expects the rejection; it does not prove the manifest deployable. The author-reported scratch native-pair tests are absent from this tree. For the manifest native pair, use currency0=address(0), currency1=address(new AntiSnipeToken()), fee=3000, tickSpacing=60, hooks=hook and the same sqrtPriceX96: direct source tracing of PoolManager.initialize -> Hooks.afterInitialize -> BaseHook.afterInitialize -> _afterInitialize -> _validatePool reaches the identical unconditional fee guard, independently of currency addresses, and reverts. Expected: the supplied manifest initializes the pool and starts a 3600-second window. Actual: fee 3000 is rejected. Also re-ran Python Draft202012Validator with the exact canonical schema supplied in the assignment: unchanged manifest accepted; changing only pool.fee to 8388608 gives exactly one error at pool.fee: 8388608 is greater than the maximum of 1000000. Exact-equality isDynamicFee proves every schema-valid fee fails the hook guard. Full local regression: forge test --offline --out /tmp/antisnipe-review-6a764074-out --cache-path /tmp/antisnipe-review-6a764074-cache --summary completed successfully; 44 reported test groups across five suites passed, with zero failures or skips, including both invariant suites. The externally attested protected suites and target-chain deployment were not executed.","severity":"medium","snippet":"    \"fee\": 3000,","title":"Unresolved: manifest fee cannot initialize the required dynamic-fee hook"},{"citation":"resolved","description":"Prior advisory c45b7f64fa3d81053823832a67d02deb21879540e820c4c8e6a41380d0091b5a remains reproducible. README.md:29 still presents DEPENDENCIES.json as SHA-256 hashes of the vendored files, but 45 of 95 recorded hashes disagree with this tree, including Hooks.sol, PoolManager.sol and BaseHook.sol. All recorded files exist and no lib files are unlisted. Thus this record cannot verify the dependencies actually compiled offline. Hash mismatches alone do not prove malicious modification or a behavioral vulnerability. Retained as one low advisory, merging the prior advisory, audit_flow and audit_permissions. The separately authorized dependency-maintenance task should restore byte-identical pinned copies or record the shipped hashes and accurately describe any transformations.","line":29,"path":"DEPENDENCIES.json","reproduction":"Recomputed SHA-256 for every relative_path, expected_hash in each dependency files map using hashlib.sha256(Path(\"lib\", dependency[\"name\"], relative_path).read_bytes()).hexdigest(), comparing all entries in DEPENDENCIES.json and enumerating lib files. Expected: 95 matching hashes. Actual: 45 mismatches, 50 matches, 0 missing and 0 unlisted. In particular, sha256sum lib/v4-core/src/libraries/Hooks.sol returns a6cb7a613fecd8ce7cee7c2553cfbf537191a0e2d8fcaaaed104b44c0d1359ca; DEPENDENCIES.json:29 records 297d577998cdede64d48b47b12f15e4f442eea032fbb9676bb3c2f89da89b83c. sha256sum lib/v4-periphery/src/utils/BaseHook.sol returns e0a309e495eed81aae245fa80957b09ae8996e490bded6f3d7e98373fc3d5bf8; DEPENDENCIES.json:67 records 11b5cf3845e6f34974ce0a51eae87ba5f2aa9aa6ddbe8e7b42a86f578038dda5.","severity":"low","snippet":"      \"src/libraries/Hooks.sol\": \"297d577998cdede64d48b47b12f15e4f442eea032fbb9676bb3c2f89da89b83c\",","title":"Unresolved: dependency integrity record disagrees with 45 shipped files"}],"hash":"3868f6f844c08067972e3193615b38b25fe081f2dd7eba0a6e9affc0805ef45b","nodeId":"6a764074-0e5d-4ecc-a50e-15d3ca0824c3","outcome":"completed","summary":"Wrote [.imd-findings.json](/home/imd-worker/.identitymd/work/d8c77885-cfb8-4bf6-b33d-96b9aa10e0d9/6a764074-0e5d-4ecc-a50e-15d3ca0824c3/.imd-findings.json).\n\nBoth earlier findings remain reproducible:\n\n- **Medium:** manifest fee prevents initialization.\n- **Low:** 45 dependency hashes mismatch.\n\nDuplicates merged; all 13 entry points covered. All 44 local test groups passed. No new defects reported; protected suites were not executed.","treeHash":null,"usage":{"cachedInputTokens":677632,"inputTokens":93925,"model":"gpt-6-astra","outputTokens":7256,"runtime":"codex","turns":4,"wallClockMs":273065}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"fea57d3e9d0ca7bf","findings":[{"citation":"resolved","description":"Trust gap between the hook's hard requirement and the launch pipeline that must satisfy it. The hook only works on a dynamic-fee pool: v4 ignores the beforeSwap fee override on static-fee pools (lib/v4-core/src/libraries/Hooks.sol:284 `if (key.fee.isDynamicFee()) lpFeeOverride = result.parseFee();`), so _validatePool correctly reverts afterInitialize and beforeSwap unless key.fee == LPFeeLibrary.DYNAMIC_FEE_FLAG (0x800000 = 8,388,608). The LaunchManifest schema supplied with this assignment bounds pool.fee to an integer in [0, 1000000]. isDynamicFee() is an exact equality test, so no value a schema-valid launch.json can carry passes it, and the only value that passes cannot be written into launch.json. If the factory initializes the pool with the manifest's fee field verbatim, the single launch transaction (token deploy, hook deploy, initialize) reverts with WrappedError(hook, afterInitialize.selector, DynamicFeeRequired, HookCallFailed) and the launch cannot ship; if the deployer or factory silently maps the manifest value to the dynamic flag, that mapping is the undocumented load-bearing step and is not evidenced anywhere in this tree (README.md:51 instructs 'Pool fee field 0x800000 (8388608) exactly; do not put 3,000 or 10,000 here', which the schema rejects). No funds are at risk because the failure is an atomic revert, but the launch is blocked until the gap is closed. The hook-side check must stay: removing it would let a static-fee pool initialize and silently charge the static fee with no anti-snipe window. Needed evidence / fix: confirmation that apps/deployer or the factory ORs/sets LPFeeLibrary.DYNAMIC_FEE_FLAG for this hook (and which manifest value triggers that), or a schema/policy change that accepts 8388608 for pool.fee. Until one of those is shown, this hook has no valid manifest.","line":81,"path":"src/AntiSnipeHook.sol","reproduction":"State: PoolManager deployed; AntiSnipeHook CREATE2-deployed at an address carrying AFTER_INITIALIZE|BEFORE_SWAP (0x1080). Key: currency0 < currency1, tickSpacing 60, hooks = hook. Input: key.fee = any value in the schema range, e.g. 3000, 0 or the schema maximum 1_000_000. Call manager.initialize(key, 2**96). Expected (what a launch needs): pool initializes and antiSnipeEndsAt[poolId] = block.timestamp + 3600. Actual: revert CustomRevert.WrappedError(address(hook), IHooks.afterInitialize.selector, abi.encodeWithSelector(AntiSnipeHook.DynamicFeeRequired.selector), abi.encodeWithSelector(Hooks.HookCallFailed.selector)); antiSnipeEndsAt stays 0. Control: key.fee = 8_388_608 initializes and sets the deadline, but 8_388_608 > 1_000_000 fails the manifest schema's pool.fee maximum. Verified locally with test/scratch/ManifestFeeRange.t.sol (fuzz over all fees in [0,1_000_000] reverts; 0x800000 succeeds), 5/5 passing, on forge 1.8.3 / solc 0.8.26.","severity":"medium","snippet":"        if (!key.fee.isDynamicFee()) revert DynamicFeeRequired();","title":"Launch manifest schema cannot express the dynamic-fee pool key the hook requires; every schema-valid pool.fee makes the launch's initialize revert"},{"citation":"resolved","description":"Provenance trust gap. README.md:29 states that DEPENDENCIES.json 'records exact upstream commits and SHA-256 hashes for the vendored files' and that sources are 'retained without modifying upstream source'. Recomputing sha256 over lib/ shows 45 of 95 listed files do not match their recorded hash, including the files the hook's access control and fee path depend on: v4-periphery BaseHook.sol (the onlyPoolManager dispatch), v4-core Hooks.sol (callHook / beforeSwap fee parsing / permission validation), PoolManager.sol and Pool.sol (the swap fee override), HookMiner.sol, solmate ERC20.sol and most of forge-std. Fetching each file from its pinned upstream commit shows the recorded hashes are the true upstream hashes and the shipped copies are the ones that changed: every diff is a `forge fmt` reformat at the repository's line_length = 110 (line wraps, braces added around single-statement ifs, one comment spacing change) with no token-level semantic change. So the libraries are functionally upstream, but the integrity record cannot be used to prove that: anyone verifying DEPENDENCIES.json gets 45 failures and has to re-derive what I did (fetch upstream at the pinned commit and diff) to tell a reformat from a tamper. The 50 files that do match (ImmutableState.sol, LPFeeLibrary.sol, OpenZeppelin ERC20.sol, etc.) show the intended workflow is hash-then-vendor-verbatim; the fmt pass broke it. Fix: either re-vendor the 45 files byte-for-byte from the pinned commits (and exclude lib/ from `forge fmt`, e.g. via [fmt] ignore), or regenerate the hashes from the shipped files and state in README that vendored files are reformatted. Note the fix touches lib/ and DEPENDENCIES.json, which this review's rules do not let the reviewer change.","line":67,"path":"DEPENDENCIES.json","reproduction":"Input: the tree as committed. Run `sha256sum lib/v4-periphery/src/utils/BaseHook.sol` -> e0a309e495eed81aae245fa80957b09ae8996e490bded6f3d7e98373fc3d5bf8; DEPENDENCIES.json:67 records 11b5cf3845e6f34974ce0a51eae87ba5f2aa9aa6ddbe8e7b42a86f578038dda5. Likewise lib/v4-core/src/libraries/Hooks.sol -> a6cb7a613fecd8ce7cee7c2553cfbf537191a0e2d8fcaaaed104b44c0d1359ca vs recorded 297d5779... (DEPENDENCIES.json:29) and lib/v4-core/src/PoolManager.sol -> 586d7ef5af44f09a0a158129dec1a8d697fcb4efc8fc4b73deed76fb6e8f70e9 vs recorded 3b6ab111... (DEPENDENCIES.json:12). A loop over every entry in DEPENDENCIES.json reports 45 mismatches, 0 missing files, 0 unlisted files under lib/. Expected: every recorded hash equals the shipped file's hash. Actual: 45 do not. Cross-check: curl https://raw.githubusercontent.com/Uniswap/v4-periphery/444c526b77d804590f0d7bc5a481af5a3277c952/src/utils/BaseHook.sol | sha256sum -> 11b5cf38... (equals the recorded value), and diff against the shipped file shows only the beforeSwap signature re-wrapped across lines.","severity":"low","snippet":"      \"src/utils/BaseHook.sol\": \"11b5cf3845e6f34974ce0a51eae87ba5f2aa9aa6ddbe8e7b42a86f578038dda5\",","title":"DEPENDENCIES.json SHA-256 hashes do not match 45 of the 95 shipped vendored files; the shipped copies were reformatted after hashing"},{"citation":"resolved","description":"Deployment trust note, not an exploit. The extra constructor guard goes beyond BaseHook (which only validates the address permission bits) and makes deployability depend on the environment: creation code attested with the launch chain's PoolManager address M reverts with InvalidPoolManager anywhere M has no code. The supplied admission floor (.imd/reads/protected/univ4_hook/Hook.protected.t.sol:51-61) handles this by etching PoolManager runtime at IMD_POOL_MANAGER before CREATE2-deploying, but only when that env var is set; its address(0) fallback deploys a fresh manager at a different address and does not etch, in which case deployAtFlags hits `require(at != address(0), \"hook deployment reverted\")` and the whole floor fails in setUp rather than reporting per-test results. On the real chain M has code, so production deployment is unaffected. The check does not establish authenticity either (any contract passes), which README.md:75 already acknowledges. Recorded so the deployer and verifier know IMD_POOL_MANAGER must be supplied for this hook; no code change is required if that is already the pipeline's behaviour.","line":35,"path":"src/AntiSnipeHook.sol","reproduction":"State: an EVM where the address passed as `manager` has no code (e.g. a Foundry test that did not etch; or the protected harness run without IMD_POOL_MANAGER against creation code baked with a mainnet manager address). Input: new AntiSnipeHook{salt: s}(IPoolManager(0x1234)) with s mined so the address carries 0x1080. Expected for a plain BaseHook: deployment succeeds (permission bits valid). Actual: revert AntiSnipeHook.InvalidPoolManager(). Demonstrated by the delivered test test_constructorRejectsZeroOrCodelessManager in test/AntiSnipeHook.t.sol:192-199, which passes for both address(0) and address(0x1234).","severity":"info","snippet":"        if (address(manager) == address(0) || address(manager).code.length == 0) revert InvalidPoolManager();","title":"Constructor refuses a manager address that has no code in the executing VM; the attested creation code only deploys in harnesses that etch code at the baked-in PoolManager address"}],"hash":"62b27d4fa56e591539a30206a86d4b7d6cfb6871818288f55aa4dd041802f454","nodeId":"137c78e7-67d2-4394-af70-4708efbf6e4c","outcome":"completed","summary":"The review is complete. The findings file is in place at the repository root, excluded from git by the repository's own `.git/info/exclude`, and no tracked file was changed.\n\n**Outcome:** the hook's permission model holds. Every callback is behind BaseHook's PoolManager check, the one storage slot has a single writer that the PoolManager can only reach once per pool, the fee branch is symmetric across callers, directions and swap modes, and there is no path by which the hook becomes `msg.sender` to the PoolManager, which is the one way v4 would skip the fee override. I found no access-control or asymmetry defect in the Solidity. The three findings are trust gaps around the code rather than in it.\n\n**Findings written to `.imd-findings.json`:**\n\n- **Medium, manifest fee range.** The hook only accepts a pool whose fee field is the dynamic-fee sentinel 8,388,608, and correctly reverts otherwise because v4 ignores the beforeSwap override on static-fee pools. The launch manifest schema caps `pool.fee` at 1,000,000. So no schema-valid manifest can initialize this pool, and the only value that works fails the schema. If the factory passes the manifest fee verbatim, the launch transaction reverts atomically. Verified with a scratch fuzz test over the full schema range. The fix belongs in the deployer or schema, not the hook, and I said what evidence would close it.\n- **Low, dependency provenance.** 45 of the 95 vendored files do not match the SHA-256 hashes in DEPENDENCIES.json, including BaseHook, Hooks, PoolManager and Pool. I fetched each file from its pinned upstream commit: the recorded hashes are the true upstream hashes and the shipped copies were reformatted by `forge fmt`. Every diff is whitespace, line wrapping or added braces, with no semantic change. The libraries are functionally upstream, but the README's integrity claim cannot be verified from the record as shipped.\n- **Info, constructor code check.** The constructor refuses a manager address without code, so the attested creation code only deploys in harnesses that etch the PoolManager at the baked-in address. The supplied admission floor does this when `IMD_POOL_MANAGER` is set. Noted so the pipeline supplies it.\n\n**Coverage:** all 13 listed entry points have rows, 12 `holds` and `afterInitialize` tagged to finding 1, plus six invariant rows including the slither timestamp lead, which I judged not reportable because only a trusted block producer could move a swap across the one-hour boundary. The only `unreached` row is the launch manifest itself, since no launch.json exists in the tree yet.\n\nNo proof files were attached. Nothing reached high severity, and a test for the medium finding cannot be made to fail now and pass after a correct fix, because the right fix is outside the hook.","treeHash":null,"usage":{"cachedInputTokens":1320676,"inputTokens":322,"model":"claude-fable-5-1","outputTokens":35265,"runtime":"claude","turns":38,"wallClockMs":523390}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"feba2a869621cab2","findings":[],"hash":"75d905c2cef6e15f5771d8d8ee258e6760dbdb12f493b95506f81850128e9875","nodeId":"bac2923e-0789-417b-8394-45ccc75213f9","outcome":"completed","summary":"The review is complete. No defects found in the assigned area, and the findings file holds an empty list with full coverage.\n\n**Outcome:** `.imd-findings.json` contains zero findings and 17 coverage rows, one for each of the 13 listed entry points plus four invariants I checked. All 13 entry points are marked `holds`. The repository tree is unchanged.\n\n**What I checked against the Math Precision, Boundary and Numerical Gap guides:**\n\n- **Fee units and override encoding.** The constants are 10,000 and 3,000 pips on a 1,000,000 scale, so 1% and 0.3% exactly. Both pass the manager's cap check after the override flag is removed.\n- **Deadline arithmetic.** The deadline is timestamp plus 3600 in uint256. It is never zero, so the zero sentinel is safe, and it works at timestamp 0 and at the uint64 maximum. It only overflows at a timestamp no chain can reach.\n- **Strict boundary at one hour.** Seconds 0 through 3599 pay 1% and second 3600 onward pays 0.3%. This matches the brief's \"first hour\" and the README's table.\n- **Executed swap equivalence.** Swaps through the hook produce identical balance deltas and fee growth to an equivalent static-fee pool. I verified this with the protocol fee set to its 0.1% maximum in both directions, with 1-wei exact-input and exact-output swaps, and across the existing fuzzed ranges.\n- **Zero-fee bypass.** The manager stores an LP fee of zero for this pool, so any swap that skipped the hook would be free. The only skip condition is the hook itself being the swap sender, which is unreachable because the hook has no unlock callback, fallback, or swap-calling code.\n- **Token arithmetic.** The token is unmodified OpenZeppelin ERC-20 with a fixed supply of 10^27 minor units and no scaling math.\n\n**Static analysis leads:** The timestamp-comparison warning is the intended schedule mechanism, not a defect. The large-numeric-literal and internal-function-used-once notes are style only.\n\n**Not covered:** I did not go beyond the math, boundary and numerical-gap guides into access control, economics or trust assumptions except where the fee bypass invariant required it. The 1-wei exact-input swap consumes its whole input as fee, which is v4-core's own rounding and applies equally to any static-fee pool.","treeHash":null,"usage":{"cachedInputTokens":892487,"inputTokens":290,"model":"claude-fable-5-1","outputTokens":17851,"runtime":"claude","turns":28,"wallClockMs":284700}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"0256823ae36e7900","findings":[],"hash":"7f28e610b579e205a14ce4600fde95a8b32ff9bdf79693d0f733ba6e19b7b9ac","nodeId":"46faf5f6-18ac-43be-b4c2-549a524b6830","outcome":"no_change","summary":"The blocker reproduces: the hook requires fee `8388608`, while the schema caps it at `1000000`. No manifest-only fix satisfies both.\n\nLeft `launch.json` unchanged and recorded the unresolved finding in [.imd-responses.json](/home/imd-worker/.identitymd/work/d8c77885-cfb8-4bf6-b33d-96b9aa10e0d9/46faf5f6-18ac-43be-b4c2-549a524b6830/.imd-responses.json).\n\n`forge build` and all 39 local tests passed, including the rejection reproductions. Deployment remains blocked pending schema and deployment-path support.","treeHash":null,"usage":{"cachedInputTokens":518144,"inputTokens":38018,"model":"gpt-6-astra","outputTokens":5678,"runtime":"codex","turns":4,"wallClockMs":220205}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"0256823ae36e7900","findings":[{"citation":"resolved","description":"The accepted manifest sets pool.fee to 3000. AntiSnipeHook._afterInitialize calls _validatePool, whose src/AntiSnipeHook.sol:81 guard requires key.fee.isDynamicFee(); the vendored LPFeeLibrary accepts only 0x800000 (8388608). Thus using the manifest's pool fields to initialize the pool reverts. The supplied LaunchManifest schema caps pool.fee at 1000000, so no schema-valid replacement can satisfy this hook. The notes explicitly acknowledge the placeholder but, under the supplied launch boundary, cannot override deployment fields. This blocks launch before funds move; it is not a reason to remove the hook's correct dynamic-fee check. The schema/policy and deployment path need explicit support for 8388608, followed by a manifest with that value, or evidence of an authorized, defined dynamic-fee translation in the deployment path. No such translation is supplied.","line":16,"path":"launch.json","reproduction":"Executed the existing test/AntiSnipeHook.t.sol::test_staticFeeInitializationRevertsAndRollsBack as part of `forge test --offline --out /tmp/antisnipe-review-out --cache-path /tmp/antisnipe-review-cache --summary` (all 44 reported test groups passed, no failures or skips). Its fixture sets timestamp=1000000, deploys the real PoolManager, CREATE2-deploys AntiSnipeHook at a valid 0x1080 permission address, and uses sorted SNIPE/QUOTE currencies, tickSpacing=60 and sqrtPriceX96=2**96. With key.fee=3000, manager.initialize reverts with CustomRevert.WrappedError(address(hook), IHooks.afterInitialize.selector, abi.encodeWithSelector(AntiSnipeHook.DynamicFeeRequired.selector), abi.encodeWithSelector(Hooks.HookCallFailed.selector)); antiSnipeEndsAt remains zero. The test passes because it asserts this rejection, rather than successful launch. Changing only fee to 8388608 initializes successfully and quotes 10000. Expected for the delivered manifest: its pool parameters initialize successfully and establish a 3600-second window; actual fee=3000 is rejected. For the exact manifest native pair, use currency0=address(0), currency1=address(new AntiSnipeToken()), fee=3000, tickSpacing=60, hooks=hook and sqrtPriceX96=79228162514264337593543950336: tracing PoolManager.initialize reaches the identical afterInitialize guard independently of currency addresses, and rolls back. LPFeeLibrary.isDynamicFee compares fee for exact equality with 8388608, proving every fee in the supplied schema range 0..1000000 fails that guard; 8388608 cannot pass the supplied manifest schema.","severity":"medium","snippet":"    \"fee\": 3000,","title":"The manifest's static pool fee cannot initialize the required dynamic-fee hook"},{"citation":"resolved","description":"README.md:29 presents DEPENDENCIES.json as the SHA-256 record for the vendored files. Recomputing these hashes against this tree yields 45 mismatches out of 95 entries, with no missing or unlisted library files. This includes Hooks.sol, PoolManager.sol and BaseHook.sol, so the declared integrity record cannot verify the dependencies actually compiled offline. This is an integrity/documentation defect; a hash mismatch alone does not establish a malicious or behavioral change. Merge of the duplicate audit_flow and audit_permissions reports. The responsible dependency-maintenance task should either restore byte-identical pinned files or record the shipped hashes and disclose any transformations; the reviewer has not changed these protected files.","line":29,"path":"DEPENDENCIES.json","reproduction":"From this repository run `sha256sum lib/v4-core/src/libraries/Hooks.sol`. Expected from DEPENDENCIES.json:29: 297d577998cdede64d48b47b12f15e4f442eea032fbb9676bb3c2f89da89b83c. Actual: a6cb7a613fecd8ce7cee7c2553cfbf537191a0e2d8fcaaaed104b44c0d1359ca. Independently, `sha256sum lib/v4-periphery/src/utils/BaseHook.sol` returns e0a309e495eed81aae245fa80957b09ae8996e490bded6f3d7e98373fc3d5bf8 instead of the recorded 11b5cf3845e6f34974ce0a51eae87ba5f2aa9aa6ddbe8e7b42a86f578038dda5. Iterating all dependency file entries and hashing lib/<dependency>/<file> reproduces 45 unequal hashes among 95 existing files.","severity":"low","snippet":"      \"src/libraries/Hooks.sol\": \"297d577998cdede64d48b47b12f15e4f442eea032fbb9676bb3c2f89da89b83c\",","title":"The dependency integrity record disagrees with 45 shipped files"}],"hash":"dd206ec6ef13d2edb4ee9e654d59cb5bb9fe735a0252e2f46bc918f5d1d2e9ee","nodeId":"6a764074-0e5d-4ecc-a50e-15d3ca0824c3","outcome":"completed","summary":"Wrote [.imd-findings.json](/home/imd-worker/.identitymd/work/d8c77885-cfb8-4bf6-b33d-96b9aa10e0d9/6a764074-0e5d-4ecc-a50e-15d3ca0824c3/.imd-findings.json) with two reproduced, deduplicated findings:\n\n- **Medium:** Manifest fee cannot initialize the dynamic-fee hook.\n- **Low:** 45 dependency hashes mismatch shipped files.\n\nCoverage: **13/13 entry points**. Offline Foundry suite passed.","treeHash":null,"usage":{"cachedInputTokens":1016576,"inputTokens":94328,"model":"gpt-6-astra","outputTokens":7884,"runtime":"codex","turns":4,"wallClockMs":322040}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"0256823ae36e7900","findings":[{"citation":"resolved","description":"Prior finding 0df0adbd3e7af706e641e702a0f456756de2c7435d9af39776b85521b1e9811f remains unresolved. The author's response agrees that the defect reproduces and disputes only whether it can be fixed within a manifest-only assignment; that scope limitation is valid but does not make this manifest deployable. AntiSnipeHook._afterInitialize calls _validatePool, whose src/AntiSnipeHook.sol:81 guard requires key.fee.isDynamicFee(). The vendored LPFeeLibrary accepts only 0x800000 (8388608), whereas launch.json supplies 3000 and the supplied LaunchManifest schema permits only 0..1000000. Thus no schema-valid fee can initialize this hook. The notes acknowledge the placeholder but cannot override deployment fields. Initialization reverts atomically before funds move; this is a launch-compatibility blocker, not a defect in the hook's dynamic-fee guard. Resolution requires separately authorized schema/policy and deployment-path support for 8388608 followed by a manifest using it, or evidence of an authorized, defined deployment translation. None is supplied. Keep the correct hook-side guard. Merges the prior finding and audit_permissions report.","line":16,"path":"launch.json","reproduction":"Re-ran forge test --offline --out /tmp/antisnipe-rereview-out --cache-path /tmp/antisnipe-rereview-cache --match-test test_staticFeeInitializationRevertsAndRollsBack -vvvv: 1 passed, 0 failed, 0 skipped. In test/HookFixture.sol, timestamp=1000000, real PoolManager, CREATE2-deployed AntiSnipeHook with address mask 0x1080, sorted SNIPE/QUOTE currencies, tickSpacing=60, sqrtPriceX96=79228162514264337593543950336. test/AntiSnipeHook.t.sol:93 sets key.fee=3000 and calls manager.initialize. Actual trace: afterInitialize reverts DynamicFeeRequired, wrapped as CustomRevert.WrappedError(hook, IHooks.afterInitialize.selector, abi.encodeWithSelector(AntiSnipeHook.DynamicFeeRequired.selector), abi.encodeWithSelector(Hooks.HookCallFailed.selector)); antiSnipeEndsAt remains 0. Changing only fee to 8388608 succeeds, sets deadline=1003600 and returns beforeSwap fee=10000|0x400000. The test passes because it expects the rejection; it does not prove the manifest launches. For the manifest's exact native pair, set currency0=address(0), currency1=address(new AntiSnipeToken()), fee=3000, tickSpacing=60, hooks=hook and the same sqrtPriceX96: source trace PoolManager.initialize -> Hooks.afterInitialize -> BaseHook.afterInitialize -> _afterInitialize -> _validatePool reaches the identical unconditional fee guard, independently of currency addresses, and rolls back. Expected: manifest fields successfully initialize and start the 3600-second window. Actual: fee=3000 is rejected. LPFeeLibrary.isDynamicFee is exact equality with 8388608, proving every fee <=1000000 in the supplied schema fails; the only accepted value exceeds the schema maximum. The author's temporary native-pair tests are not present in this tree, so this re-review reruns the available reproduction and explicitly traces the native-pair case. Also re-ran Draft202012Validator against the canonical schema supplied in the assignment: the delivered manifest is accepted; changing only pool.fee to 8388608 produces exactly one error, '8388608 is greater than the maximum of 1000000' at pool.fee. The full local command forge test --offline --out /tmp/antisnipe-rereview-out --cache-path /tmp/antisnipe-rereview-cache --summary passed all 44 reported test groups, with no failures or skips, including both invariant suites. The externally attested protected suites and target-chain deployment were not executed.","severity":"medium","snippet":"    \"fee\": 3000,","title":"The manifest's static pool fee still cannot initialize the required dynamic-fee hook"},{"citation":"resolved","description":"Prior advisory e217d1fdc7880b545679e7ef3b098bbe1dcf4ad4217b7a11161e4f61de828aa2 remains reproducible. README.md:29 presents DEPENDENCIES.json as SHA-256 hashes for the vendored files, but 45 of its 95 recorded hashes differ from this tree, including Hooks.sol, PoolManager.sol and BaseHook.sol. All listed files exist and no library files are unlisted. The record therefore cannot verify the dependencies actually compiled offline. Hash mismatches alone do not establish malicious changes or a behavioral vulnerability. Merge of duplicate audit_flow and audit_permissions reports; retain as low advisory. The responsible dependency-maintenance task should restore byte-identical pinned copies or record the shipped hashes and accurately document any transformations; no protected files were changed by this review.","line":29,"path":"DEPENDENCIES.json","reproduction":"Against the current tree, sha256sum lib/v4-core/src/libraries/Hooks.sol returns a6cb7a613fecd8ce7cee7c2553cfbf537191a0e2d8fcaaaed104b44c0d1359ca; expected DEPENDENCIES.json:29 is 297d577998cdede64d48b47b12f15e4f442eea032fbb9676bb3c2f89da89b83c. sha256sum lib/v4-periphery/src/utils/BaseHook.sol returns e0a309e495eed81aae245fa80957b09ae8996e490bded6f3d7e98373fc3d5bf8; expected DEPENDENCIES.json:67 is 11b5cf3845e6f34974ce0a51eae87ba5f2aa9aa6ddbe8e7b42a86f578038dda5. Recompute hashlib.sha256(Path('lib', dependency['name'], relative_path).read_bytes()).hexdigest() for every relative_path, expected_hash in each dependency['files'] from json.loads(Path('DEPENDENCIES.json').read_text()). Expected: 95 equal hashes. Actual: 45 mismatches among 95 entries, 0 missing and 0 unlisted lib files.","severity":"low","snippet":"      \"src/libraries/Hooks.sol\": \"297d577998cdede64d48b47b12f15e4f442eea032fbb9676bb3c2f89da89b83c\",","title":"The dependency integrity record still disagrees with 45 shipped files"}],"hash":"e603d9dfd2454a6cdd33c94846b3c75356952426fda12bef8409742b6100605b","nodeId":"6a764074-0e5d-4ecc-a50e-15d3ca0824c3","outcome":"completed","summary":"Wrote [.imd-findings.json](/home/imd-worker/.identitymd/work/d8c77885-cfb8-4bf6-b33d-96b9aa10e0d9/6a764074-0e5d-4ecc-a50e-15d3ca0824c3/.imd-findings.json).\n\nBoth prior findings remain reproducible: the medium manifest blocker and low dependency-hash advisory. Duplicates merged; no new findings.\n\nCoverage: 13/13 entry points. All 44 local test groups passed. Source and configuration files unchanged.","treeHash":null,"usage":{"cachedInputTokens":1191936,"inputTokens":105764,"model":"gpt-6-astra","outputTokens":6901,"runtime":"codex","turns":5,"wallClockMs":280441}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"cbc83f8151b8340d","findings":[{"citation":"resolved","description":"Periphery/provenance. DEPENDENCIES.json is presented (README.md line 29: 'records exact upstream commits and SHA-256 hashes for the vendored files. Source subsets and license files are retained without modifying upstream source.') as the way an offline verifier confirms that the code under lib/ is the pinned upstream code. The recorded hashes are the hashes of the upstream files at the pinned commits (verified by fetching each file from GitHub at the recorded commit), but 45 of the 95 recorded files committed under lib/ were reformatted after the hashes were taken, so their SHA-256 differs from the record. Affected files include every manager-side file the hook's control flow depends on: lib/v4-core/src/PoolManager.sol, lib/v4-core/src/libraries/Hooks.sol, lib/v4-core/src/libraries/Pool.sol, lib/v4-periphery/src/utils/BaseHook.sol, lib/v4-periphery/src/utils/HookMiner.sol, plus forge-std, solmate and v4-core test helpers. I compared every mismatched file with its upstream copy: 41 differ only in whitespace, and the other 4 (PoolManager.sol, Hooks.sol, SqrtPriceMath.sol, PoolModifyLiquidityTest.sol) differ only by braces added around single-statement if bodies, i.e. forge fmt output at the project's 110-column limit. No semantic change to the vendored code was found, so hook behaviour is unaffected. The defect is that the integrity record cannot verify the tree it ships with: a reviewer or the admission step recomputing hashes over lib/ gets 45 failures and cannot distinguish this benign reformat from a tampered dependency, and the README statement that upstream source is unmodified is false. Fix: either re-vendor the 45 files byte-for-byte from upstream (and exclude lib/ from forge fmt), or regenerate the hashes from the committed files and state in README that the copies are reformatted.","line":29,"path":"DEPENDENCIES.json","reproduction":"In the repository root run: sha256sum lib/v4-core/src/libraries/Hooks.sol  -> a6cb7a613fecd8ce7cee7c2553cfbf537191a0e2d8fcaaaed104b44c0d1359ca. DEPENDENCIES.json line 29 records 297d577998cdede64d48b47b12f15e4f442eea032fbb9676bb3c2f89da89b83c for that file. Expected: equal. Actual: different. Same for lib/v4-core/src/PoolManager.sol (committed 586d7ef5..., recorded 3b6ab111... at line 12) and lib/v4-periphery/src/utils/BaseHook.sol (committed e0a309e4..., recorded 11b5cf38... at line 67). A script iterating every entry of DEPENDENCIES.json and hashing lib/<name>/<path> reports 45 mismatches out of 95 entries and 0 missing files. Fetching https://raw.githubusercontent.com/Uniswap/v4-core/a7cf038cd568801a79a9b4cf92cd5b52c95c8585/src/libraries/Hooks.sol and hashing it yields exactly the recorded 297d5779..., proving the record describes upstream and not the committed copy; diff -w against the fetched file shows only line re-wrapping and added braces.","severity":"low","snippet":"      \"src/libraries/Hooks.sol\": \"297d577998cdede64d48b47b12f15e4f442eea032fbb9676bb3c2f89da89b83c\",","title":"DEPENDENCIES.json hashes do not match the committed vendored library files (45 of 95 reformatted after hashing)"}],"hash":"e8c9a58b4190b9f3e7f9aff2e945cad3f7f413ca814ee618257d1ce1a5c576ca","nodeId":"9487968d-0895-4470-b3ab-8af536489899","outcome":"completed","summary":"The findings file is on disk at the repository root and is hidden from git by the harness's own exclude rule, which is expected. The review is complete and nothing further depends on another result.\n\n## Review outcome\n\nThe hook's control flow is sound in the assigned area. I found one low-severity defect, in the dependency provenance record rather than in the contracts, and wrote it with a full coverage record to `.imd-findings.json`.\n\n**What I covered**\n\n- **Execution Trace.** Traced `initialize` through `Hooks.afterInitialize` into the hook's single storage write, and `swap` through `Hooks.beforeSwap`, `ParseBytes.parseFee` and `Pool.swap` to the applied fee. The returned 96-byte tuple is parsed only because the pool is dynamic-fee, and that state is enforced at initialization since a static-fee key makes the hook revert and the whole initialize roll back. The first swap in the same transaction as initialization already pays 1%. A protocol fee combines with, but does not alter, the 1% and 0.3% LP schedule. All of these were confirmed with a scratch Foundry test that passed.\n- **Periphery.** `BaseHook` gates every callback on the immutable manager, the eight unused callbacks revert for everyone, `HookFlags` masks the correct 14 bits, and `HookMiner` is used with exact-flag matching. The token is unmodified OpenZeppelin v5 ERC-20 and its vendored copy matches its recorded hash.\n- **First Principles.** No path leaves a live pool without a deadline, so no pool can be bricked. The deadline is never zero after the write. Reinitialization is blocked by the manager before the hook runs. The window keyed on initialization rather than liquidity is documented and matches the brief.\n\n**The finding**\n\nThe dependency record does not describe the committed tree. The recorded SHA-256 values match the upstream files at the pinned commits, which I confirmed by fetching each one, but 45 of the 95 vendored files were reformatted after hashing and no longer match. I diffed every mismatched file against upstream: 41 differ only in whitespace and 4 differ only by braces added around one-line `if` bodies. No semantic change exists, so runtime behaviour is unaffected. The defect is that an offline verifier recomputing hashes over the vendored code gets 45 failures and cannot tell this benign reformat from tampering, and the README claim that upstream source is unmodified is false.\n\n**Static-analysis leads.** The Slither timestamp warning and both Aderyn notes were checked and are not defects. They are recorded as coverage rows.\n\n**Coverage.** All 13 listed entry points have a row, 12 marked `holds` and none unreached, plus 7 rows for invariants, leads and the one finding. Nothing in `src/`, `test/` or configuration was changed. The scratch test lives under the gitignored scratch directory.","treeHash":null,"usage":{"cachedInputTokens":1888840,"inputTokens":482,"model":"claude-fable-5-1","outputTokens":30387,"runtime":"claude","turns":41,"wallClockMs":486395}},{"artifacts":[],"attempt":1,"bundleHash":"4ccb1b4d3580844b783379ee34f337251d73ba578dd05d0c463386bb271fd030","device":"35c52a5b502e847c","findings":[],"hash":"eb8cf80113b2bbc5e34c7ad35c71d51cbc1d2b693d1bddce64c5209cf35f1ff9","nodeId":"d62115fa-a178-4515-9736-9a25f0e47c59","outcome":"completed","summary":"Implemented the ownerless hook: 1% LP fee for the first hour, then 0.3% at exactly 3,600 seconds, through `beforeSwap` with no swap-time storage writes.\n\nAdded the fixed-supply token, vendored dependencies, mining helper, and [deployment documentation](/home/identitymd5/.identitymd/work/d8c77885-cfb8-4bf6-b33d-96b9aa10e0d9/d62115fa-a178-4515-9736-9a25f0e47c59/README.md).\n\nVerified with Solidity 0.8.26: `forge build`, all 37 tests, and `forge fmt --check` pass, including an offline clean-copy run.","treeHash":"24554fb0d80e582dd0e890e4281e88dd66771175","usage":{"cachedInputTokens":1100928,"inputTokens":82080,"model":"gpt-6-astra","outputTokens":21281,"runtime":"codex","turns":6,"wallClockMs":699772}}],"verification":[{"checks":[{"durationMs":9837,"exitCode":0,"name":"build","output":"Compiling 90 files with Solc 0.8.26\nSolc 0.8.26 finished in 9.32s\nCompiler run successful!\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/AntiSnipeHook.sol:70:22\n   │\n70 │         uint24 fee = block.timestamp < endsAt ? INITIAL_LP_FEE : STANDARD_LP_FEE;\n   │                      ━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\n","passed":true},{"durationMs":57424,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 9 tests for test/AntiSnipeToken.t.sol:AntiSnipeTokenTest\n[PASS] testFuzz_mintsToAnyDeployer(address) (runs: 256, μ: 18135, ~: 18135)\n[PASS] testFuzz_transferMovesExactAmountAndConservesSupply(uint256) (runs: 256, μ: 89839, ~: 89811)\nLogs:\n  Bound result 318000051159799358220561393\n\n[PASS] test_fixedSupplyAndMetadata() (gas: 52795)\n[PASS] test_noMintBurnOwnerPauseFeeOrUpgradeSelectors() (gas: 679380)\n[PASS] test_rejectsOverdraftAndZeroRecipient() (gas: 64088)\n[PASS] test_runtimeHasNoEscapeOpcodes() (gas: 1019374)\n[PASS] test_selfTransferAndZeroTransferDoNotChangeSupply() (gas: 91393)\n[PASS] test_transferCannotSpendAnotherAccountWithoutApproval() (gas: 33550)\n[PASS] test_transferFromConsumesAllowance() (gas: 140315)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 14.63ms (36.80ms CPU time)\n\nRan 11 tests for test/AntiSnipeIntegration.t.sol:AntiSnipeIntegrationTest\n[PASS] testFuzz_actualSwapsMatchStaticPool(uint32,bool,bool,uint96) (runs: 256, μ: 751005, ~: 754606)\nLogs:\n  Bound result 10\n  Bound result 99999999999999999056\n\n[PASS] test_badPriceLimitRevertsWithoutChangingTimerOrBalances() (gas: 120747)\n[PASS] test_exactInputAfterHourInReverseDirection() (gas: 736314)\n[PASS] test_exactInputAtHour() (gas: 750177)\n[PASS] test_exactInputAtInitialization() (gas: 750157)\n[PASS] test_exactInputJustBeforeHourInReverseDirection() (gas: 736271)\n[PASS] test_exactOutputAtHourInReverseDirection() (gas: 737662)\n[PASS] test_exactOutputBeforeHour() (gas: 747648)\n[PASS] test_failedSettlementRollsBackSwap() (gas: 218807)\n[PASS] test_fullLifecycleEarnsLPFeesAndConservesTokens() (gas: 717171)\n[PASS] test_noCallerCanChangeStoredLPFee() (gas: 75425)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 404.14ms (244.10ms CPU time)\n\nRan 17 tests for test/AntiSnipeHook.t.sol:AntiSnipeHookTest\n[PASS] testFuzz_feeIndependentOfSenderDataAndSwapParameters(uint64,bool,int128,address,bytes) (runs: 256, μ: 140887, ~: 140795)\n[PASS] testFuzz_unauthorizedCallbacksCannotStartOrResetTimer(address) (runs: 256, μ: 77657, ~: 77657)\n[PASS] test_callbackRejectsStaticFeeAndMalformedDynamicFlag() (gas: 190500)\n[PASS] test_constructorRejectsWrongPermissionAddress() (gas: 11667)\n[PASS] test_constructorRejectsZeroOrCodelessManager() (gas: 68485767)\n[PASS] test_disabledCallbacksRevertEvenFromManager() (gas: 452100)\n[PASS] test_feeAtInitializationAndHourBoundary() (gas: 263173)\n[PASS] test_initializationAtTimestampZeroIsSupported() (gas: 183340)\n[PASS] test_noAdministrativeSelectors() (gas: 267934)\n[PASS] test_permissionsMatchDeployedAddress() (gas: 2008742)\n[PASS] test_poolsHaveIndependentClocks() (gas: 296968)\n[PASS] test_predictedPoolCannotInitializeBeforeHookExists() (gas: 48688699)\n[PASS] test_reinitializationCannotRestartExpiredWindow() (gas: 210466)\n[PASS] test_staticFeeInitializationRevertsAndRollsBack() (gas: 216567)\n[PASS] test_uninitializedPoolCannotReceiveFeeQuote() (gas: 45929)\n[PASS] test_windowStartsAtPoolInitializationNotHookDeployment() (gas: 153727)\n[PASS] test_wrongHookKeyRejected() (gas: 68616)\nSuite result: ok. 17 passed; 0 failed; 0 skipped; finished in 813.09ms (1.29s CPU time)\n\nRan 5 tests for test/AntiSnipeTokenInvariant.t.sol:AntiSnipeTokenInvariantTest\n[PASS]\nAntiSnipeTokenInvariantTest invariants:\n[PASS] invariant_allowancesOnlyChangeByApprovalOrAuthorizedSpend\n[PASS] invariant_fixedSupplyEqualsAllBalances\n AntiSnipeTokenInvariantTest invariants (runs: 256, calls: 32768, reverts: 0)\n\n╭-----------------------+-----------------------+-------+---------+----------╮\n| Contract              | Selector              | Calls | Reverts | Discards |\n+============================================================================+\n| AntiSnipeTokenHandler | approve               | 5438  | 0       | 0        |\n|-----------------------+-----------------------+-------+---------+----------|\n| AntiSnipeTokenHandler | rejectOverdraft       | 5459  | 0       | 0        |\n|-----------------------+-----------------------+-------+---------+----------|\n| AntiSnipeTokenHandler | rejectUnapprovedSpend | 5500  | 0       | 0        |\n|-----------------------+-----------------------+-------+---------+----------|\n| AntiSnipeTokenHandler | rejectZeroRecipient   | 5394  | 0       | 0        |\n|-----------------------+-----------------------+-------+---------+----------|\n| AntiSnipeTokenHandler | transfer              | 5508  | 0       | 0        |\n|-----------------------+-----------------------+-------+---------+----------|\n| AntiSnipeTokenHandler | transferFrom          | 5469  | 0       | 0        |\n╰-----------------------+-----------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 42760162074993\n  Bound result 4660\n  Bound result 508\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 426\n  Bound result 8388608\n  Bound result 0\n  Bound result 10000\n  Bound result 391\n  Bound result 0\n  Bound result 101\n  Bound result 807388989318440526850892873\n  Bound result 8\n  Bound result 2761333\n  Bound result 1241\n  Bound result 53261\n  Bound result 53261\n  Bound result 2441042\n  Bound result 0\n  Bound result 6065\n  Bound result 383465076497088859245450647\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 5443\n  Bound result 0\n  Bound result 306581263585026640284197844\n  Bound result 3000000000000000000\n  Bound result 185278145723097255497733870\n  Bound result 98231090745875862927581577\n  Bound result 95\n  Bound result 0\n  Bound result 112658795762627694558\n  Bound result 3382\n  Bound result 511691432372828525235078901\n  Bound result 294450683808915234985151947\n  Bound result 0\n  Bound result 145138982472716446180358757\n  Bound result 7000000000000000000\n  Bound result 98499493451085971660068715\n  Bound result 97\n  Bound result 0\n  Bound result 1525\n  Bound result 100000000000000000000\n  Bound result 336825587475458384730729174\n  Bound result 2767\n  Bound result 10000000000000000000\n  Bound result 9113\n  Bound result 2575\n  Bound result 3000000000000000000\n  Bound result 0\n  Bound result 52217893169683068955754533\n  Bound result 7424\n  Bound result 0\n  Bound result 1460\n  Bound result 8388609\n  Bound result 402\n  Bound result 60\n  Bound result 3\n  Bound result 8573\n  Bound result 8391608\n  Bound result 97481704013954186\n  Bound result 4\n  Bound result 8100\n  Bound result 37970076302728033437310506\n  Bound result 3758\n  Bound result 228162514264337593543950257\n  Bound result 0\n  Bound result 3\n  Bound result 39201769780667610652\n  Bound result 20534599210912912091993523\n  Bound result 0\n  Bound result 7\n  Bound result 8388609\n\n[PASS] test_failedTransferFromRestoresAllowance() (gas: 818999)\nLogs:\n  Bound result 1\n\n[PASS] test_infiniteApprovalSurvivesFullSupplySpendThenRevocation() (gas: 1024207)\nLogs:\n  Bound result 1000000000000000000000000000\n  Bound result 1000000000000000000000000000\n\n[PASS] test_zeroAddressCannotReceiveEvenZeroOrBeApproved() (gas: 761927)\nLogs:\n  Bound result 0\n\n[PASS] test_zeroOneAndFullSupplyTransfers() (gas: 504222)\nLogs:\n  Bound result 0\n  Bound result 1\n  Bound result 999999999999999999999999999\n  Bound result 1000000000000000000000000000\n  Bound result 1000000000000000000000000000\n\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 24.77s (24.77s CPU time)\n\nRan 2 tests for test/AntiSnipeSequenceInvariant.t.sol:AntiSnipeSequenceInvariantTest\n[PASS]\nAntiSnipeSequenceInvariantTest invariants:\n[PASS] invariant_eachPoolKeepsItsOriginalWindowAndFee\n[PASS] invariant_settlementConservesAllValueAndLeavesNoHookCustody\n AntiSnipeSequenceInvariantTest invariants (runs: 256, calls: 32768, reverts: 0)\n\n╭--------------------------+-----------------------------+-------+---------+----------╮\n| Contract                 | Selector                    | Calls | Reverts | Discards |\n+=====================================================================================+\n| AntiSnipeSequenceHandler | advanceTime                 | 5441  | 0       | 0        |\n|--------------------------+-----------------------------+-------+---------+----------|\n| AntiSnipeSequenceHandler | collectFees                 | 5567  | 0       | 0        |\n|--------------------------+-----------------------------+-------+---------+----------|\n| AntiSnipeSequenceHandler | initialize                  | 5437  | 0       | 0        |\n|--------------------------+-----------------------------+-------+---------+----------|\n| AntiSnipeSequenceHandler | liquidityRoundTrip          | 5334  | 0       | 0        |\n|--------------------------+-----------------------------+-------+---------+----------|\n| AntiSnipeSequenceHandler | rejectUnauthorizedCallbacks | 5531  | 0       | 0        |\n|--------------------------+-----------------------------+-------+---------+----------|\n| AntiSnipeSequenceHandler | trade                       | 5458  | 0       | 0        |\n╰--------------------------+-----------------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 609\n  Bound result 0\n  Bound result 120\n  Bound result 999999999999999000900\n  Bound result 179787852857992662027\n  Bound result 1603\n  Bound result 6020\n  Bound result 2570\n  Bound result 99999900000\n  Bound result 846\n  Bound result 102\n  Bound result 900\n  Bound result 249\n  Bound result 334\n  Bound result 900\n  Bound result 798\n  Bound result 49\n  Bound result 3449\n  Bound result 8391608\n  Bound result 205\n  Bound result 999999999999999009024\n  Bound result 11052\n  Bound result 4423\n  Bound result 3\n  Bound result 75606502332591362151\n  Bound result 820\n  Bound result 32028945790692\n  Bound result 477\n  Bound result 242\n  Bound result 624\n  Bound result 109\n  Bound result 1000000000000000000\n  Bound result 249\n  Bound result 12879\n  Bound result 86366824664711759930\n  Bound result 678\n  Bound result 1\n  Bound result 5\n  Bound result 89\n  Bound result 97\n  Bound result 275\n  Bound result 5451\n  Bound result 8388608\n  Bound result 1000000\n  Bound result 100000000000000000000\n  Bound result 1405\n  Bound result 203\n  Bound result 512\n  Bound result 4921\n  Bound result 52\n  Bound result 999999999999999010236\n  Bound result 448\n  Bound result 999999999999999000128\n  Bound result 2\n  Bound result 1000000000000000000\n  Bound result 721\n  Bound result 478243804960580000881\n  Bound result 241\n  Bound result 514264416821626722174\n  Bound result 999999999999999000834\n  Bound result 14508395825109879\n  Bound result 99\n  Bound result 11593\n\n[PASS] test_sequenceAcrossStaggeredHourBoundaries() (gas: 3835763)\nLogs:\n  Bound result 1000000000000000000\n  Bound result 900\n  Bound result 900\n  Bound result 900\n  Bound result 899\n  Bound result 1\n  Bound result 1\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000000\n  Bound result 900\n  Bound result 900\n  Bound result 1\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 57.00s (56.80s CPU time)\n\nRan 5 test suites in 57.01s (83.01s CPU time): 44 tests passed, 0 failed, 0 skipped (44 total tests)\n","passed":true},{"durationMs":382,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"AntiSnipeHook.afterAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"AntiSnipeHook.afterDonate(address,(address,address,uint24,int24,address),uint256,uint256,bytes)\",\"AntiSnipeHook.afterInitialize(address,(address,address,uint24,int24,address),uint160,int24)\",\"AntiSnipeHook.afterRemoveLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"AntiSnipeHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"AntiSnipeHook.beforeAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"AntiSnipeHook.beforeDonate(address,(address,address,uint24,int24,address),uint256,uint256,bytes)\",\"AntiSnipeHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"AntiSnipeHook.beforeRemoveLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"AntiSnipeHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"AntiSnipeToken.approve(address,uint256)\",\"AntiSnipeToken.transfer(address,uint256)\",\"AntiSnipeToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":5,\"DEPENDENCIES.json\":132,\"LICENSE\":23,\"README.md\":81,\"foundry.toml\":21,\"remappings.txt\":7,\"script/MineHook.s.sol\":24,\"src/AntiSnipeHook.sol\":84,\"src/AntiSnipeToken.sol\":12,\"src/HookFlags.sol\":32,\"test/AntiSnipeHook.t.sol\":243,\"test/AntiSnipeIntegration.t.sol\":169,\"test/AntiSnipeSequenceInvariant.t.sol\":290,\"test/AntiSnipeToken.t.sol\":116,\"test/AntiSnipeTokenInvariant.t.sol\":178,\"test/HookFixture.sol\":76,\"test/InvariantCoverage.md\":44,\"test/mocks/MockERC20.sol\":10},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"0ccc0c568ee031c706915ad07c7aecc009f86a46641cccd965546536ab94943e","verifiedTreeHash":"66ab41a948e4ac720fde964eb105d1d6d352b7c8","verifierVersion":"0.1.0+da6bdbe5"},{"checks":[{"durationMs":2032,"exitCode":0,"name":"build","output":"Compiling 88 files with Solc 0.8.26\nSolc 0.8.26 finished in 1.90s\nCompiler run successful!\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/AntiSnipeHook.sol:70:22\n   │\n70 │         uint24 fee = block.timestamp < endsAt ? INITIAL_LP_FEE : STANDARD_LP_FEE;\n   │                      ━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\n","passed":true},{"durationMs":433,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 9 tests for test/AntiSnipeToken.t.sol:AntiSnipeTokenTest\n[PASS] testFuzz_mintsToAnyDeployer(address) (runs: 256, μ: 18135, ~: 18135)\n[PASS] testFuzz_transferMovesExactAmountAndConservesSupply(uint256) (runs: 256, μ: 89705, ~: 89781)\nLogs:\n  Bound result 322\n\n[PASS] test_fixedSupplyAndMetadata() (gas: 52795)\n[PASS] test_noMintBurnOwnerPauseFeeOrUpgradeSelectors() (gas: 679380)\n[PASS] test_rejectsOverdraftAndZeroRecipient() (gas: 64088)\n[PASS] test_runtimeHasNoEscapeOpcodes() (gas: 1019374)\n[PASS] test_selfTransferAndZeroTransferDoNotChangeSupply() (gas: 91393)\n[PASS] test_transferCannotSpendAnotherAccountWithoutApproval() (gas: 33550)\n[PASS] test_transferFromConsumesAllowance() (gas: 140315)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 4.37ms (11.17ms CPU time)\n\nRan 11 tests for test/AntiSnipeIntegration.t.sol:AntiSnipeIntegrationTest\n[PASS] testFuzz_actualSwapsMatchStaticPool(uint32,bool,bool,uint96) (runs: 256, μ: 750127, ~: 746106)\nLogs:\n  Bound result 5766\n  Bound result 99999999999999999006\n\n[PASS] test_badPriceLimitRevertsWithoutChangingTimerOrBalances() (gas: 120747)\n[PASS] test_exactInputAfterHourInReverseDirection() (gas: 736314)\n[PASS] test_exactInputAtHour() (gas: 750177)\n[PASS] test_exactInputAtInitialization() (gas: 750157)\n[PASS] test_exactInputJustBeforeHourInReverseDirection() (gas: 736271)\n[PASS] test_exactOutputAtHourInReverseDirection() (gas: 737662)\n[PASS] test_exactOutputBeforeHour() (gas: 747648)\n[PASS] test_failedSettlementRollsBackSwap() (gas: 218807)\n[PASS] test_fullLifecycleEarnsLPFeesAndConservesTokens() (gas: 717171)\n[PASS] test_noCallerCanChangeStoredLPFee() (gas: 75425)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 297.91ms (60.05ms CPU time)\n\nRan 17 tests for test/AntiSnipeHook.t.sol:AntiSnipeHookTest\n[PASS] testFuzz_feeIndependentOfSenderDataAndSwapParameters(uint64,bool,int128,address,bytes) (runs: 256, μ: 140875, ~: 140679)\n[PASS] testFuzz_unauthorizedCallbacksCannotStartOrResetTimer(address) (runs: 256, μ: 77657, ~: 77657)\n[PASS] test_callbackRejectsStaticFeeAndMalformedDynamicFlag() (gas: 190500)\n[PASS] test_constructorRejectsWrongPermissionAddress() (gas: 11667)\n[PASS] test_constructorRejectsZeroOrCodelessManager() (gas: 68485767)\n[PASS] test_disabledCallbacksRevertEvenFromManager() (gas: 452100)\n[PASS] test_feeAtInitializationAndHourBoundary() (gas: 263173)\n[PASS] test_initializationAtTimestampZeroIsSupported() (gas: 183340)\n[PASS] test_noAdministrativeSelectors() (gas: 267934)\n[PASS] test_permissionsMatchDeployedAddress() (gas: 2008742)\n[PASS] test_poolsHaveIndependentClocks() (gas: 296968)\n[PASS] test_predictedPoolCannotInitializeBeforeHookExists() (gas: 48688699)\n[PASS] test_reinitializationCannotRestartExpiredWindow() (gas: 210466)\n[PASS] test_staticFeeInitializationRevertsAndRollsBack() (gas: 216567)\n[PASS] test_uninitializedPoolCannotReceiveFeeQuote() (gas: 45929)\n[PASS] test_windowStartsAtPoolInitializationNotHookDeployment() (gas: 153727)\n[PASS] test_wrongHookKeyRejected() (gas: 68616)\nSuite result: ok. 17 passed; 0 failed; 0 skipped; finished in 343.69ms (484.12ms CPU time)\n\nRan 3 test suites in 344.47ms (645.96ms CPU time): 37 tests passed, 0 failed, 0 skipped (37 total tests)\n","passed":true},{"durationMs":43,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"AntiSnipeHook.afterAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"AntiSnipeHook.afterDonate(address,(address,address,uint24,int24,address),uint256,uint256,bytes)\",\"AntiSnipeHook.afterInitialize(address,(address,address,uint24,int24,address),uint160,int24)\",\"AntiSnipeHook.afterRemoveLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"AntiSnipeHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"AntiSnipeHook.beforeAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"AntiSnipeHook.beforeDonate(address,(address,address,uint24,int24,address),uint256,uint256,bytes)\",\"AntiSnipeHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"AntiSnipeHook.beforeRemoveLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"AntiSnipeHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"AntiSnipeToken.approve(address,uint256)\",\"AntiSnipeToken.transfer(address,uint256)\",\"AntiSnipeToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":5,\"DEPENDENCIES.json\":132,\"LICENSE\":23,\"README.md\":81,\"foundry.toml\":21,\"launch.json\":21,\"remappings.txt\":7,\"script/MineHook.s.sol\":24,\"src/AntiSnipeHook.sol\":84,\"src/AntiSnipeToken.sol\":12,\"src/HookFlags.sol\":32,\"test/AntiSnipeHook.t.sol\":243,\"test/AntiSnipeIntegration.t.sol\":169,\"test/AntiSnipeToken.t.sol\":116,\"test/HookFixture.sol\":76,\"test/mocks/MockERC20.sol\":10},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"19b5e14072d2ed41ce471eb6756e4a9b31d771bea2b030c15ed3e438ad1caca1","verifiedTreeHash":"510e4efae45ccd8cb71dcb6329c6dbf5c028c46b","verifierVersion":"0.1.0+da6bdbe5"},{"checks":[{"durationMs":2273,"exitCode":0,"name":"build","output":"Compiling 88 files with Solc 0.8.26\nSolc 0.8.26 finished in 2.12s\nCompiler run successful!\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/AntiSnipeHook.sol:70:22\n   │\n70 │         uint24 fee = block.timestamp < endsAt ? INITIAL_LP_FEE : STANDARD_LP_FEE;\n   │                      ━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\n","passed":true},{"durationMs":461,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 9 tests for test/AntiSnipeToken.t.sol:AntiSnipeTokenTest\n[PASS] testFuzz_mintsToAnyDeployer(address) (runs: 256, μ: 18135, ~: 18135)\n[PASS] testFuzz_transferMovesExactAmountAndConservesSupply(uint256) (runs: 256, μ: 89358, ~: 89781)\nLogs:\n  Bound result 682110080946417297195602059\n\n[PASS] test_fixedSupplyAndMetadata() (gas: 52795)\n[PASS] test_noMintBurnOwnerPauseFeeOrUpgradeSelectors() (gas: 679380)\n[PASS] test_rejectsOverdraftAndZeroRecipient() (gas: 64088)\n[PASS] test_runtimeHasNoEscapeOpcodes() (gas: 1019374)\n[PASS] test_selfTransferAndZeroTransferDoNotChangeSupply() (gas: 91393)\n[PASS] test_transferCannotSpendAnotherAccountWithoutApproval() (gas: 33550)\n[PASS] test_transferFromConsumesAllowance() (gas: 140315)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 5.68ms (13.98ms CPU time)\n\nRan 11 tests for test/AntiSnipeIntegration.t.sol:AntiSnipeIntegrationTest\n[PASS] testFuzz_actualSwapsMatchStaticPool(uint32,bool,bool,uint96) (runs: 256, μ: 750391, ~: 746113)\nLogs:\n  Bound result 1281\n  Bound result 204130\n\n[PASS] test_badPriceLimitRevertsWithoutChangingTimerOrBalances() (gas: 120747)\n[PASS] test_exactInputAfterHourInReverseDirection() (gas: 736314)\n[PASS] test_exactInputAtHour() (gas: 750177)\n[PASS] test_exactInputAtInitialization() (gas: 750157)\n[PASS] test_exactInputJustBeforeHourInReverseDirection() (gas: 736271)\n[PASS] test_exactOutputAtHourInReverseDirection() (gas: 737662)\n[PASS] test_exactOutputBeforeHour() (gas: 747648)\n[PASS] test_failedSettlementRollsBackSwap() (gas: 218807)\n[PASS] test_fullLifecycleEarnsLPFeesAndConservesTokens() (gas: 717171)\n[PASS] test_noCallerCanChangeStoredLPFee() (gas: 75425)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 140.61ms (60.81ms CPU time)\n\nRan 17 tests for test/AntiSnipeHook.t.sol:AntiSnipeHookTest\n[PASS] testFuzz_feeIndependentOfSenderDataAndSwapParameters(uint64,bool,int128,address,bytes) (runs: 256, μ: 140906, ~: 140787)\n[PASS] testFuzz_unauthorizedCallbacksCannotStartOrResetTimer(address) (runs: 256, μ: 77657, ~: 77657)\n[PASS] test_callbackRejectsStaticFeeAndMalformedDynamicFlag() (gas: 190500)\n[PASS] test_constructorRejectsWrongPermissionAddress() (gas: 11667)\n[PASS] test_constructorRejectsZeroOrCodelessManager() (gas: 68485767)\n[PASS] test_disabledCallbacksRevertEvenFromManager() (gas: 452100)\n[PASS] test_feeAtInitializationAndHourBoundary() (gas: 263173)\n[PASS] test_initializationAtTimestampZeroIsSupported() (gas: 183340)\n[PASS] test_noAdministrativeSelectors() (gas: 267934)\n[PASS] test_permissionsMatchDeployedAddress() (gas: 2008742)\n[PASS] test_poolsHaveIndependentClocks() (gas: 296968)\n[PASS] test_predictedPoolCannotInitializeBeforeHookExists() (gas: 48688699)\n[PASS] test_reinitializationCannotRestartExpiredWindow() (gas: 210466)\n[PASS] test_staticFeeInitializationRevertsAndRollsBack() (gas: 216567)\n[PASS] test_uninitializedPoolCannotReceiveFeeQuote() (gas: 45929)\n[PASS] test_windowStartsAtPoolInitializationNotHookDeployment() (gas: 153727)\n[PASS] test_wrongHookKeyRejected() (gas: 68616)\nSuite result: ok. 17 passed; 0 failed; 0 skipped; finished in 355.15ms (511.38ms CPU time)\n\nRan 3 test suites in 355.69ms (501.44ms CPU time): 37 tests passed, 0 failed, 0 skipped (37 total tests)\n","passed":true},{"durationMs":59,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"AntiSnipeHook.afterAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"AntiSnipeHook.afterDonate(address,(address,address,uint24,int24,address),uint256,uint256,bytes)\",\"AntiSnipeHook.afterInitialize(address,(address,address,uint24,int24,address),uint160,int24)\",\"AntiSnipeHook.afterRemoveLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"AntiSnipeHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"AntiSnipeHook.beforeAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"AntiSnipeHook.beforeDonate(address,(address,address,uint24,int24,address),uint256,uint256,bytes)\",\"AntiSnipeHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"AntiSnipeHook.beforeRemoveLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"AntiSnipeHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"AntiSnipeToken.approve(address,uint256)\",\"AntiSnipeToken.transfer(address,uint256)\",\"AntiSnipeToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":5,\"DEPENDENCIES.json\":132,\"LICENSE\":23,\"README.md\":81,\"foundry.toml\":21,\"remappings.txt\":7,\"script/MineHook.s.sol\":24,\"src/AntiSnipeHook.sol\":84,\"src/AntiSnipeToken.sol\":12,\"src/HookFlags.sol\":32,\"test/AntiSnipeHook.t.sol\":243,\"test/AntiSnipeIntegration.t.sol\":169,\"test/AntiSnipeToken.t.sol\":116,\"test/HookFixture.sol\":76,\"test/mocks/MockERC20.sol\":10},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":989,"exitCode":0,"name":"slither","output":"[low/medium] timestamp at src/AntiSnipeHook.sol:60: AntiSnipeHook._beforeSwap(address,PoolKey,SwapParams,bytes) (src/AntiSnipeHook.sol#60-77) uses timestamp for comparisons","passed":true},{"durationMs":250,"exitCode":0,"name":"aderyn","output":"[low] internal-function-used-once at src/HookFlags.sol:25: Internal Function Used Only Once\n[low] large-numeric-literal at src/AntiSnipeHook.sol:25: Large Numeric Literal (2 places)","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"eb8cf80113b2bbc5e34c7ad35c71d51cbc1d2b693d1bddce64c5209cf35f1ff9","verifiedTreeHash":"24554fb0d80e582dd0e890e4281e88dd66771175","verifierVersion":"0.1.0+da6bdbe5"}]}