{"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":"81c6d9d5-265a-4fb0-a46f-116edcf3ef33","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"bfa41d706c35a0c1d6e91d1ecb4355a537894223d2e757ea9a11fa7c086d214c","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":"9e5ea2550b620903f7aabb740dcf7af2878e08aa9a2306afad380c2a5e4655ee","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":"7a110470bd59e63b6c82938bd99d50dd1e75c3787bc0eccaaebe5ffe0096bf0f","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":"waiting"},{"acceptedSubmissionHash":"303e940394eb8463a0c272a34e9efb3df0ba149f54d1211424827e1b47df5fd4","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":"cc0767348f8f64bfd2aee57bacaa3454e3dd04738a173316217dc4386195387d","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":"7a19e11ffafef91a4e246dfe734da80b6e4c4eef225c9ff7fc1f624694d78da1","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":"a053a07f0c1801edbc60d9fe4fb216343ab33565ff44378d3198e85f01a769b9","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"working"},{"acceptedSubmissionHash":"23f2cef2d7085cee6e358886238dda446009952ca14143b8116483c672019f07","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":"failed"}],"objective":"BurnTax: a Uniswap v4 hook for the launched token's pool that burns a small part of every swap.\n\nOn every swap in a pool that uses this hook, take 1% of the launched-token side of the trade (the amount the trader receives on buys, the amount the trader pays on sells) and send it to the dead address 0x000000000000000000000000000000000000dEaD, using the hook's return deltas so the trader's received or paid amount reflects the 1%. Emit an event with the pool, the trader-facing direction and the amount burned. Nothing else changes: the LP fee is the pool's own, no owner, no admin, no withdraw, no way to change the 1% after deployment. Handle exact-input and exact-output swaps in both directions.\n\nTests against a real PoolManager: burn amount and direction for buys and sells, exact-in and exact-out, the dead address balance, events, and that a pool without the launched token is unaffected. README with the rule and its limits.\nToken: name \"BurnTax\", symbol BTAX, fixed supply, nobody can mint more.","parentJobId":null,"planHash":"af53c830213df8ef59db6c068b938e9853da67c3f4b98fc7b25d2bc7e58cd3bd","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"81c6d9d5-265a-4fb0-a46f-116edcf3ef33","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-580-burntax-uniswap-v4-hook"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"51331","feedbackHash":"399556cf86e4fb599d8216fcc4c2abb664508d917d650696cbfb5da774e5c4c2","nodeKey":"audit_economics","submissionHash":"bfa41d706c35a0c1d6e91d1ecb4355a537894223d2e757ea9a11fa7c086d214c","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51340","feedbackHash":"fad84ae6700905478aa404befd524b77152dde2a0b7f608c7c754116d166feed","nodeKey":"audit_flow","submissionHash":"9e5ea2550b620903f7aabb740dcf7af2878e08aa9a2306afad380c2a5e4655ee","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51023","feedbackHash":"c5b0a24ed1d97a97ebab81d7d7c08c6d60acb22c2ac2dd0eb5cd49b0a2113fc3","nodeKey":"audit_judge","submissionHash":"7a110470bd59e63b6c82938bd99d50dd1e75c3787bc0eccaaebe5ffe0096bf0f","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51430","feedbackHash":"538a6a60c899a196f7bc1f4b652c1f3bfe654caab1b7bfd2236a5c3cc5db9320","nodeKey":"audit_math","submissionHash":"303e940394eb8463a0c272a34e9efb3df0ba149f54d1211424827e1b47df5fd4","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"50939","feedbackHash":"4b225c4cb28887b26a395bfe09b22459c6f7c503c092068ef22bdfe03c4a0bcd","nodeKey":"audit_permissions","submissionHash":"cc0767348f8f64bfd2aee57bacaa3454e3dd04738a173316217dc4386195387d","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"50971","feedbackHash":"54184af1c375bd49801b355fbd8a0b72de93b024a7dad35cb02313e3b627da82","nodeKey":"build_contract_project","submissionHash":"7a19e11ffafef91a4e246dfe734da80b6e4c4eef225c9ff7fc1f624694d78da1","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"50956","feedbackHash":"d78223d1e914d25b4f3a76cc4aac749d8ff559534d5703c86f682bafe15370d1","nodeKey":"build_contract_project","submissionHash":"0a0b6414c4050554c31f14aaa13e9f2cf77b49c072ec3a045deec881623ebaef","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"50957","feedbackHash":"f63dba704f9fa17327fe994bfb1fecb9e333cb3c45cbcdb8eded81d0af34800f","nodeKey":"manifest","submissionHash":"e11c9143a40373415adb171f71faceadd7d4cd0e9df46eb10486fe7497433af8","tag1":"verification:checks","tag2":"acceptance-v2","value":0},{"agentId":"50962","feedbackHash":"c40bca68cf0d7d86e8a6df65bf2a9148e2f3a6d7d7fbcea99dfed9ed99ecdaee","nodeKey":"manifest","submissionHash":"a053a07f0c1801edbc60d9fe4fb216343ab33565ff44378d3198e85f01a769b9","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"50971","feedbackHash":"e6b6bf736e2449f0194aef51e73f92fd37a7e358b4c5b55e6544dc723a23f8d6","nodeKey":"write_foundry_tests","submissionHash":"23f2cef2d7085cee6e358886238dda446009952ca14143b8116483c672019f07","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"b7e1ac98884888e6626d2888d0f770942df48d21078f9424d19dbe00a6e93a4a","state":"blocked","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"7678b894c111ba13b47603efd4c80d4d4a773f88a809c72319f180abb36268cd","device":"bb0a3bf63233e5e5","findings":[],"hash":"0a0b6414c4050554c31f14aaa13e9f2cf77b49c072ec3a045deec881623ebaef","nodeId":"1ade3e93-7644-44b8-b43d-7a3e2d7f2dc9","outcome":"completed","summary":"Implemented the immutable 1% burn hook, fixed-supply BTAX token, vendored dependencies, deployment miner, and documentation.\n\nVerified with Solidity 0.8.26:\n\n- `forge build` passed\n- `forge test`: 59 passed\n- `forge fmt --check` passed\n\n[README](/home/imd-worker/.identitymd/work/81c6d9d5-265a-4fb0-a46f-116edcf3ef33/1ade3e93-7644-44b8-b43d-7a3e2d7f2dc9/README.md) documents two material limits: BTAX-specified partial fills revert, and sells need existing manager BTAX reserves or router pre-settlement.","treeHash":"8986861bbb987d4b6ff8466c1662c2793c716f08","usage":{"cachedInputTokens":1143552,"inputTokens":98866,"model":"gpt-6-astra","outputTokens":28528,"runtime":"codex","turns":6,"wallClockMs":954647}},{"artifacts":[],"attempt":1,"bundleHash":"d0700fb5e4a54824e33d5b93961e6a52b4730c7230a41b3d629107648898e1ae","device":"35c52a5b502e847c","findings":[{"description":"afterSwap transfers the burn immediately from the PoolManager, before an ordinary v4 router settles its input. A valid BTAX sell into a quote-only pool therefore reverts even though the seller owns and can settle the entire input and the pool has sufficient quote liquidity. This affects exact-input and exact-output sells when the manager's existing BTAX is below the burn. The README acknowledges pre-settlement as a workaround; the assignment's swap support still has this availability gap. There is no fund loss: the transaction rolls back. A custom prefunding router or unrelated pools' BTAX can mask the defect, so the reproducer uses an isolated real manager and ordinary settle-after-swap accounting. The passing suite does not assert that rejecting this valid sell is correct.","line":116,"path":"src/BurnTaxHook.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {BurnTaxToken} from \"src/BurnTaxToken.sol\";\nimport {BurnTaxHook} from \"src/BurnTaxHook.sol\";\nimport {PoolManager} from \"v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"v4-core/src/interfaces/IPoolManager.sol\";\nimport {IHooks} from \"v4-core/src/interfaces/IHooks.sol\";\nimport {IUnlockCallback} from \"v4-core/src/interfaces/callback/IUnlockCallback.sol\";\nimport {PoolKey} from \"v4-core/src/types/PoolKey.sol\";\nimport {Currency} from \"v4-core/src/types/Currency.sol\";\nimport {BalanceDelta} from \"v4-core/src/types/BalanceDelta.sol\";\nimport {ModifyLiquidityParams, SwapParams} from \"v4-core/src/types/PoolOperation.sol\";\nimport {TickMath} from \"v4-core/src/libraries/TickMath.sol\";\nimport {TransientStateLibrary} from \"v4-core/src/libraries/TransientStateLibrary.sol\";\n\ncontract UnfundedSellProof is Test, IUnlockCallback {\n    using TransientStateLibrary for IPoolManager;\n    PoolManager manager;\n    BurnTaxToken token;\n    BurnTaxHook hook;\n    PoolKey key;\n    address constant DEAD = 0x000000000000000000000000000000000000dEaD;\n\n    function setUp() public {\n        vm.deal(address(this), 100 ether);\n        manager = new PoolManager(address(this));\n        token = new BurnTaxToken();\n        bytes32 codeHash = keccak256(abi.encodePacked(type(BurnTaxHook).creationCode,\n            abi.encode(IPoolManager(address(manager)), address(token))));\n        for (uint256 i; i < 200000; ++i) {\n            address predicted = address(uint160(uint256(keccak256(\n                abi.encodePacked(hex\"ff\", address(this), bytes32(i), codeHash)))));\n            if ((uint160(predicted) & 0x3fff) == 0x20cc) {\n                hook = new BurnTaxHook{salt: bytes32(i)}(manager, address(token));\n                break;\n            }\n        }\n        require(address(hook) != address(0), \"salt search failed\");\n        key = PoolKey(Currency.wrap(address(0)), Currency.wrap(address(token)), 3000, 60, IHooks(address(hook)));\n        manager.initialize(key, uint160(1 << 96));\n        manager.unlock(abi.encode(key, true, int256(0)));\n        assertEq(token.balanceOf(address(manager)), 0);\n        assertGt(address(manager).balance, 2 ether);\n    }\n\n    function test_exactInputSellShouldSettleWithoutPreexistingInputReserves() public {\n        _sell(-1 ether);\n    }\n\n    function test_exactOutputSellShouldSettleWithoutPreexistingInputReserves() public {\n        _sell(1 ether);\n    }\n\n    function _sell(int256 amountSpecified) internal {\n        // Control: the real manager can execute the same sell without this hook.\n        uint256 snapshot = vm.snapshotState();\n        PoolKey memory plain = key;\n        plain.hooks = IHooks(address(0));\n        manager.initialize(plain, uint160(1 << 96));\n        manager.unlock(abi.encode(plain, true, int256(0)));\n        BalanceDelta control = abi.decode(manager.unlock(abi.encode(plain, false, amountSpecified)), (BalanceDelta));\n        assertGt(control.amount0(), 0);\n        assertLt(control.amount1(), 0);\n        assertTrue(vm.revertToState(snapshot));\n        assertEq(token.balanceOf(address(manager)), 0);\n\n        uint256 balanceBefore = token.balanceOf(address(this));\n        // Expected: the sell executes, and 1% of the trader's gross BTAX payment\n        // reaches DEAD. Actual: afterSwap.take reverts before input can be settled.\n        BalanceDelta delta = abi.decode(manager.unlock(abi.encode(key, false, amountSpecified)), (BalanceDelta));\n        uint256 paid = balanceBefore - token.balanceOf(address(this));\n        assertEq(token.balanceOf(DEAD), paid / 100);\n        assertGt(token.balanceOf(DEAD), 0);\n        if (amountSpecified < 0) assertEq(delta.amount1(), amountSpecified);\n        else assertEq(delta.amount0(), amountSpecified);\n    }\n\n    function unlockCallback(bytes calldata data) external returns (bytes memory) {\n        require(msg.sender == address(manager), \"only manager\");\n        (PoolKey memory pool, bool adding, int256 amount) = abi.decode(data, (PoolKey, bool, int256));\n        BalanceDelta delta;\n        if (adding) {\n            (delta,) = manager.modifyLiquidity(pool, ModifyLiquidityParams(60, 120, 1e22, bytes32(0)), \"\");\n        } else {\n            delta = manager.swap(pool, SwapParams(false, amount, TickMath.MAX_SQRT_PRICE - 1), \"\");\n        }\n        // Ordinary flash accounting: settle inputs after swap returns.\n        _settle(pool.currency0);\n        _settle(pool.currency1);\n        return abi.encode(delta);\n    }\n\n    function _settle(Currency currency) internal {\n        int256 delta = IPoolManager(manager).currencyDelta(address(this), currency);\n        if (delta < 0) {\n            manager.sync(currency);\n            if (Currency.unwrap(currency) == address(0)) manager.settle{value: uint256(-delta)}();\n            else {\n                token.transfer(address(manager), uint256(-delta));\n                manager.settle();\n            }\n        } else if (delta > 0) manager.take(currency, address(this), uint256(delta));\n    }\n\n    receive() external payable {}\n}","reproduction":"Run the self-contained proof as test/scratch/UnfundedSellProof.t.sol with forge test --match-path test/scratch/UnfundedSellProof.t.sol -vv. Deploy a real PoolManager, BurnTaxToken and mined BurnTaxHook (flags 0x20cc). Initialize native ETH/BTAX at sqrtPriceX96=2^96, fee=3000, tickSpacing=60. Add liquidity 10^22 over ticks [60,120]; manager BTAX balance is zero and it holds more than 2 ETH. Sell with zeroForOne=false and sqrtPriceLimitX96=TickMath.MAX_SQRT_PRICE-1, using amountSpecified=-10^18 (exact input) or +10^18 (exact output). The proof first demonstrates each sell succeeds in an equivalent unhooked pool and restores the snapshot before exercising the hooked pool. Expected: positive ETH output, specified input/output respected, and floor(total BTAX paid/100) transferred to DEAD (10^16 BTAX minor units on the exact-input case). Actual: both fail in afterSwap -> take -> token.transfer with ERC20InsufficientBalance(manager,0,burn), wrapped by v4; settlement is never reached. Both failures were reproduced locally.","severity":"medium","title":"Sells revert before settlement when the PoolManager lacks existing BTAX reserves"}],"hash":"23f2cef2d7085cee6e358886238dda446009952ca14143b8116483c672019f07","nodeId":"21d9d014-103f-4d86-a333-ac33af4ef7d5","outcome":"completed","summary":"Added adversarial swap tests, failure-path coverage, multi-actor invariants, and `test/README.md`.\n\n`forge build` passes. Full suite: **77 passed, 0 failed, 0 skipped**.\n\nReported one medium-severity defect in `.imd-findings.json`, with a verified failing proof: sells revert before settlement when the manager lacks existing BTAX reserves.","treeHash":"e8ecd54cbdaf084cb80d61dae8893453ec9c3ebc","usage":{"cachedInputTokens":2666368,"inputTokens":131299,"model":"gpt-6-astra","outputTokens":23715,"runtime":"codex","turns":6,"wallClockMs":813969}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"2a5d68f89de314cb","findings":[{"citation":"resolved","description":"Boundary (external call: PoolManager.take). afterSwap pays the burn with an immediate `take`, which transfers BTAX out of the PoolManager's own ERC-20 balance at that moment. On a sell the BTAX the trader is paying has not been settled yet: every production router (Universal Router, V4Router, any unlock -> swap -> settle flow) pays its input only after `swap` returns. So the transfer is funded solely by BTAX the manager already holds, i.e. the live reserves of all BTAX pools plus unsettled credits. Whenever that total is below `sell/100` the ERC-20 transfer reverts with ERC20InsufficientBalance, PoolManager wraps it, and the entire swap fails although the AMM itself could fill the trade (the identical sell on an un-hooked BTAX pool in the same state fills). The reachable state is a BTAX pool that buyers have (nearly) emptied: the manager then holds dust of BTAX while the price is at its highest, which is exactly when holders want to sell. In the reproduction the manager holds 2 wei of BTAX and a sell of 1e22 (fee 1e20) reverts; the seller can only get through by splitting into chunks of at most 100x the remaining reserve, or by using a router that pre-settles BTAX inside the unlock, which no standard router does. Exact-output sells fail the same way (fee P/99). The README documents this as an integrator limit, but the reference guidance for this network asks that a hook fee be payable without relying on the manager's prior balance. Suggested minimal fix that keeps the design (no owner, no withdraw, nothing retained for anyone but DEAD): in afterSwap, when `Currency.wrap(launchedToken).balanceOf(address(poolManager)) < fee`, call `poolManager.mint(address(this), currency.toId(), fee)` instead of `take`, and add a permissionless function that unlocks the manager, burns the hook's ERC-6909 BTAX claim and takes it to DEAD. The accounting stays identical (the hook is debited `fee` by `mint` exactly as by `take`, and credited `fee` by the return delta). Keep the direct `take` whenever the balance covers it so the ordinary path is unchanged.","line":116,"path":"src/BurnTaxHook.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {BurnTaxHook} from \"src/BurnTaxHook.sol\";\nimport {BurnTaxToken} from \"src/BurnTaxToken.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 {IHooks} from \"v4-core/src/interfaces/IHooks.sol\";\nimport {IUnlockCallback} from \"v4-core/src/interfaces/callback/IUnlockCallback.sol\";\nimport {TransientStateLibrary} from \"v4-core/src/libraries/TransientStateLibrary.sol\";\nimport {TickMath} from \"v4-core/src/libraries/TickMath.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 {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/// @dev Minimal production-shaped router: unlock -> swap -> settle input -> take output.\n/// Nothing is paid to the manager before `swap` returns, exactly like Uniswap's own routers.\ncontract SettleAfterRouter is IUnlockCallback {\n    using TransientStateLibrary for IPoolManager;\n\n    IPoolManager public immutable manager;\n    address internal payer;\n\n    constructor(IPoolManager m) {\n        manager = m;\n    }\n\n    function modify(PoolKey memory key, ModifyLiquidityParams memory p) external payable returns (BalanceDelta) {\n        payer = msg.sender;\n        return abi.decode(manager.unlock(abi.encode(true, key, p, SwapParams(false, 0, 0))), (BalanceDelta));\n    }\n\n    function swap(PoolKey memory key, SwapParams memory s) external payable returns (BalanceDelta) {\n        payer = msg.sender;\n        return abi.decode(\n            manager.unlock(abi.encode(false, key, ModifyLiquidityParams(0, 0, 0, bytes32(0)), s)), (BalanceDelta)\n        );\n    }\n\n    function unlockCallback(bytes calldata data) external returns (bytes memory) {\n        require(msg.sender == address(manager));\n        (bool liquidity, PoolKey memory key, ModifyLiquidityParams memory p, SwapParams memory s) =\n            abi.decode(data, (bool, PoolKey, ModifyLiquidityParams, SwapParams));\n        BalanceDelta delta;\n        if (liquidity) (delta,) = manager.modifyLiquidity(key, p, \"\");\n        else delta = manager.swap(key, s, \"\");\n        _settle(key.currency0);\n        _settle(key.currency1);\n        return abi.encode(delta);\n    }\n\n    function _settle(Currency c) internal {\n        int256 d = manager.currencyDelta(address(this), c);\n        if (d < 0) {\n            manager.sync(c);\n            if (Currency.unwrap(c) == address(0)) {\n                manager.settle{value: uint256(-d)}();\n            } else {\n                require(IERC20(Currency.unwrap(c)).transferFrom(payer, address(manager), uint256(-d)));\n                manager.settle();\n            }\n        } else if (d > 0) {\n            manager.take(c, payer, uint256(d));\n        }\n    }\n\n    receive() external payable {}\n}\n\ncontract SellFundingProofTest is Test {\n    address constant DEAD = 0x000000000000000000000000000000000000dEaD;\n    uint160 constant PRICE = 1 << 96;\n\n    PoolManager manager;\n    SettleAfterRouter router;\n    BurnTaxToken token;\n    BurnTaxHook hook;\n    PoolKey key;\n\n    receive() external payable {}\n\n    function setUp() public {\n        manager = new PoolManager(address(this));\n        router = new SettleAfterRouter(manager);\n        token = new BurnTaxToken();\n        hook = _deployHook();\n        // Native ETH is always currency0; BTAX is currency1.\n        key = PoolKey(Currency.wrap(address(0)), Currency.wrap(address(token)), 3000, 60, IHooks(address(hook)));\n        manager.initialize(key, PRICE);\n        token.approve(address(router), type(uint256).max);\n        vm.deal(address(this), 1e27);\n        // Two-sided launch liquidity: the manager holds BTAX from the start.\n        router.modify{value: 1e23}(key, ModifyLiquidityParams(-600, 600, 1e24, bytes32(0)));\n        assertGt(token.balanceOf(address(manager)), 1e22);\n    }\n\n    /// Buyers take all the BTAX the pool holds, then a holder sells with an ordinary router.\n    /// The AMM has the liquidity to take the sell (the same sell on an un-hooked pool fills), but the\n    /// hook's `take(BTAX, DEAD, fee)` in afterSwap runs before the router has paid the BTAX in, and the\n    /// manager has only dust of BTAX, so the whole swap reverts with ERC20InsufficientBalance.\n    function test_sellWithOrdinaryRouterAfterPoolIsBoughtOut() public {\n        // Drain: exact-input buy with 1e25 wei ETH, price limit past the range.\n        router.swap{value: 1e25}(key, SwapParams(true, -1e25, TickMath.MIN_SQRT_PRICE + 1));\n        uint256 managerBtax = token.balanceOf(address(manager));\n        assertLt(managerBtax, 1e18, \"pool bought out; manager holds dust BTAX\");\n\n        uint256 sell = 1e22; // fee = 1e20 > managerBtax\n        uint256 traderBefore = token.balanceOf(address(this));\n        uint256 deadBefore = token.balanceOf(DEAD);\n\n        // Expected: the sell executes; the trader pays exactly `sell`; 1% is burned (or at least\n        // committed as a claim the hook can later burn).\n        BalanceDelta d = router.swap(key, SwapParams(false, -int256(sell), TickMath.MAX_SQRT_PRICE - 1));\n\n        assertEq(int256(d.amount1()), -int256(sell), \"trader pays exactly the sell amount\");\n        assertEq(traderBefore - token.balanceOf(address(this)), sell);\n        uint256 burnedOrPending =\n            token.balanceOf(DEAD) - deadBefore + manager.balanceOf(address(hook), uint160(address(token)));\n        assertEq(burnedOrPending, sell / 100, \"one percent of the sell is burned or committed to burn\");\n    }\n\n    function _deployHook() internal returns (BurnTaxHook deployed) {\n        bytes memory code = abi.encodePacked(type(BurnTaxHook).creationCode, abi.encode(manager, address(token)));\n        bytes32 codeHash = keccak256(code);\n        for (uint256 i; i < 200_000; ++i) {\n            bytes32 salt = bytes32(i);\n            address predicted =\n                address(uint160(uint256(keccak256(abi.encodePacked(hex\"ff\", address(this), salt, codeHash)))));\n            if (HookFlags.matches(predicted, HookFlags.BURN_TAX)) {\n                deployed = new BurnTaxHook{salt: salt}(manager, address(token));\n                require(address(deployed) == predicted);\n                return deployed;\n            }\n        }\n        revert(\"salt search exhausted\");\n    }\n}","reproduction":"State: fresh PoolManager; BurnTaxToken; hook mined at flags 0x20cc; pool ETH/BTAX fee 3000 spacing 60 at sqrtPrice 2^96; two-sided liquidity 1e24 over ticks [-600,600] (manager then holds ~2.96e22 BTAX). Step 1: exact-input buy with 1e25 wei ETH, zeroForOne=true, priceLimit MIN_SQRT_PRICE+1 (partial fill, drains the pool's BTAX; manager BTAX balance falls to 2 wei, in the fixture with a second plain BTAX pool it is 2 wei after draining both). Step 2: ordinary settle-after router (unlock -> manager.swap -> settle currency0 -> settle currency1) sells exact-input 1e22 BTAX, zeroForOne=false, priceLimit MAX_SQRT_PRICE-1. Expected: swap fills, trader's BTAX delta is -1e22, DEAD gains 1e20. Actual: revert WrappedError(hook, afterSwap selector, WrappedError(token, transfer selector, ERC20InsufficientBalance(manager, 2, 1e20), ...)); nothing burned, no trade. Control: the same sell on an un-hooked ETH/BTAX pool in the same drained state fills (trader pays 1e22); the same sell on the hooked pool with 1e22 BTAX pre-settled inside the unlock also fills and burns 1e20. Exact-output sell of 1e21 quote in the same state reverts with ERC20InsufficientBalance(manager, 2, 9.55e18). Run: forge test --match-path test/scratch/SellFundingProof.t.sol (fails on current code).","severity":"medium","snippet":"        if (fee != 0) poolManager.take(Currency.wrap(launchedToken), DEAD, fee);","title":"Sells revert for every settle-after router once the PoolManager's BTAX balance is below the 1% burn"},{"citation":"resolved","description":"Boundary (sentinel input on an entry point). PoolKey.fee = 0x800000 (LPFeeLibrary.DYNAMIC_FEE_FLAG) passes PoolManager.initialize for any hook address and reaches beforeInitialize, which checks only key.hooks. v4 initializes a dynamic pool with lpFee 0 and only `key.hooks` may ever call updateDynamicLPFee; this hook never does, and its beforeSwap returns 0 without the override flag, so Hooks.beforeSwap sets no override. Result: anyone can create a BTAX pool using this hook with a permanent 0% LP fee, while the 1% burn still applies to it. The README states the hook neither sets nor overrides LP fees and that the launch tiers are 500/3000/10000; it does not say a zero-fee hooked pool can be created, and the launch policy excludes 0 and the dynamic flag as LP fees. No funds are lost; LPs who join such a pool simply earn nothing, and it fragments liquidity under the launch hook's identity. Fix: in beforeInitialize `if (key.fee.isDynamicFee()) revert UnsupportedFee();` (LPFeeLibrary), which does not affect any static-fee pool.","line":62,"path":"src/BurnTaxHook.sol","reproduction":"State: standard fixture (BTAX/quote, hook at 0x20cc). Call manager.initialize(PoolKey(currency0, currency1, 0x800000, 60, hook), 2^96): succeeds (expected: revert). getSlot0(poolId).lpFee == 0. Add liquidity 1e24 over [-600,600]; buy exact-input 100 ether quote: trader receives 98.990100989901009900 BTAX, i.e. gross 99.990000999901009999 BTAX with zero LP fee minus the 1% burn, versus 99.690060900928177460 BTAX gross on the same pool with fee 3000. Burned events still fire. Run test_dynamicFeePoolAcceptedWithZeroLpFee in test/scratch/Probe.t.sol.","severity":"low","snippet":"        if (address(key.hooks) != address(this)) revert WrongHook();","title":"beforeInitialize accepts the dynamic-fee sentinel, creating a hooked BTAX pool whose LP fee is 0 forever"},{"citation":"resolved","description":"Boundary x invariant seam, reported for the record because the README documents it as an intended limit. When BTAX is the specified currency the burn is reserved in beforeSwap as a specified delta, and afterSwap can only adjust the unspecified currency, so a partial fill cannot be re-taxed on executed volume; the hook reverts the whole swap. A plain v4 pool, and this hook's own unspecified-BTAX modes, fill partially in the same situation. Effect: a sell or exact-output buy whose price limit is hit, or that exhausts one-sided liquidity, fails for the user rather than returning a partial fill; routers that rely on partial fills (price-limit orders) cannot use these two modes. No funds move. This is inherent to v4's return-delta rules given the chosen gross definition; the alternative (burn only 1% of the executed leg and refund the surplus reserve to `sender`) would pay a router, not the user, so the revert is a defensible choice. No change is recommended beyond keeping the README text.","line":102,"path":"src/BurnTaxHook.sol","reproduction":"Standard fixture. Exact-input sell of 1e22 BTAX with sqrtPriceLimitX96 = TickMath.getSqrtPriceAtTick(-1) (BTAX as currency0, zeroForOne=true): revert WrappedError(hook, afterSwap, PartialFillOnSpecifiedToken()). The same params on the un-hooked reference pool fill partially (quote out < 1e22, price at tick -1). Exact-output buy of 1e22 with limit at tick +1 reverts the same way. Covered by test_specifiedTokenPartialFillsRevertAtomically in test/Hook.t.sol.","severity":"info","snippet":"            if (tokenDelta != params.amountSpecified + fee.toInt256()) {\n                revert PartialFillOnSpecifiedToken();\n            }","title":"BTAX-specified swaps (exact-input sells, exact-output buys) revert instead of partially filling at a price limit or liquidity edge"}],"hash":"303e940394eb8463a0c272a34e9efb3df0ba149f54d1211424827e1b47df5fd4","nodeId":"3e08ac07-281f-43d1-a66a-a4838303f0c1","outcome":"completed","summary":"The review is complete and `.imd-findings.json` holds three findings plus eleven coverage rows. No project files were changed; only `test/scratch/` and the findings file were written.\n\n**Verdict on the assigned area.** The burn arithmetic holds. The 1%-of-gross rule is exact in all four swap modes and both currency orderings: the `/99` gross-up satisfies floor((N + floor(N/99)) / 100) == floor(N/99), so burn equals 1% of the gross BTAX leg whether BTAX is specified or not. I fuzzed this to 2e22 with and without the maximum protocol fee, checked the 1 to 199 minor-unit boundaries, and confirmed the int128 bounds, the reserve-less-than-input property that keeps `HookDeltaExceedsSwapAmount` unreachable, and the zero-delta hook accounting against the vendored v4-core.\n\n**Findings written:**\n\n- **Medium, with proof.** Sells revert for any router that settles after `swap` once the PoolManager's total BTAX balance is below the 1% burn. The `take` to the dead address runs in `afterSwap` before the seller's BTAX is paid in, so it is funded only by what the manager already holds. After buyers drain the pool the manager holds 2 wei of BTAX and a sell of 1e22 fails with `ERC20InsufficientBalance(manager, 2, 1e20)`, while the same sell fills on an un-hooked pool. The README documents this limit, but it breaks the \"handle sells\" requirement with every production router. Suggested fix: mint an ERC-6909 claim when the balance is short and add a permissionless function that burns that claim to the dead address. The proof at `test/scratch/SellFundingProof.t.sol` fails on the current code and is fix-agnostic.\n- **Low.** `beforeInitialize` accepts the dynamic-fee sentinel. Since the hook never calls `updateDynamicLPFee`, anyone can create a hooked BTAX pool with a permanent 0% LP fee. Reproduced: fee 0x800000 initializes, `lpFee` reads 0, and a 100-quote buy returns a 0-fee gross minus the burn.\n- **Info.** BTAX-specified swaps revert on partial fills rather than taxing executed volume. Documented and inherent to v4's return-delta rules; recorded so the judge sees it was examined.\n\n**Coverage.** All four listed entry points have rows: `afterSwap` is \"finding\", the three token functions \"hold\" as unmodified OpenZeppelin v5.2.0. Extra rows cover `beforeSwap`, `beforeInitialize`, and four invariants. Not reached: a fork rehearsal against a live Universal Router, which the environment has no network for.","treeHash":null,"usage":{"cachedInputTokens":2025936,"inputTokens":482,"model":"claude-fable-5-1","outputTokens":47298,"runtime":"claude","turns":35,"wallClockMs":694060}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"ca080fd306399669","findings":[{"citation":"resolved","description":"The hook's second constructor argument (address token_) is immutable and is the only thing that decides which pools are taxed (_containsToken compares both currencies with launchedToken). launch.json writes that argument as the literal 0x0000000000000000000000000000000000000001. The deployer resolves only \"$poolManager\"; the manifest's own notes confirm there is no token substitution and that the literal must be replaced. As a deployable artifact the manifest therefore instantiates a hook that is permanently bound to a non-token address: every swap in the ETH/BTAX launch pool returns zero deltas, no Burned event, nothing to DEAD, and there is no owner or setter to repair it. Hook salt mining also depends on this argument, so the salt cannot be computed until the real address is in place. The actual gap is on the configuration side: the launch factory deploys the token and the hook in one transaction, so the token address must either be supplied by a deployer-side substitution for the launched token, or be the token's deterministic CREATE2 address computed from the factory's deployer and salt and written into constructorArgs[1] before the hook salt is mined. Needed evidence before admission: the resolved BurnTaxToken address (or the deployer feature that resolves it) and a hook salt mined against that exact argument.","line":7,"path":"launch.json","reproduction":"Fixture: HookFixture._setup(true) (real PoolManager, BTAX as currency0, MockERC20 quote). Deploy BurnTaxHook(manager, address(1)) at a 0x20cc-flag address exactly as launch.json specifies; wrong.launchedToken() == 0x…01. Initialize PoolKey(BTAX, quote, 3000, 60, hooks = that hook) at 2^96 and add 1e24 liquidity over [-600, 600]. Exact-input buy of 100e18 quote: expected (per brief) 1% of the BTAX leg at DEAD and a Burned event; actual: trader receives the full untaxed 99690060900928177460 BTAX, DEAD balance unchanged, no event. Exact-input sell of 100e18 BTAX: DEAD balance still unchanged. Reproduced in test/scratch/JudgeProbe.t.sol test_sentinelTokenHookDoesNotTaxBtaxPool.","severity":"high","snippet":"      \"0x0000000000000000000000000000000000000001\"","title":"launch.json binds the hook's immutable launchedToken to the sentinel 0x…01, so the deployed hook would never tax the launch pool"},{"citation":"resolved","description":"poolManager.take transfers BTAX out of the PoolManager's ERC-20 balance at once. On a sell the trader's BTAX is still only a debt in transient accounting when afterSwap runs: every production router (V4Router, Universal Router: SWAP then SETTLE) pays its input after swap returns. The transfer is therefore funded only by BTAX the manager already holds, i.e. the live reserves of BTAX pools. Whenever that is below sell/100 (exact-input) or P/99 (exact-output), OpenZeppelin's transfer reverts with ERC20InsufficientBalance, v4 wraps it as WrappedError(hook, afterSwap, WrappedError(token, transfer, …), HookCallFailed) and the whole sell reverts although the AMM could fill it (the identical sell on an un-hooked BTAX pool in the same state fills). The state is reached by ordinary buying: a token-only seeded launch range is bought out once buyers push the price past its top, leaving wei-level BTAX dust in the manager, at which point every holder who wants to sell through a stock router in either mode is refused. Recovery needs someone to donate BTAX to the manager, add BTAX liquidity, or ladder dust sells of at most 100x the current reserve. Buys are unaffected because the output is already in the manager. The same mid-swap transfer also under-credits any router that keeps a sync/settle pair open across swap (sync, transfer, swap, settle credits G - fee, leaving fee stranded in the manager if topped up), so the README's pre-settlement advice must be followed as a closed sync/transfer/settle before swap. Reported by all four specialists and the test writer; merged here. Minimal fix that preserves the no-owner/no-withdraw design: when launchedToken.balanceOf(poolManager) < fee, poolManager.mint(…, currency.toId(), fee) an ERC-6909 claim instead of take (to DEAD directly, which is as irrecoverable as the ERC-20 balance, or to the hook plus a permissionless function that unlocks, burns the claim and takes the BTAX to DEAD). mint debits the hook exactly as take does, so the return-delta accounting is unchanged. Keep the direct take when the balance covers it. The attached proof accepts either variant.","line":116,"path":"src/BurnTaxHook.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {PoolManager} from \"v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"v4-core/src/interfaces/IPoolManager.sol\";\nimport {IHooks} from \"v4-core/src/interfaces/IHooks.sol\";\nimport {IUnlockCallback} from \"v4-core/src/interfaces/callback/IUnlockCallback.sol\";\nimport {PoolKey} from \"v4-core/src/types/PoolKey.sol\";\nimport {Currency} from \"v4-core/src/types/Currency.sol\";\nimport {BalanceDelta} from \"v4-core/src/types/BalanceDelta.sol\";\nimport {SwapParams, ModifyLiquidityParams} from \"v4-core/src/types/PoolOperation.sol\";\nimport {TickMath} from \"v4-core/src/libraries/TickMath.sol\";\nimport {TransientStateLibrary} from \"v4-core/src/libraries/TransientStateLibrary.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {BurnTaxHook} from \"src/BurnTaxHook.sol\";\nimport {BurnTaxToken} from \"src/BurnTaxToken.sol\";\n\n/// @dev Router shaped like Uniswap's own (V4Router / Universal Router): unlock -> swap -> settle\n/// each owed currency afterwards -> take each credited currency. Nothing is paid before `swap` returns.\ncontract SettleAfterRouter is IUnlockCallback {\n    using TransientStateLibrary for IPoolManager;\n\n    IPoolManager public immutable manager;\n\n    constructor(IPoolManager m) {\n        manager = m;\n    }\n\n    function modify(PoolKey memory key, ModifyLiquidityParams memory p) external payable returns (BalanceDelta) {\n        return abi.decode(manager.unlock(abi.encode(msg.sender, key, true, p, SwapParams(false, 0, 0))), (BalanceDelta));\n    }\n\n    function swap(PoolKey memory key, SwapParams memory s) external payable returns (BalanceDelta) {\n        return abi.decode(\n            manager.unlock(abi.encode(msg.sender, key, false, ModifyLiquidityParams(0, 0, 0, 0), s)), (BalanceDelta)\n        );\n    }\n\n    function unlockCallback(bytes calldata data) external returns (bytes memory) {\n        require(msg.sender == address(manager));\n        (address payer, PoolKey memory key, bool liq, ModifyLiquidityParams memory p, SwapParams memory s) =\n            abi.decode(data, (address, PoolKey, bool, ModifyLiquidityParams, SwapParams));\n        BalanceDelta delta;\n        if (liq) (delta,) = manager.modifyLiquidity(key, p, \"\");\n        else delta = manager.swap(key, s, \"\");\n        _settle(key.currency0, payer);\n        _settle(key.currency1, payer);\n        return abi.encode(delta);\n    }\n\n    function _settle(Currency c, address payer) private {\n        int256 d = manager.currencyDelta(address(this), c);\n        if (d < 0) {\n            manager.sync(c);\n            if (Currency.unwrap(c) == address(0)) {\n                manager.settle{value: uint256(-d)}();\n            } else {\n                require(IERC20(Currency.unwrap(c)).transferFrom(payer, address(manager), uint256(-d)));\n                manager.settle();\n            }\n        } else if (d > 0) {\n            manager.take(c, payer, uint256(d));\n        }\n    }\n\n    receive() external payable {}\n}\n\n/// Launch shape: native ETH / BTAX, fee 3000, spacing 60, price 1:1, seeded with BTAX only below\n/// the current tick. Buyers take the whole BTAX side of the range; afterwards an ordinary sell\n/// through a settle-after-swap router must still execute, with 1% of the BTAX paid going to DEAD\n/// (or being committed as an ERC-6909 claim that only DEAD can ever receive).\ncontract JudgeSellFundingTest is Test {\n    address constant DEAD = 0x000000000000000000000000000000000000dEaD;\n    uint160 constant FLAGS = (1 << 13) | (1 << 7) | (1 << 6) | (1 << 3) | (1 << 2);\n\n    PoolManager manager;\n    SettleAfterRouter router;\n    BurnTaxToken token;\n    BurnTaxHook hook;\n    PoolKey key;\n\n    function setUp() public {\n        manager = new PoolManager(address(this));\n        router = new SettleAfterRouter(manager);\n        token = new BurnTaxToken();\n        hook = _deployHook();\n        key = PoolKey(Currency.wrap(address(0)), Currency.wrap(address(token)), 3000, 60, IHooks(address(hook)));\n        manager.initialize(key, 1 << 96);\n        token.approve(address(router), type(uint256).max);\n        vm.deal(address(this), 1000 ether);\n        router.modify(key, ModifyLiquidityParams(-120, -60, 1e22, bytes32(0)));\n        assertEq(address(manager).balance, 0);\n        assertGt(token.balanceOf(address(manager)), 1e18);\n    }\n\n    function _buyOutRange() internal {\n        router.swap{value: 500 ether}(key, SwapParams(true, -500 ether, TickMath.MIN_SQRT_PRICE + 1));\n        assertLt(token.balanceOf(address(manager)), 1e16, \"range should be bought out\");\n    }\n\n    function _committedBurn(uint256 deadBefore) internal view returns (uint256) {\n        uint256 id = uint256(uint160(address(token)));\n        return token.balanceOf(DEAD) - deadBefore + manager.balanceOf(address(hook), id)\n            + manager.balanceOf(DEAD, id);\n    }\n\n    function test_exactInputSellAfterBuyoutThroughOrdinaryRouter() public {\n        _buyOutRange();\n        uint256 deadBefore = token.balanceOf(DEAD);\n        uint256 myBefore = token.balanceOf(address(this));\n\n        BalanceDelta d = router.swap(key, SwapParams(false, -1 ether, TickMath.MAX_SQRT_PRICE - 1));\n\n        assertEq(d.amount1(), -1 ether, \"seller pays exactly 1 BTAX\");\n        assertEq(myBefore - token.balanceOf(address(this)), 1 ether);\n        assertEq(_committedBurn(deadBefore), 0.01 ether, \"1% of the paid BTAX is burned or committed to burn\");\n    }\n\n    function test_exactOutputSellAfterBuyoutThroughOrdinaryRouter() public {\n        _buyOutRange();\n        uint256 deadBefore = token.balanceOf(DEAD);\n        uint256 myBefore = token.balanceOf(address(this));\n\n        BalanceDelta d = router.swap(key, SwapParams(false, 0.1 ether, TickMath.MAX_SQRT_PRICE - 1));\n\n        assertEq(d.amount0(), 0.1 ether, \"buyer of ETH receives exactly the requested ETH\");\n        uint256 paid = myBefore - token.balanceOf(address(this));\n        assertGt(paid, 0);\n        assertEq(_committedBurn(deadBefore), paid / 100, \"1% of the paid BTAX is burned or committed to burn\");\n    }\n\n    function _deployHook() internal returns (BurnTaxHook deployed) {\n        bytes memory code = abi.encodePacked(type(BurnTaxHook).creationCode, abi.encode(manager, address(token)));\n        bytes32 h = keccak256(code);\n        for (uint256 i; i < 200_000; ++i) {\n            address predicted =\n                address(uint160(uint256(keccak256(abi.encodePacked(hex\"ff\", address(this), bytes32(i), h)))));\n            if ((uint160(predicted) & ((1 << 14) - 1)) == FLAGS) {\n                deployed = new BurnTaxHook{salt: bytes32(i)}(manager, address(token));\n                return deployed;\n            }\n        }\n        revert(\"no salt\");\n    }\n\n    receive() external payable {}\n}","reproduction":"Fresh PoolManager; BurnTaxToken; hook mined at flags 0x20cc; pool (native ETH currency0, BTAX currency1, fee 3000, spacing 60) initialised at 2^96; 1e22 liquidity in ticks [-120,-60] added from the BTAX side only (manager holds BTAX, 0 ETH). Step 1: exact-input buy of 500 ETH, zeroForOne=true, limit MIN_SQRT_PRICE+1, through a swap-then-settle router: succeeds, price leaves the range, manager BTAX balance = 1 wei. Step 2: exact-input sell SwapParams(false, -1e18, MAX_SQRT_PRICE-1) through the same router. Expected: swap fills, seller's amount1 delta is -1e18, 1e16 BTAX reaches DEAD (or is committed as a claim). Actual: afterSwap computes fee 1e16, take → BurnTaxToken.transfer reverts ERC20InsufficientBalance(manager, 1, 10000000000000000); the sell reverts with WrappedError(hook, 0xb47b2fb1, …, HookCallFailed). Step 2': exact-output sell SwapParams(false, +1e17, MAX_SQRT_PRICE-1) reverts the same way (ERC20InsufficientBalance(manager, 1, 1001065952790095)). The specialists' three proofs (quote-only pool, two-sided pool drained by a 1e25 buy) fail for the same reason. Run: forge test --match-path test/scratch/JudgeSellFunding.t.sol (fails on this code; passes with a balance-gated take/mint fallback, verified against a scratch copy of the hook).","severity":"medium","snippet":"        if (fee != 0) poolManager.take(Currency.wrap(launchedToken), DEAD, fee);","title":"afterSwap pays the burn with an immediate take before the seller has settled, so every ordinary sell reverts once the PoolManager holds less BTAX than 1% of the sale"},{"citation":"resolved","description":"beforeInitialize validates nothing in the key except key.hooks. A key with fee = LPFeeLibrary.DYNAMIC_FEE_FLAG (0x800000) passes PoolManager.initialize for any hook address; v4 initialises such a pool with lpFee 0, and only key.hooks may ever call updateDynamicLPFee. This hook has no such call and beforeSwap returns 0 without the override flag, so the pool's LP fee is 0 permanently while the 1% burn still applies. Any unprivileged account can create that pool beside the launch pool under the launch hook's identity; LPs who join it earn nothing and it undercuts the policy fee tiers (500/3000/10000) the README says are the supported ones. No funds are lost and the launch manifest cannot select the flag, so the launch pool itself is unaffected. Reported by three specialists; merged. Fix: in beforeInitialize `if (key.fee.isDynamicFee()) revert UnsupportedFee();` (LPFeeLibrary), which leaves every static fee accepted.","line":62,"path":"src/BurnTaxHook.sol","reproduction":"Fixture HookFixture._setup(true). From address 0xBEEF: manager.initialize(PoolKey(BTAX, quote, 0x800000, 60, hook), 2^96). Expected: revert. Actual: succeeds; StateLibrary.getSlot0(poolId).lpFee == 0. Add 1e24 liquidity over [-600,600]; exact-input buy of 100e18 quote returns 98990100989901009900 BTAX net in the dynamic pool versus 98693160291918895686 in the fee-3000 hooked pool with identical liquidity (no LP fee charged). manager.updateDynamicLPFee(dyn, 3000) from any address other than the hook reverts UnauthorizedDynamicLPFeeUpdate, and the hook has no code path that calls it. Reproduced in test/scratch/JudgeProbe.t.sol test_dynamicFeePoolAcceptedWithZeroLpFee.","severity":"low","snippet":"        if (address(key.hooks) != address(this)) revert WrongHook();","title":"beforeInitialize accepts the dynamic-fee flag, so anyone can open a hooked BTAX pool whose LP fee is 0 forever"},{"citation":"resolved","description":"When BTAX is the specified currency the burn is reserved in beforeSwap as a specified delta, and afterSwap can only adjust the unspecified currency, so a partial fill cannot be re-taxed on executed volume; the hook reverts the whole swap. A plain v4 pool, and this hook's own exact-input-buy and exact-output-sell paths, fill partially in the same situation. Effect: a sell or exact-output buy whose price limit is hit, or that exhausts the one-sided liquidity of a launch range, fails for the user rather than returning a partial fill, so limit-priced sells and oversized sells on the launch pool are refused although the brief asks for both modes in both directions to be handled. No funds move; the revert is atomic; the README documents it as a limit. Reported by two specialists; merged, kept at low so the author can decide whether to keep the documented limit (a defensible choice, since refunding the surplus reserve would pay the router, not the user) or restrict the fee to a post-swap unspecified-side mechanism.","line":102,"path":"src/BurnTaxHook.sol","reproduction":"Fixture HookFixture._setup(true) (BTAX is currency0, 1e24 liquidity over [-600,600]). SwapParams(zeroForOne=true, amountSpecified=-1e22, sqrtPriceLimitX96=TickMath.getSqrtPriceAtTick(-1)). On the un-hooked referenceKey pool: fills partially, trader pays 50149197655462481469 BTAX and price stops at tick -1. On the hooked key: reverts WrappedError(hook, afterSwap, PartialFillOnSpecifiedToken()). Exact-output buy amountSpecified=+1e22 with limit getSqrtPriceAtTick(1) reverts the same way. Existing test test_specifiedTokenPartialFillsRevertAtomically in test/Hook.t.sol and test/scratch/JudgeProbe.t.sol test_specifiedPartialFillReverts show it.","severity":"low","snippet":"            if (tokenDelta != params.amountSpecified + fee.toInt256()) {\n                revert PartialFillOnSpecifiedToken();\n            }","title":"BTAX-specified swaps (exact-input sells, exact-output buys) revert instead of partially filling at a price limit or liquidity edge"}],"hash":"7a110470bd59e63b6c82938bd99d50dd1e75c3787bc0eccaaebe5ffe0096bf0f","nodeId":"67655110-b342-462d-a366-692664c09c7e","outcome":"completed","summary":"The findings file is in place at the repository root, excluded from git by the repo's own exclude rule, and no tracked file was changed. The scratch tests have been removed.\n\n**Outcome.** Four findings, one high, one medium, two low, with a coverage record of ten rows. Every specialist finding was reproduced against a real PoolManager; the five reports of the sell-funding defect were merged into one, the three dynamic-fee reports into one, and the two partial-fill reports into one. The sync/settle under-credit report was folded into the sell-funding finding because it shares the root cause and the fix.\n\n**Findings written to .imd-findings.json:**\n\n1. **High, launch.json line 7.** The hook's immutable token argument is the sentinel address 0x…01. A hook deployed from the manifest as written never taxes the launch pool, and nothing can repair it after deployment. I reproduced it by deploying the hook with that argument and swapping in a BTAX pool: no burn, no event. The gap is configuration: the deployer resolves only the pool manager, so the token's resolved or CREATE2-predicted address must be written in before the hook salt is mined.\n\n2. **Medium, src/BurnTaxHook.sol line 116, with proof.** The burn is paid by an immediate take inside afterSwap, before a settle-after router has paid the seller's BTAX in. Once buyers empty the seeded range the manager holds dust, and every ordinary sell in both modes reverts with ERC20InsufficientBalance. All three specialist proofs failed for this reason, and my own proof fails on the current code and passes against a scratch copy of the hook that mints an ERC-6909 claim when the balance is short.\n\n3. **Low, line 62.** beforeInitialize accepts the dynamic-fee flag. Anyone can open a hooked BTAX pool whose LP fee is zero forever, since only the hook could ever set it and it has no such path.\n\n4. **Low, line 102.** Exact-input sells and exact-output buys revert on any partial fill where a plain pool fills partially. It is documented, atomic and loses no funds, so it is reported for the author to decide on.\n\n**Coverage.** afterSwap and beforeInitialize point to findings 2 and 3. The three token entry points hold as unmodified OpenZeppelin ERC-20. beforeSwap, the constructor and two accounting invariants hold. The existing 77-test suite passes.","treeHash":null,"usage":{"cachedInputTokens":1496952,"inputTokens":386,"model":"claude-fable-5-1","outputTokens":29584,"runtime":"claude","turns":31,"wallClockMs":428493}},{"artifacts":[],"attempt":1,"bundleHash":"7004a19c1f31822484449c471bb741a7fccd9f732a8c1a1bdc070551caca9f1e","device":"35c52a5b502e847c","findings":[],"hash":"7a19e11ffafef91a4e246dfe734da80b6e4c4eef225c9ff7fc1f624694d78da1","nodeId":"1ade3e93-7644-44b8-b43d-7a3e2d7f2dc9","outcome":"completed","summary":"Fixed sell funding and open-sync settlement using claims assigned directly to DEAD when needed. Dynamic-fee BTAX pools now revert. The documented partial-fill limit remains, with the advisory disputed.\n\nAll findings are answered in [.imd-responses.json](/home/identitymd5/.identitymd/work/81c6d9d5-265a-4fb0-a46f-116edcf3ef33/1ade3e93-7644-44b8-b43d-7a3e2d7f2dc9/.imd-responses.json).\n\nValidation passed: `forge build`, all 75 tests, `forge fmt --check`, and both supplied proof tests.","treeHash":"f8528325ae64daa3b4095f57046f6cdf89257455","usage":{"cachedInputTokens":1105792,"inputTokens":90964,"model":"gpt-6-astra","outputTokens":12131,"runtime":"codex","turns":5,"wallClockMs":417440}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"bb0a3bf63233e5e5","findings":[],"hash":"8dd82d809f2175323330b9627d449b5aa19231f8acbcfaff2fcc983447ff44ed","nodeId":"21d9d014-103f-4d86-a333-ac33af4ef7d5","outcome":"failed","summary":"could not restore accepted work: accepted work conflicts with a dependency, which plan validation should have prevented: ","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":null,"outputTokens":0,"runtime":"codex","turns":0,"wallClockMs":185}},{"artifacts":[],"attempt":3,"bundleHash":null,"device":"02ae6543274731ab","findings":[],"hash":"9a3c4060b8ea8b85d5d067142e0ec8893f2ee3ce783e7cce1f9dd2740532f8b9","nodeId":"21d9d014-103f-4d86-a333-ac33af4ef7d5","outcome":"failed","summary":"could not restore accepted work: accepted work conflicts with a dependency, which plan validation should have prevented: ","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":null,"outputTokens":0,"runtime":"codex","turns":0,"wallClockMs":351}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"3b260b68e9ad6a37","findings":[{"citation":"resolved","description":"afterSwap pays the burn with poolManager.take, which transfers BTAX out of the PoolManager's ERC-20 balance immediately. On a sell the seller's BTAX is still only a debt in transient accounting at that point; every production router (Universal Router / V4Router: SWAP then SETTLE_ALL) settles after swap returns. So the take is funded solely by whatever BTAX the manager already holds, i.e. this pool's remaining BTAX reserve. Once buys have moved the price past the top of the seeded range (a token-only launch position is finite), or whenever a sell is larger than 100x the remaining reserve, the ERC-20 transfer fails with ERC20InsufficientBalance and the whole swap reverts. The sell direction of the launch pool is therefore unusable through standard routers exactly in the state a launch reaches after a run of buys, until someone bootstraps the reserve with sub-100-wei dust sells (fee rounds to 0) or a bespoke router that pre-settles. The README documents this as an integrator duty, but the brief requires both directions to be handled and the reference for this task explicitly asks for a mint-claim fallback (poolManager.mint of an ERC-6909 claim to the hook, plus a permissionless redeem to DEAD) or a balance-gated take. Buys are unaffected because the output tokens are already in the manager.","line":116,"path":"src/BurnTaxHook.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {PoolManager} from \"v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"v4-core/src/interfaces/IPoolManager.sol\";\nimport {IHooks} from \"v4-core/src/interfaces/IHooks.sol\";\nimport {IUnlockCallback} from \"v4-core/src/interfaces/callback/IUnlockCallback.sol\";\nimport {PoolKey} from \"v4-core/src/types/PoolKey.sol\";\nimport {Currency} from \"v4-core/src/types/Currency.sol\";\nimport {BalanceDelta} from \"v4-core/src/types/BalanceDelta.sol\";\nimport {SwapParams, ModifyLiquidityParams} from \"v4-core/src/types/PoolOperation.sol\";\nimport {TickMath} from \"v4-core/src/libraries/TickMath.sol\";\nimport {TransientStateLibrary} from \"v4-core/src/libraries/TransientStateLibrary.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {BurnTaxHook} from \"src/BurnTaxHook.sol\";\nimport {BurnTaxToken} from \"src/BurnTaxToken.sol\";\n\n/// @dev Minimal router that behaves like production routers (Universal Router / V4Router):\n/// it calls `swap` first and settles its debts afterwards, in the same unlock.\ncontract SettleAfterRouter is IUnlockCallback {\n    using TransientStateLibrary for IPoolManager;\n\n    IPoolManager public immutable manager;\n\n    constructor(IPoolManager m) {\n        manager = m;\n    }\n\n    function modify(PoolKey memory key, ModifyLiquidityParams memory p) external payable returns (BalanceDelta) {\n        return abi.decode(manager.unlock(abi.encode(msg.sender, key, true, p, SwapParams(false, 0, 0))), (BalanceDelta));\n    }\n\n    function swap(PoolKey memory key, SwapParams memory s) external payable returns (BalanceDelta) {\n        return abi.decode(\n            manager.unlock(abi.encode(msg.sender, key, false, ModifyLiquidityParams(0, 0, 0, 0), s)), (BalanceDelta)\n        );\n    }\n\n    function unlockCallback(bytes calldata data) external returns (bytes memory) {\n        require(msg.sender == address(manager));\n        (address payer, PoolKey memory key, bool liq, ModifyLiquidityParams memory p, SwapParams memory s) =\n            abi.decode(data, (address, PoolKey, bool, ModifyLiquidityParams, SwapParams));\n        BalanceDelta delta;\n        if (liq) (delta,) = manager.modifyLiquidity(key, p, \"\");\n        else delta = manager.swap(key, s, \"\");\n        _settle(key.currency0, payer);\n        _settle(key.currency1, payer);\n        return abi.encode(delta);\n    }\n\n    function _settle(Currency c, address payer) private {\n        int256 d = manager.currencyDelta(address(this), c);\n        if (d < 0) {\n            manager.sync(c);\n            if (Currency.unwrap(c) == address(0)) {\n                manager.settle{value: uint256(-d)}();\n            } else {\n                require(IERC20(Currency.unwrap(c)).transferFrom(payer, address(manager), uint256(-d)));\n                manager.settle();\n            }\n        } else if (d > 0) {\n            manager.take(c, payer, uint256(d));\n        }\n    }\n\n    receive() external payable {}\n}\n\ncontract SellAfterBuyoutTest is Test {\n    address constant DEAD = 0x000000000000000000000000000000000000dEaD;\n    uint160 constant FLAGS = (1 << 13) | (1 << 7) | (1 << 6) | (1 << 3) | (1 << 2);\n\n    PoolManager manager;\n    SettleAfterRouter router;\n    BurnTaxToken token;\n    BurnTaxHook hook;\n    PoolKey key;\n\n    function setUp() public {\n        manager = new PoolManager(address(this));\n        router = new SettleAfterRouter(manager);\n        token = new BurnTaxToken();\n        hook = _deployHook();\n        // Launch shape: native ETH is currency0, BTAX is currency1, price 1:1.\n        key = PoolKey(Currency.wrap(address(0)), Currency.wrap(address(token)), 3000, 60, IHooks(address(hook)));\n        manager.initialize(key, 1 << 96);\n        token.approve(address(router), type(uint256).max);\n        vm.deal(address(this), 1000 ether);\n        // Token-only seeding below the current tick: the position holds only BTAX.\n        router.modify(key, ModifyLiquidityParams(-120, -60, 1e22, bytes32(0)));\n        assertEq(address(manager).balance, 0);\n        assertGt(token.balanceOf(address(manager)), 0);\n    }\n\n    /// Buys consume the whole BTAX side of the range. Afterwards an ordinary sell through a\n    /// settle-after-swap router cannot execute because afterSwap takes the burn from a manager\n    /// that holds no BTAX yet. Expected: the sell fills and 1% of the paid BTAX reaches DEAD.\n    function test_sellAfterRangeIsBoughtOut() public {\n        // Buy with more ETH than the range can absorb: price exits the range, BTAX reserve -> 0.\n        router.swap{value: 500 ether}(\n            key, SwapParams(true, -500 ether, TickMath.MIN_SQRT_PRICE + 1)\n        );\n        uint256 reserve = token.balanceOf(address(manager));\n        assertLt(reserve, 1e16, \"range should be bought out\");\n\n        uint256 deadBefore = token.balanceOf(DEAD);\n        uint256 myBefore = token.balanceOf(address(this));\n\n        // Ordinary exact-input sell of 1 BTAX. Burn would be 0.01 BTAX, more than the manager holds.\n        BalanceDelta d = router.swap(key, SwapParams(false, -1 ether, TickMath.MAX_SQRT_PRICE - 1));\n\n        assertEq(d.amount1(), -1 ether, \"seller pays exactly 1 BTAX\");\n        assertEq(myBefore - token.balanceOf(address(this)), 1 ether);\n        // The 1% must be accounted for: either already at DEAD, or held by the hook as an\n        // ERC-6909 claim awaiting redemption to DEAD.\n        uint256 burnedNow = token.balanceOf(DEAD) - deadBefore;\n        uint256 claimed = manager.balanceOf(address(hook), uint256(uint160(address(token))));\n        assertEq(burnedNow + claimed, 0.01 ether, \"1% of the paid BTAX is burned or reserved for burning\");\n    }\n\n    function _deployHook() internal returns (BurnTaxHook deployed) {\n        bytes memory code = abi.encodePacked(type(BurnTaxHook).creationCode, abi.encode(manager, address(token)));\n        bytes32 h = keccak256(code);\n        for (uint256 i; i < 200_000; ++i) {\n            address predicted =\n                address(uint160(uint256(keccak256(abi.encodePacked(hex\"ff\", address(this), bytes32(i), h)))));\n            if ((uint160(predicted) & ((1 << 14) - 1)) == FLAGS) {\n                deployed = new BurnTaxHook{salt: bytes32(i)}(manager, address(token));\n                return deployed;\n            }\n        }\n        revert(\"no salt\");\n    }\n\n    receive() external payable {}\n}","reproduction":"State: fresh PoolManager; pool (ETH, BTAX, fee 3000, spacing 60, this hook) initialised at 1:1; liquidity 1e22 in [-120,-60] added from the BTAX side only (manager holds BTAX, 0 ETH). Step 1: exact-input buy of 500 ETH with limit MIN_SQRT_PRICE+1 -> succeeds, price exits the range, manager BTAX balance = 1 wei. Step 2: exact-input sell of 1e18 BTAX via a router that settles after swap (as Universal Router does). Expected: swap fills, seller pays 1e18, 1e16 BTAX reaches DEAD (or is reserved as a claim). Actual: afterSwap -> PoolManager.take(BTAX, DEAD, 1e16) -> BurnTaxToken.transfer reverts ERC20InsufficientBalance(manager, 1, 1e16), wrapped as WrappedError(hook, afterSwap, ...), the entire sell reverts. Same outcome for any sell whose amount/100 exceeds token.balanceOf(manager); existing test FreshManagerTest.test_sellWithoutReservesOrPrefundingRevertsAtomically shows the quote-only variant. Run: forge test --match-path test/scratch/SellAfterBuyout.t.sol","severity":"medium","snippet":"        if (fee != 0) poolManager.take(Currency.wrap(launchedToken), DEAD, fee);","title":"Sells revert whenever the PoolManager holds less BTAX than the burn: afterSwap takes the fee before the seller has settled"},{"citation":"resolved","description":"beforeInitialize only checks key.hooks. A pool keyed with fee = LPFeeLibrary.DYNAMIC_FEE_FLAG (0x800000) is accepted; v4 sets its initial LP fee to 0 and only the hook may ever change it (PoolManager.updateDynamicLPFee requires msg.sender == key.hooks). The hook has no such call and beforeSwap always returns lpFeeOverride 0 without the override flag, so the pool's LP fee is 0 forever. Anyone can deploy such a BTAX pool beside the launch pool; it undercuts the launch pool's LP fee (3000/500/10000 from the manifest) and routes volume to a pool whose LPs earn nothing, while the 1% burn still applies. The brief says the LP fee is 'the pool's own' and the launch policy allows only 500/3000/10000; rejecting key.fee.isDynamicFee() in beforeInitialize (or restricting to the policy tiers for pools containing launchedToken) closes it.","line":62,"path":"src/BurnTaxHook.sol","reproduction":"State: HookFixture._setup(true). Call manager.initialize(PoolKey(currency0=BTAX, currency1=quote, fee=0x800000, tickSpacing=60, hooks=hook), 1<<96) -> succeeds. StateLibrary.getSlot0(dynId).lpFee == 0. Add liquidity 1e24 in [-600,600] and do an exact-input buy of 100e18 quote: hooked dynamic pool returns 98990100989901009900 BTAX net, while the identical plain fee-3000 pool returns 99690060900928177460 before burn; no LP fee was charged and nobody can ever set one. Reproduced in test/scratch/DynamicFee.t.sol (log 'lpFee of dynamic pool: 0').","severity":"low","snippet":"        if (address(key.hooks) != address(this)) revert WrongHook();","title":"beforeInitialize accepts the dynamic-fee flag, creating BTAX pools that run at a permanent 0% LP fee while still burning"},{"citation":"resolved","description":"For exact-input sells and exact-output buys the fee is reserved in beforeSwap from the requested amount, and afterSwap can only return an unspecified-currency delta, so it cannot refund the reserved part if the AMM filled less. The hook resolves this by reverting on any partial fill. In a plain v4 pool, and in this hook's exact-input-buy / exact-output-sell paths, a swap that hits sqrtPriceLimitX96 (or exhausts the range's liquidity) fills partially and succeeds. The asymmetry means a limit-priced sell order, or a sell larger than the available liquidity, fails outright on the launch pool although it would execute on any unhooked pool. It is documented in the README; reported so the judge can weigh whether the brief's 'handle exact-input and exact-output swaps in both directions' tolerates it. No funds are lost and the revert is atomic.","line":103,"path":"src/BurnTaxHook.sol","reproduction":"State: HookFixture._setup(true) (BTAX is currency0, 1e24 liquidity in [-600,600]). Exact-input sell: SwapParams(zeroForOne=true, amountSpecified=-1e22, sqrtPriceLimitX96=getSqrtPriceAtTick(-1)). Expected (plain referenceKey pool): fills partially, trader pays the amount needed to move price to tick -1. Actual (hooked key): reverts WrappedError(hook, afterSwap, PartialFillOnSpecifiedToken()). Same for exact-output buy amountSpecified=+1e22 with limit getSqrtPriceAtTick(1). Shown by existing HookToken0Test.test_specifiedTokenPartialFillsRevertAtomically versus test_unspecifiedTokenPartialFillsTaxOnlyExecutedAmount.","severity":"low","snippet":"                revert PartialFillOnSpecifiedToken();","title":"BTAX-specified swaps that reach their price limit revert instead of partially filling, unlike plain pools and the two quote-specified modes"}],"hash":"9e5ea2550b620903f7aabb740dcf7af2878e08aa9a2306afad380c2a5e4655ee","nodeId":"585313c7-41d8-44d6-a33f-ae8a93eb674d","outcome":"completed","summary":"Review complete. The findings file is written at `.imd-findings.json` with three findings and eleven coverage rows, and the proof test is in `test/scratch/SellAfterBuyout.t.sol`.\n\n**Findings**\n\n- **Medium: sells revert when the manager's BTAX reserve is below the burn.** The hook's `afterSwap` pays the burn with an immediate `take`, before the seller's router has settled its input. Production routers settle after the swap, so the transfer is funded only by the pool's remaining BTAX. After buys push the price past the top of a token-only launch range, or for any sell over 100 times the remaining reserve, the ERC-20 transfer fails and the whole sell reverts. The attached proof test seeds a token-only pool, buys the range out, and shows a 1 BTAX sell reverting with `ERC20InsufficientBalance`. It will pass with a balance-gated take or a mint-claim fallback plus a permissionless redeem to the dead address, which the task's own reference asks for.\n- **Low: the dynamic-fee flag is accepted at initialization.** A BTAX pool keyed with the dynamic flag starts at a zero LP fee and nothing can ever change it, since only the hook may call the fee setter and it never does. Reproduced: such a pool initializes, reports an LP fee of zero, and swaps with no fee while still burning.\n- **Low: BTAX-specified swaps that hit a price limit revert instead of filling partially.** Exact-input sells and exact-output buys reserve the fee before the AMM runs and cannot refund it afterwards, so the hook reverts on any partial fill. Plain pools and the two quote-specified modes fill partially. This is documented, atomic, and loses no funds, so it is reported for the judge to weigh against the brief.\n\n**What held**\n\nThe delta accounting nets to zero for the hook in all four modes and both currency orderings. The burn equals one percent of the gross BTAX leg in every mode, including the `/99` gross-up cases, and the quote leg is untouched. Unrelated pools return zero deltas and emit nothing. Callbacks reject callers other than the PoolManager and keys naming another hook. The token is an unmodified OpenZeppelin ERC-20 with a one-time constructor mint and no admin path. Both static-analysis leads were style-only and did not reproduce as defects.","treeHash":null,"usage":{"cachedInputTokens":1203515,"inputTokens":290,"model":"claude-fable-5-1","outputTokens":27932,"runtime":"claude","turns":30,"wallClockMs":387139}},{"artifacts":[],"attempt":2,"bundleHash":"89aa65c5e935c11483bc8ad70909102e652774708581aa9afae364cdfa8d117c","device":"3f6a9bdd601cb99f","findings":[],"hash":"a053a07f0c1801edbc60d9fe4fb216343ab33565ff44378d3198e85f01a769b9","nodeId":"0e2f943e-3495-484f-b0f7-332cb18cab2c","outcome":"completed","summary":"Created [launch.json](/home/seat/.identitymd/work/81c6d9d5-265a-4fb0-a46f-116edcf3ef33/0e2f943e-3495-484f-b0f7-332cb18cab2c/launch.json). Only that file changed.\n\nSchema, ABI and permission checks passed. `forge build` succeeded; all 59 tests passed.\n\nDeployment remains blocked: the repository provides no actual BTAX address. The manifest explicitly documents its token-address sentinel, which must be replaced before deployment.","treeHash":"463389cf227816c98d94fb6a0730299076fac3b5","usage":{"cachedInputTokens":261888,"inputTokens":50853,"model":"gpt-6-astra","outputTokens":5073,"runtime":"codex","turns":4,"wallClockMs":173073}},{"artifacts":[],"attempt":2,"bundleHash":null,"device":"35c52a5b502e847c","findings":[],"hash":"bbbaee066632e852d508bb0cff331e7b3c93ee472c9ef070b2cfad9ec68d30c4","nodeId":"21d9d014-103f-4d86-a333-ac33af4ef7d5","outcome":"failed","summary":"could not restore accepted work: accepted work conflicts with a dependency, which plan validation should have prevented: ","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":null,"outputTokens":0,"runtime":"codex","turns":0,"wallClockMs":515}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"d2d5a117dd72f6b4","findings":[{"citation":"resolved","description":"The burn is paid by an immediate ERC-20 transfer out of the PoolManager (`take`) inside `afterSwap`. On a sell, the seller's BTAX has not been settled yet at that point (every standard v4 router, including the Universal Router and V4Router, calls `swap` first and `SETTLE` afterwards), so the transfer is funded only by BTAX the manager already holds: the pool reserves. A sell of G therefore needs the manager to hold at least G/100 BTAX *before* the trade, or the OpenZeppelin transfer reverts with ERC20InsufficientBalance(manager, balance, G/100), v4 wraps it as WrappedError(hook, afterSwap, ..., HookCallFailed) and the whole sell reverts. The state is reachable by any unprivileged buyer: a launch pool seeded single-sided with BTAX in a bounded tick range is fully bought out once buyers push the price past the range's edge, leaving the manager with wei-level BTAX dust. From then on, every exact-input and exact-output sell through a swap-then-settle router fails, in both currency orderings, which breaks the requirement that the hook handles both swap directions in both modes. Recovery is possible only by a ladder of sells each at most 100x the manager's current BTAX balance (measured: 9 chained sells from 1 wei of dust to reach a 1e18 reserve), by someone adding BTAX liquidity, or by a custom router that pre-settles BTAX before calling swap. The README documents the pre-settlement requirement as an integration responsibility, but no production router does it, so the limit is user-facing. Buys are unaffected because the AMM output G is already in the manager and G/100 < G. Suggested minimal fix that preserves the design: fund the burn from a claim when the balance is short, e.g. `if (currency.balanceOf(address(poolManager)) >= fee) poolManager.take(currency, DEAD, fee); else poolManager.mint(DEAD, currency.toId(), fee);` (an ERC-6909 claim owned by 0xdEaD is as irrecoverable as the ERC-20 balance), or mint the claim to the hook and expose a permissionless redeem that unlocks, burns the claim and takes the BTAX to DEAD, as the launch reference recommends for fee-bearing hooks. The attached proof passes under the first variant.","line":116,"path":"src/BurnTaxHook.sol","reproduction":"Fresh PoolManager; BurnTaxToken; hook mined at flags 0x20cc; pool key (ETH as currency0, BTAX as currency1, fee 3000, tickSpacing 60) initialised at sqrtPrice 2^96; add 1e22 liquidity in ticks [-120,-60] (BTAX only, below the current price). 1) Buy: swap(zeroForOne=true, amountSpecified=-1000 ether, limit MIN_SQRT_PRICE+1) through a swap-then-settle router. The range is exhausted and the manager is left with ~2.1e10 wei of BTAX. 2) Sell: swap(zeroForOne=false, amountSpecified=-1 ether, limit MAX_SQRT_PRICE-1) through the same router. Expected: the sell executes, the trader pays exactly 1e18 BTAX, Burned(poolId, false, 1e16) is emitted and 1e16 BTAX ends up irrecoverable. Actual: afterSwap computes fee = 1e16, calls poolManager.take(BTAX, 0xdEaD, 1e16); the ERC-20 transfer reverts with ERC20InsufficientBalance(manager, 21248304356, 1e16) and the sell reverts with WrappedError(hook, 0xb47b2fb1 /*afterSwap*/, ..., HookCallFailed). The same state is reproduced by the repository's own test_sellWithoutReservesOrPrefundingRevertsAtomically (quote-only pool, no prefund). Run: forge test --match-path test/scratch/SellAfterBuyout.t.sol","severity":"medium","snippet":"        if (fee != 0) poolManager.take(Currency.wrap(launchedToken), DEAD, fee);","title":"Sells revert whenever the PoolManager holds less than 1% of the sold BTAX: afterSwap's take() to DEAD runs before the seller settles, so a bought-out pool refuses every ordinary sell"},{"citation":"resolved","description":"The only check in beforeInitialize is key.hooks == this. A pool key with fee = 0x800000 (LPFeeLibrary.DYNAMIC_FEE_FLAG) is accepted; v4 initialises such a pool with lpFee = 0 and only the hook may later call updateDynamicLPFee, which this hook never does and has no way to do. Anyone can therefore create a second BTAX pool with this hook (same pair, any tick spacing) whose LP fee is 0 forever while the 1% burn still applies. Measured: a 10 ETH exact-input buy returns 9.8999e18 BTAX in the dynamic-fee pool versus 9.9699e18 in the 3000-fee launch pool with identical liquidity. The launch pool itself is unaffected and nobody is forced to provide liquidity to the zero-fee pool, so this is informational: LPs who join such a pool earn nothing, and the README's statement that the LP fee is always the pool's own is technically true but the pool's own fee is then zero. The launch manifest cannot select the dynamic flag, so a launch cannot hit this. Optional hardening consistent with the design: revert in beforeInitialize when key.fee.isDynamicFee().","line":56,"path":"src/BurnTaxHook.sol","reproduction":"Same fixture as test/Hook.t.sol (HookToken1Test setUp). key2 = key with fee = 0x800000; manager.initialize(key2, 1<<96) succeeds; router.modify(key2, ModifyLiquidityParams(-600, 600, 1e24, 0)); getSlot0(key2.toId()).lpFee == 0; router.swap(key2, buy exact-input 10 ether) returns token delta 9899901000989990100 and burns 1% to DEAD, versus 9969900600091017092 for the same trade on the 3000-fee reference pool. Expected per the stated launch policy (fee tiers 500/3000/10000 only): initialization refused. Actual: accepted with a 0 LP fee that can never change.","severity":"info","snippet":"    function beforeInitialize(address, PoolKey calldata key, uint160)","title":"beforeInitialize accepts dynamic-fee pools, and the hook never sets a dynamic LP fee, so such a BTAX pool trades at a permanent 0% LP fee"}],"hash":"bfa41d706c35a0c1d6e91d1ecb4355a537894223d2e757ea9a11fa7c086d214c","nodeId":"f89aac7d-930c-496b-acd9-92ab8892cf4f","outcome":"completed","summary":"Review complete. The findings are in `.imd-findings.json` at the repository root. No tracked file was changed; the only additions are the findings file and my proof test under `test/scratch/`, both git-ignored.\n\n**What I audited.** The Economic Security, Invariant and Flow Gap guides against the BurnTax hook and token, with the full 59-test suite passing as baseline. I traced the delta accounting in all four swap modes and both currency orderings, re-derived the rounding identities, and probed with scratch tests on a real PoolManager: a bought-out pool, a dynamic-fee pool, and swaps with the protocol fee at maximum.\n\n**Findings.**\n\n- **Medium: sells revert when the manager holds under 1% of the sold BTAX.** The burn is paid by `take` inside afterSwap, before the seller's router settles its input, so it is funded only by BTAX already in the manager. Any buyer who exhausts a bounded single-sided launch range leaves wei-level dust, after which every ordinary exact-in and exact-out sell fails with an insufficient-balance error wrapped by v4. Recovery needs a ladder of sells each at most 100x the current reserve (measured: 9 chained sells to get from 1 wei back to 1e18), a liquidity add, or a custom pre-settling router. The README documents the pre-settlement requirement, but no production router does it. A proof test fails on the current code and passes with a claim-mint fallback. Suggested fix: take when the balance covers the fee, otherwise mint an ERC-6909 claim to DEAD or to the hook with a permissionless redeem.\n- **Info: dynamic-fee pools are accepted and run at a permanent 0% LP fee.** beforeInitialize checks only the hook address, and the hook never calls updateDynamicLPFee. The launch pool is unaffected and the manifest cannot select the flag.\n\n**What holds.** The 1% is exactly floor(gross BTAX leg / 100) in every mode, including exact-output grossing by 1/99, and it is unchanged with protocol fees on. The quote leg matches a plain pool. The hook ends every swap with zero delta, zero claims and zero balance. Partial fills on BTAX-specified trades revert atomically; others tax only executed volume. Unrelated pools are untouched. The token is unmodified OpenZeppelin v5.2.0 with a fixed supply. Coverage rows answer all four listed entry points plus the view callbacks and the invariants I checked.\n\n**Not reached.** Nothing in my area was left unexamined. Static-analysis leads were all low and none reproduced as a defect.","treeHash":null,"usage":{"cachedInputTokens":2039922,"inputTokens":514,"model":"claude-fable-5-1","outputTokens":44410,"runtime":"claude","turns":44,"wallClockMs":598875}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"72b617d4b615473a","findings":[{"citation":"resolved","description":"Asymmetry between the buy and sell branches of afterSwap (pair: buy/sell; lens: asymmetry x flow). Both branches end in the same immediate poolManager.take(BTAX, DEAD, fee). On a buy the fee is a slice of BTAX the pool itself just released, so the manager always holds it. On a sell the trader's BTAX has not been settled yet when afterSwap runs, so the transfer is funded by whatever BTAX the PoolManager happens to hold for other reasons. When that balance is below the fee the ERC-20 transfer inside take reverts (ERC20InsufficientBalance wrapped in WrappedError) and the whole sell reverts, although the trade itself is fine. The state is reachable by ordinary buying: a launch pool seeded with BTAX only in a bounded range holds ~0 BTAX once buyers have bought the range out, and at exactly that moment every holder who wants to sell through a swap-then-settle router is refused. README ('Immediate transfer funding') documents the condition and test/FreshManager.t.sol:62 asserts the revert, but the stated remedy (router pre-settles BTAX before swap) is not something a stock v4 router does (v4-periphery V4Router / Universal Router swap first and settle afterwards), so for ordinary users the sell side is simply unavailable in that state. It is recoverable by anyone (see reproduction), hence low. Minimal fix that keeps the no-owner/no-withdraw design: when launchedToken.balanceOf(poolManager) < fee, poolManager.mint(address(this), id, fee) instead of take, plus a function anyone may call that unlocks, burns the hook's claim and takes it to DEAD; or always mint and flush.","line":116,"path":"src/BurnTaxHook.sol","reproduction":"Verified with the repo's own helpers (HookFixture._deployHook, PoolRouter) on a fresh PoolManager. 1) Pool {currency0: native ETH, currency1: BTAX, fee 3000, tickSpacing 60, hooks: BurnTaxHook}, initialize at sqrtPriceX96 = 2^96. 2) Seed token-only: router.modify(key, ModifyLiquidityParams(-120, -60, 1e22, 0)) -> manager holds 29863828045988816613 BTAX, 0 ETH. 3) Buyer: router.swap{value: 100 ether}(key, SwapParams(zeroForOne=true, amountSpecified=-100 ether, MIN_SQRT_PRICE+1), 0, 100 ether, prefund=0) -> the range is bought out; manager now holds 1 wei BTAX and 30224475487224067890 wei ETH. 4) Seller: router.swap(key, SwapParams(zeroForOne=false, amountSpecified=-1 ether, MAX_SQRT_PRICE-1), 0, 1 ether, prefund=0). Expected: sell executes, 0.01 BTAX goes to DEAD, seller pays 1 BTAX. Actual: reverts with WrappedError(hook, afterSwap, ERC20InsufficientBalance(manager, 1, 10000000000000000), HookCallFailed). 5) Exact-output sell SwapParams(false, +0.001 ether, MAX_SQRT_PRICE-1) reverts the same way. 6) A 99-wei exact-input sell (fee rounds to 0) succeeds, and after anyone does token.transfer(address(manager), 0.01 ether) the 1 BTAX sell from step 4 succeeds - so the state is recoverable, but only by donating BTAX to the manager or bootstrapping with dust sells.","severity":"low","snippet":"if (fee != 0) poolManager.take(Currency.wrap(launchedToken), DEAD, fee);","title":"Sell branch pays the burn out of the manager's unrelated BTAX balance: sells revert for swap-then-settle routers once the seeded BTAX is bought out"},{"citation":"resolved","description":"Trust gap between the hook and the integrator the README delegates sell funding to. PoolManager.settle credits balanceOf(manager) - reservesRecordedBySync. The hook's take moves `fee` BTAX out of the manager in the middle of the swap, so if the seller's router has BTAX synced across the swap (sync -> transfer -> swap -> settle, a natural way to implement the README's 'pre-settle sufficient BTAX inside the same unlock before calling swap'), settle credits G - fee instead of G. The swap delta is still -G, so the router is left with an unsettled -fee: it either reverts with CurrencyNotSettled or tops up, in which case the seller pays 101% and `fee` BTAX stays in the manager credited to nobody (not burned, not in the pool, not claimable). README never says the sync/settle pair must be closed before swap; test/helpers/PoolRouter.sol only happens to do so. Fix: the same claim-mint path as finding 1 (mint does not move the manager's token balance), or state the ordering requirement explicitly in the README.","line":116,"path":"src/BurnTaxHook.sol","reproduction":"Verified on the HookFixture pool (BTAX = currency0, quote = currency1, fee 3000, tickSpacing 60, liquidity 1e24 in [-600,600]). Router unlock callback for an exact-input sell of 100 BTAX: manager.sync(BTAX); BTAX.transferFrom(seller, manager, 100e18); manager.swap(key, SwapParams(zeroForOne=true, amountSpecified=-100e18, MIN_SQRT_PRICE+1), \"\"); manager.settle(). Expected: router BTAX delta after settle = 0, seller paid 100 BTAX, 1 BTAX burned. Actual: manager.currencyDelta(router, BTAX) = -1000000000000000000 after settle; closing it (sync, transfer 1e18, settle) makes the seller pay 101000000000000000000, DEAD receives 1000000000000000000, and the manager's BTAX balance rises by 100000000000000000000 while the pool received only 99e18: 1 BTAX is stranded unaccounted. Without the top-up the unlock reverts with CurrencyNotSettled.","severity":"low","snippet":"if (fee != 0) poolManager.take(Currency.wrap(launchedToken), DEAD, fee);","title":"Burn transfer leaves the manager between a caller's sync and settle: a router that follows the README's pre-settlement advice with sync before swap is under-credited by the fee and the difference is s"},{"citation":"resolved","description":"Access-control trace of initialization. beforeInitialize is correctly restricted to the PoolManager and returns the right selector, but it ignores `sender` and validates nothing in the key except key.hooks, so any account may initialize further pools on this hook with any fee, tick spacing and price. That is by design ('no owner') and harmless for static fees. The one parameter the hook can never serve is fee = 0x800000 (dynamic): only the hook may call updateDynamicLPFee and it has no such path, and beforeSwap returns override 0 without the override flag, so that pool's LP fee is 0 forever. No funds are at risk and the launch pool is unaffected; the cost is a dead-end BTAX pool that pays LPs nothing while looking like an official hooked pool. If unwanted, add `if (key.fee == 0x800000) revert` (LPFeeLibrary.isDynamicFee) in beforeInitialize; static tiers 500/3000/10000 stay accepted.","line":62,"path":"src/BurnTaxHook.sol","reproduction":"After the hook is deployed, from an arbitrary address (vm.prank(0xBEEF)): manager.initialize(PoolKey{currency0: ETH, currency1: BTAX, fee: 0x800000, tickSpacing: 60, hooks: hook}, 2^96). Expected for a hook with no fee logic: revert. Actual: succeeds; getSlot0(poolId).lpFee == 0 and no call path can ever change it.","severity":"info","snippet":"if (address(key.hooks) != address(this)) revert WrongHook();","title":"beforeInitialize accepts the dynamic-fee flag: anyone can open a BTAX pool on this hook whose LP fee is permanently 0"}],"hash":"cc0767348f8f64bfd2aee57bacaa3454e3dd04738a173316217dc4386195387d","nodeId":"6f0a6057-ccc8-4138-a43d-fb93f4bb3c14","outcome":"completed","summary":"The review is written to `.imd-findings.json` in the repository root: three findings (two low, one info) and nine coverage rows. No tracked file was changed, and the scratch tests I used were deleted.\n\n**Verdict for the assigned area:** the permission model holds. I found no critical or high defect, so no finding carries a `proof` test.\n\n## Findings\n\n1. **Low — sells revert once the seeded BTAX is bought out** (`src/BurnTaxHook.sol:116`). On a sell, the burn transfer is paid from whatever BTAX the PoolManager already holds, because the seller has not settled yet.\n   - **Reproduction:** token-only seed of 1e22 liquidity in [-120, -60], then a 100 ETH buy that empties the range leaves the manager with 1 wei of BTAX. A 1 BTAX exact-input sell and a 0.001 ETH exact-output sell then both revert with `ERC20InsufficientBalance(manager, 1, 1e16)`.\n   - **Recovery:** a 99-wei sell works, and after anyone transfers 0.01 BTAX to the manager the 1 BTAX sell works.\n   - **Already documented:** the README states this limit and `test/FreshManager.t.sol:62` asserts the revert. I report it because the README's remedy (router pre-settles before the swap) is, as far as I know, not what the stock v4 routers do; I could not check them here.\n\n2. **Low — a router that syncs BTAX before the swap is under-credited by the fee** (`src/BurnTaxHook.sol:116`). The hook's transfer to the dead address reduces the manager's balance between the router's `sync` and `settle`.\n   - **Reproduction:** with the order sync → transfer 100 BTAX → swap → settle, the router is left owing 1 BTAX. If it tops up, the seller pays 101 BTAX, 1 is burned, and 1 stays in the manager credited to nobody.\n   - **Not documented:** the README advises pre-settlement but does not say the sync/settle pair must close before the swap.\n\n3. **Info — `beforeInitialize` accepts the dynamic-fee flag** (`src/BurnTaxHook.sol:62`). Any address can open a BTAX pool on this hook with fee `0x800000`; I confirmed its LP fee reads 0, and the hook has no way to change it. No funds are at risk and the launch pool is unaffected.\n\n## Coverage\n\n- **`BurnTaxHook.afterSwap`**: `finding` (ref 1). The manager-only guard and the pool-key check hold, and deltas net to zero in all four modes and both currency orderings; the defects are the two above.\n- **`BurnTaxToken.approve`, `transfer`, `transferFrom`**: `holds`. Inherited from the vendored OpenZeppelin v5.2.0 ERC20 with no overrides; the constructor is the only mint.\n- **Access Control:** every callback is manager-only; there are no roles, setters, storage, proxy or receive/fallback; the constructor validates the address flags (`0x20cc`).\n- **Asymmetry:** I compared buy/sell, exact-in/exact-out, specified/unspecified, both currency orderings, and `beforeSwap` against `afterSwap`. The burn is 1% of the gross BTAX leg in every mode, differing by at most 1 wei.\n- **Trust Gap:** there is no privileged actor. A third-party pool pairing BTAX with any token cannot make the hook burn manager-held BTAX for free.\n\n## Verification and limits\n\n- The existing suite passes (60 tests). All three reproductions were run as scratch Foundry tests against a real PoolManager, using the repo's own fixture and router.\n- I did not test against the real v4-periphery or Universal Router (not vendored), and ran no fork rehearsal.\n- I did not report `TAX_BPS` (`src/BurnTaxHook.sol:24`): it is never read and the math hardcodes 100 and 99, but no input makes it fail.\n- Open item, not a finding: the hook's second constructor argument is the token address, and nothing I was given says how a launch manifest refers to a token deployed in the same transaction.\n- Outside my area I looked only at the fee funding path; rounding economics and `script/MineHook.s.sol` were not audited.","treeHash":null,"usage":{"cachedInputTokens":1001453,"inputTokens":22,"model":"claude-fable-5-1","outputTokens":38128,"runtime":"claude","turns":14,"wallClockMs":441496}},{"artifacts":[],"attempt":1,"bundleHash":"130a192ee29a2d9f6959735eb1b49514fbb4cbdd6ed5b1d79c6ad9ca1bdabe45","device":"0256823ae36e7900","findings":[],"hash":"e11c9143a40373415adb171f71faceadd7d4cd0e9df46eb10486fe7497433af8","nodeId":"0e2f943e-3495-484f-b0f7-332cb18cab2c","outcome":"completed","summary":"Created [launch.json](/home/imd-worker/.identitymd/work/81c6d9d5-265a-4fb0-a46f-116edcf3ef33/0e2f943e-3495-484f-b0f7-332cb18cab2c/launch.json) matching the contracts, constructor order and permissions, with pool settings and documented limits.\n\nValidation passed against the supplied schema. `forge build` succeeded; `forge test` passed all 59 tests. Only `launch.json` changed outside permitted scratch output.","treeHash":"6a69a6024a0a1bec5cbc943a0f3c6c2c2d91205e","usage":{"cachedInputTokens":249856,"inputTokens":45091,"model":"gpt-6-astra","outputTokens":3937,"runtime":"codex","turns":3,"wallClockMs":147386}}],"verification":[{"checks":[{"durationMs":2942,"exitCode":0,"name":"build","output":"Compiling 83 files with Solc 0.8.26\nSolc 0.8.26 finished in 2.78s\nCompiler run successful!\n","passed":true},{"durationMs":981,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 5 tests for test/Token.t.sol:TokenTest\n[PASS] testFuzz_transferConservesSupply(uint256) (runs: 256, μ: 91975, ~: 91960)\nLogs:\n  Bound result 935718633020524775999794\n\n[PASS] test_allowanceAndTransferFrom() (gas: 164131)\n[PASS] test_invalidTransfersRevert() (gas: 58795)\n[PASS] test_metadataAndFixedSupply() (gas: 52740)\n[PASS] test_noMintAdminOrUpgradeEvenForDeployer() (gas: 397442)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 3.87ms (4.34ms CPU time)\n\nRan 2 tests for test/Deployment.t.sol:DeploymentTest\n[PASS] test_exhaustedSearchReverts() (gas: 1108287)\n[PASS] test_minedAddressDeploysActualCreationCode() (gas: 12163472)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 13.52ms (13.27ms CPU time)\n\nRan 5 tests for test/FreshManager.t.sol:FreshManagerTest\n[PASS] test_firstBuyExactInputOnTokenOnlyFreshManager() (gas: 20497507)\n[PASS] test_firstBuyExactOutputOnTokenOnlyFreshManager() (gas: 20485305)\n[PASS] test_sellExactInputIntoQuoteOnlyPoolWithPrefunding() (gas: 20495809)\n[PASS] test_sellExactOutputIntoQuoteOnlyPoolWithPrefunding() (gas: 20518677)\n[PASS] test_sellWithoutReservesOrPrefundingRevertsAtomically() (gas: 20481137)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 54.10ms (114.46ms CPU time)\n\nRan 23 tests for test/Hook.t.sol:HookToken1Test\n[PASS] testFuzz_allFourModes(uint96,bool,bool) (runs: 256, μ: 571502, ~: 578776)\nLogs:\n  Bound result 7050\n\n[PASS] test_allEnabledCallbacksRejectUnauthorizedCallers() (gas: 106998)\n[PASS] test_allLaunchFeeTiersAcceptedAndUnchanged() (gas: 3533620)\n[PASS] test_buyExactInput() (gas: 576351)\n[PASS] test_buyExactOutput() (gas: 575926)\n[PASS] test_constructorRejectsZeroParameters() (gas: 6109)\n[PASS] test_failedInputSettlementRollsBackBurn() (gas: 321274)\n[PASS] test_initializationBeforeCodeDeploymentFails() (gas: 40565)\n[PASS] test_largeSpecifiedAmountsRejectBeforeNegationOrNarrowing() (gas: 162146)\n[PASS] test_liquidityCanBeRemovedWithoutTax() (gas: 241240)\n[PASS] test_noAdministrativeSelectors() (gas: 121760)\n[PASS] test_permissionsAndInitialization() (gas: 61379)\n[PASS] test_poolWithoutTokenIsUnaffectedInAllModes() (gas: 2375542)\n[PASS] test_roundingBoundaries() (gas: 12266481)\n[PASS] test_runtimeHasNoProxyOrDestructionOpcodes() (gas: 2133082)\n[PASS] test_sellExactInput() (gas: 565025)\n[PASS] test_sellExactOutput() (gas: 564733)\n[PASS] test_slippageFailureRollsBackBurnAndPrice() (gas: 294754)\n[PASS] test_specifiedTokenPartialFillsRevertAtomically() (gas: 508293)\n[PASS] test_unspecifiedTokenPartialFillsTaxOnlyExecutedAmount() (gas: 899427)\n[PASS] test_wrongDeploymentFlagsRejected() (gas: 8167)\n[PASS] test_wrongKeyRejected() (gas: 80121)\n[PASS] test_zeroSwapRevertsWithoutBurn() (gas: 63863)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 62.30ms (80.13ms CPU time)\n\nRan 23 tests for test/Hook.t.sol:HookToken0Test\n[PASS] testFuzz_allFourModes(uint96,bool,bool) (runs: 256, μ: 569716, ~: 568733)\nLogs:\n  Bound result 6934\n\n[PASS] test_allEnabledCallbacksRejectUnauthorizedCallers() (gas: 107189)\n[PASS] test_allLaunchFeeTiersAcceptedAndUnchanged() (gas: 3524146)\n[PASS] test_buyExactInput() (gas: 563000)\n[PASS] test_buyExactOutput() (gas: 565185)\n[PASS] test_constructorRejectsZeroParameters() (gas: 6109)\n[PASS] test_failedInputSettlementRollsBackBurn() (gas: 308670)\n[PASS] test_initializationBeforeCodeDeploymentFails() (gas: 40565)\n[PASS] test_largeSpecifiedAmountsRejectBeforeNegationOrNarrowing() (gas: 161713)\n[PASS] test_liquidityCanBeRemovedWithoutTax() (gas: 241240)\n[PASS] test_noAdministrativeSelectors() (gas: 121760)\n[PASS] test_permissionsAndInitialization() (gas: 61379)\n[PASS] test_poolWithoutTokenIsUnaffectedInAllModes() (gas: 2363305)\n[PASS] test_roundingBoundaries() (gas: 12192835)\n[PASS] test_runtimeHasNoProxyOrDestructionOpcodes() (gas: 2133082)\n[PASS] test_sellExactInput() (gas: 577353)\n[PASS] test_sellExactOutput() (gas: 574451)\n[PASS] test_slippageFailureRollsBackBurnAndPrice() (gas: 287600)\n[PASS] test_specifiedTokenPartialFillsRevertAtomically() (gas: 507583)\n[PASS] test_unspecifiedTokenPartialFillsTaxOnlyExecutedAmount() (gas: 898853)\n[PASS] test_wrongDeploymentFlagsRejected() (gas: 8167)\n[PASS] test_wrongKeyRejected() (gas: 80312)\n[PASS] test_zeroSwapRevertsWithoutBurn() (gas: 64054)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 62.37ms (74.32ms CPU time)\n\nRan 1 test for test/Invariant.t.sol:BurnTaxInvariantTest\n[PASS]\nBurnTaxInvariantTest invariants:\n[PASS] invariant_noUnsettledDeltasOrClaims\n[PASS] invariant_supplyBalancesAndBurnConserved\n BurnTaxInvariantTest invariants (runs: 64, calls: 2048, reverts: 0)\n\n╭-------------+----------+-------+---------+----------╮\n| Contract    | Selector | Calls | Reverts | Discards |\n+=====================================================+\n| SwapHandler | trade    | 2048  | 0       | 0        |\n╰-------------+----------+-------+---------+----------╯\n\nLogs:\n  Bound result 8175\n  Bound result 1957\n  Bound result 989\n  Bound result 19349\n  Bound result 3531\n  Bound result 36810557425610055037\n  Bound result 84918268359212997903\n  Bound result 1680565875\n  Bound result 18418715144056625615\n  Bound result 1921\n  Bound result 4294967296\n  Bound result 164\n  Bound result 99999999999999999914\n  Bound result 11998\n  Bound result 1260\n  Bound result 81445911953521282211\n  Bound result 40616123987970091405\n  Bound result 3731\n  Bound result 18002\n  Bound result 10488\n  Bound result 9450193826\n  Bound result 6657\n  Bound result 4920180096567281578\n  Bound result 2031\n  Bound result 15779\n  Bound result 7434\n  Bound result 6021758274339415431\n  Bound result 5637\n  Bound result 14916441868785669975\n  Bound result 202\n  Bound result 10342\n  Bound result 10010\n  Bound result 1259352356\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 859.44ms (810.29ms CPU time)\n\nRan 6 test suites in 860.94ms (1.06s CPU time): 59 tests passed, 0 failed, 0 skipped (59 total tests)\n","passed":true},{"durationMs":49,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"BurnTaxHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"BurnTaxToken.approve(address,uint256)\",\"BurnTaxToken.transfer(address,uint256)\",\"BurnTaxToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":3,\"DEPENDENCIES.md\":12,\"LICENSE\":23,\"README.md\":80,\"foundry.toml\":24,\"remappings.txt\":4,\"script/MineHook.s.sol\":30,\"src/BurnTaxHook.sol\":143,\"src/BurnTaxToken.sol\":11,\"src/HookFlags.sol\":31,\"test/Deployment.t.sol\":30,\"test/FreshManager.t.sol\":97,\"test/Hook.t.sol\":347,\"test/Invariant.t.sol\":95,\"test/Token.t.sol\":71,\"test/helpers/HookFixture.sol\":85,\"test/helpers/PoolRouter.sol\":112,\"test/mocks/MockERC20.sol\":10},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":1106,"exitCode":0,"name":"slither","output":"slither: no results at low impact or above","passed":true},{"durationMs":409,"exitCode":0,"name":"aderyn","output":"[low] internal-function-used-once at src/HookFlags.sol:24: Internal Function Used Only Once\n[low] large-numeric-literal at src/BurnTaxToken.sol:9: Large Numeric Literal\n[low] literal-instead-of-constant at src/BurnTaxHook.sol:110: Literal Instead of Constant (4 places)","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"0a0b6414c4050554c31f14aaa13e9f2cf77b49c072ec3a045deec881623ebaef","verifiedTreeHash":"8986861bbb987d4b6ff8466c1662c2793c716f08","verifierVersion":"0.1.0+61e9b7ca"},{"checks":[{"durationMs":10078,"exitCode":0,"name":"build","output":"Compiling 87 files with Solc 0.8.26\nSolc 0.8.26 finished in 9.71s\nCompiler run successful!\n","passed":true},{"durationMs":15078,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 8 tests for test/Token.t.sol:TokenTest\n[PASS] testFuzz_transferConservesSupply(uint256) (runs: 256, μ: 92143, ~: 92079)\nLogs:\n  Bound result 139212464137085123895943556\n\n[PASS] test_allowanceAndTransferFrom() (gas: 164259)\n[PASS] test_failedTransferFromRestoresAllowanceAndSupply() (gas: 181229)\n[PASS] test_fullSupplyTransferAndInfiniteAllowanceRoundTrip() (gas: 211550)\n[PASS] test_invalidTransfersRevert() (gas: 58942)\n[PASS] test_metadataAndFixedSupply() (gas: 52774)\n[PASS] test_noMintAdminOrUpgradeEvenForDeployer() (gas: 397476)\n[PASS] test_zeroAndSelfTransfersDoNotTaxAndDeadTransfersDoNotMintOrDestroySupply() (gas: 165525)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 8.89ms (12.72ms CPU time)\n\nRan 2 tests for test/Deployment.t.sol:DeploymentTest\n[PASS] test_exhaustedSearchReverts() (gas: 1108287)\n[PASS] test_minedAddressDeploysActualCreationCode() (gas: 12163472)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 30.00ms (29.96ms CPU time)\n\nRan 4 tests for test/FreshManager.t.sol:FreshManagerTest\n[PASS] test_firstBuyExactInputOnTokenOnlyFreshManager() (gas: 20497573)\n[PASS] test_firstBuyExactOutputOnTokenOnlyFreshManager() (gas: 20485283)\n[PASS] test_sellExactInputIntoQuoteOnlyPoolWithPrefunding() (gas: 20495787)\n[PASS] test_sellExactOutputIntoQuoteOnlyPoolWithPrefunding() (gas: 20518677)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 113.71ms (149.14ms CPU time)\n\nRan 23 tests for test/Hook.t.sol:HookToken0Test\n[PASS] testFuzz_allFourModes(uint96,bool,bool) (runs: 256, μ: 569270, ~: 568769)\nLogs:\n  Bound result 303904148630994903944\n\n[PASS] test_allEnabledCallbacksRejectUnauthorizedCallers() (gas: 107189)\n[PASS] test_allLaunchFeeTiersAcceptedAndUnchanged() (gas: 3524146)\n[PASS] test_buyExactInput() (gas: 563000)\n[PASS] test_buyExactOutput() (gas: 565185)\n[PASS] test_constructorRejectsZeroParameters() (gas: 6109)\n[PASS] test_failedInputSettlementRollsBackBurn() (gas: 308670)\n[PASS] test_initializationBeforeCodeDeploymentFails() (gas: 40565)\n[PASS] test_largeSpecifiedAmountsRejectBeforeNegationOrNarrowing() (gas: 161713)\n[PASS] test_liquidityCanBeRemovedWithoutTax() (gas: 241240)\n[PASS] test_noAdministrativeSelectors() (gas: 121760)\n[PASS] test_permissionsAndInitialization() (gas: 61379)\n[PASS] test_poolWithoutTokenIsUnaffectedInAllModes() (gas: 2363305)\n[PASS] test_roundingBoundaries() (gas: 12192835)\n[PASS] test_runtimeHasNoProxyOrDestructionOpcodes() (gas: 2133082)\n[PASS] test_sellExactInput() (gas: 577353)\n[PASS] test_sellExactOutput() (gas: 574451)\n[PASS] test_slippageFailureRollsBackBurnAndPrice() (gas: 287600)\n[PASS] test_specifiedTokenPartialFillsRevertAtomically() (gas: 507583)\n[PASS] test_unspecifiedTokenPartialFillsTaxOnlyExecutedAmount() (gas: 898853)\n[PASS] test_wrongDeploymentFlagsRejected() (gas: 8167)\n[PASS] test_wrongKeyRejected() (gas: 80312)\n[PASS] test_zeroSwapRevertsWithoutBurn() (gas: 64054)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 327.21ms (296.55ms CPU time)\n\nRan 23 tests for test/Hook.t.sol:HookToken1Test\n[PASS] testFuzz_allFourModes(uint96,bool,bool) (runs: 256, μ: 570161, ~: 569082)\nLogs:\n  Bound result 719845\n\n[PASS] test_allEnabledCallbacksRejectUnauthorizedCallers() (gas: 106998)\n[PASS] test_allLaunchFeeTiersAcceptedAndUnchanged() (gas: 3533620)\n[PASS] test_buyExactInput() (gas: 576351)\n[PASS] test_buyExactOutput() (gas: 575926)\n[PASS] test_constructorRejectsZeroParameters() (gas: 6109)\n[PASS] test_failedInputSettlementRollsBackBurn() (gas: 321274)\n[PASS] test_initializationBeforeCodeDeploymentFails() (gas: 40565)\n[PASS] test_largeSpecifiedAmountsRejectBeforeNegationOrNarrowing() (gas: 162146)\n[PASS] test_liquidityCanBeRemovedWithoutTax() (gas: 241240)\n[PASS] test_noAdministrativeSelectors() (gas: 121760)\n[PASS] test_permissionsAndInitialization() (gas: 61379)\n[PASS] test_poolWithoutTokenIsUnaffectedInAllModes() (gas: 2375542)\n[PASS] test_roundingBoundaries() (gas: 12266481)\n[PASS] test_runtimeHasNoProxyOrDestructionOpcodes() (gas: 2133082)\n[PASS] test_sellExactInput() (gas: 565025)\n[PASS] test_sellExactOutput() (gas: 564733)\n[PASS] test_slippageFailureRollsBackBurnAndPrice() (gas: 294754)\n[PASS] test_specifiedTokenPartialFillsRevertAtomically() (gas: 508293)\n[PASS] test_unspecifiedTokenPartialFillsTaxOnlyExecutedAmount() (gas: 899427)\n[PASS] test_wrongDeploymentFlagsRejected() (gas: 8167)\n[PASS] test_wrongKeyRejected() (gas: 80121)\n[PASS] test_zeroSwapRevertsWithoutBurn() (gas: 63863)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 459.87ms (158.93ms CPU time)\n\nRan 6 tests for test/AdversarialHook.t.sol:AdversarialToken0Test\n[PASS] testFuzz_multiplePoolsAndModesInOneUnlock(uint256,uint8) (runs: 1000, μ: 866343, ~: 822632)\nLogs:\n  Bound result 7\n  Bound result 37672564607171916721\n  Bound result 57645029337691441376\n  Bound result 96919298715292117561\n  Bound result 73317165042713195038\n  Bound result 18296869092328545982\n  Bound result 86219855422628874686\n  Bound result 6198756464228645114\n\n[PASS] testFuzz_repeatedLiquidityRoundTripsCannotCreateValue(uint256,uint8) (runs: 1000, μ: 1553035, ~: 1350968)\nLogs:\n  Bound result 99\n  Bound result 6\n\n[PASS] test_failedFinalSettlementRollsBackEntireBatch() (gas: 607120)\n[PASS] test_failedLastSwapRollsBackEarlierSwapsAndBurns() (gas: 574779)\n[PASS] test_invalidPriceLimitsDoNotBurnOrChangePool() (gas: 1979262)\n[PASS] test_protocolFeesAndLpWithdrawalMatchPlainPool() (gas: 1948166)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 710.29ms (1.34s CPU time)\n\nRan 6 tests for test/AdversarialHook.t.sol:AdversarialToken1Test\n[PASS] testFuzz_multiplePoolsAndModesInOneUnlock(uint256,uint8) (runs: 1000, μ: 876368, ~: 835044)\nLogs:\n  Bound result 6\n  Bound result 61587368532786721193\n  Bound result 3648830390681154155\n  Bound result 6363081587755817809\n  Bound result 54059466944381446595\n  Bound result 49058648209112802976\n  Bound result 11591383224810353942\n\n[PASS] testFuzz_repeatedLiquidityRoundTripsCannotCreateValue(uint256,uint8) (runs: 1000, μ: 1556905, ~: 1201612)\nLogs:\n  Bound result 24\n  Bound result 4\n\n[PASS] test_failedFinalSettlementRollsBackEntireBatch() (gas: 614041)\n[PASS] test_failedLastSwapRollsBackEarlierSwapsAndBurns() (gas: 575444)\n[PASS] test_invalidPriceLimitsDoNotBurnOrChangePool() (gas: 1980926)\n[PASS] test_protocolFeesAndLpWithdrawalMatchPlainPool() (gas: 1963504)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 710.55ms (1.09s CPU time)\n\nRan 1 test for test/Invariant.t.sol:BurnTaxInvariantTest\n[PASS]\nBurnTaxInvariantTest invariants:\n[PASS] invariant_noUnsettledDeltasOrClaims\n[PASS] invariant_supplyBalancesAndBurnConserved\n BurnTaxInvariantTest invariants (runs: 64, calls: 2048, reverts: 0)\n\n╭-------------+----------+-------+---------+----------╮\n| Contract    | Selector | Calls | Reverts | Discards |\n+=====================================================+\n| SwapHandler | trade    | 2048  | 0       | 0        |\n╰-------------+----------+-------+---------+----------╯\n\nLogs:\n  Bound result 2708\n  Bound result 5870\n  Bound result 48284139270526236043\n  Bound result 8676\n  Bound result 10417\n  Bound result 4076725132\n  Bound result 3112\n  Bound result 11587\n  Bound result 14264337671979831208\n  Bound result 3798\n  Bound result 1343\n  Bound result 1964\n  Bound result 14264337671979831209\n  Bound result 3881\n  Bound result 20076659648335367\n  Bound result 12264\n  Bound result 17697\n  Bound result 782532231378\n  Bound result 13639\n  Bound result 36814686534750090960\n  Bound result 99999999213391990780\n  Bound result 1994\n  Bound result 7685\n  Bound result 101\n  Bound result 2882\n  Bound result 1964\n  Bound result 353\n  Bound result 10144\n  Bound result 6345\n  Bound result 19714\n  Bound result 5236\n  Bound result 48284139270527217464\n  Bound result 16325\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.69s (1.62s CPU time)\n\nRan 2 tests for test/StatefulAccounting.t.sol:StatefulToken1Test\n[PASS] invariant_supplyBurnLiquidityAndSettlement() (runs: 256, calls: 16384, reverts: 0)\n\n╭-------------------+------------------------+-------+---------+----------╮\n| Contract          | Selector               | Calls | Reverts | Discards |\n+=========================================================================+\n| AccountingHandler | attemptPrivilegedCalls | 2004  | 0       | 0        |\n|-------------------+------------------------+-------+---------+----------|\n| AccountingHandler | changeLiquidity        | 2059  | 0       | 0        |\n|-------------------+------------------------+-------+---------+----------|\n| AccountingHandler | donateToHook           | 2051  | 0       | 0        |\n|-------------------+------------------------+-------+---------+----------|\n| AccountingHandler | dustTrade              | 2150  | 0       | 0        |\n|-------------------+------------------------+-------+---------+----------|\n| AccountingHandler | rejectUnapprovedSell   | 2033  | 0       | 0        |\n|-------------------+------------------------+-------+---------+----------|\n| AccountingHandler | roundTrip              | 2050  | 0       | 0        |\n|-------------------+------------------------+-------+---------+----------|\n| AccountingHandler | trade                  | 2008  | 0       | 0        |\n|-------------------+------------------------+-------+---------+----------|\n| AccountingHandler | transferBetweenActors  | 2029  | 0       | 0        |\n╰-------------------+------------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 5\n  Bound result 456\n  Bound result 7438\n  Bound result 12\n  Bound result 11\n  Bound result 999999000000000001\n  Bound result 173\n  Bound result 8644270\n  Bound result 10000000000000000\n  Bound result 500\n  Bound result 116\n  Bound result 7\n  Bound result 59971783762558826821\n  Bound result 659918\n  Bound result 99999999999999999999\n  Bound result 16880\n  Bound result 8\n  Bound result 244\n  Bound result 8396\n  Bound result 100000000000000000000\n  Bound result 2955\n  Bound result 99999999000000002139\n  Bound result 99999999000000000124\n  Bound result 16\n  Bound result 13\n  Bound result 1999999999998\n  Bound result 15494\n  Bound result 123\n  Bound result 2\n  Bound result 42\n  Bound result 18\n  Bound result 10416\n  Bound result 4373900512680\n  Bound result 191\n  Bound result 22946\n  Bound result 1024\n  Bound result 20447\n  Bound result 801981976\n  Bound result 4597\n  Bound result 73793763901894802702\n  Bound result 76790180897922185434\n  Bound result 59971783762558826821\n  Bound result 99999999000000014215\n  Bound result 930\n  Bound result 1\n  Bound result 16796\n  Bound result 10101010101010101\n  Bound result 2\n\n[PASS] test_handlerExercisesAllActionsAndClosesPositions() (gas: 8919941)\nLogs:\n  Bound result 100000000000000000000\n  Bound result 123\n  Bound result 456\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 100\n  Bound result 100\n  Bound result 1000000000000000000\n  Bound result 100000000000000000000\n  Bound result 100000000000000000000\n  Bound result 123\n  Bound result 456\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 100\n  Bound result 100\n  Bound result 1000000000000000000\n  Bound result 100000000000000000000\n  Bound result 100000000000000000000\n  Bound result 123\n  Bound result 456\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 100\n  Bound result 100\n  Bound result 1000000000000000000\n  Bound result 100000000000000000000\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 13.95s (13.94s CPU time)\n\nRan 2 tests for test/StatefulAccounting.t.sol:StatefulToken0Test\n[PASS] invariant_supplyBurnLiquidityAndSettlement() (runs: 256, calls: 16384, reverts: 0)\n\n╭-------------------+------------------------+-------+---------+----------╮\n| Contract          | Selector               | Calls | Reverts | Discards |\n+=========================================================================+\n| AccountingHandler | attemptPrivilegedCalls | 2004  | 0       | 0        |\n|-------------------+------------------------+-------+---------+----------|\n| AccountingHandler | changeLiquidity        | 2059  | 0       | 0        |\n|-------------------+------------------------+-------+---------+----------|\n| AccountingHandler | donateToHook           | 2051  | 0       | 0        |\n|-------------------+------------------------+-------+---------+----------|\n| AccountingHandler | dustTrade              | 2150  | 0       | 0        |\n|-------------------+------------------------+-------+---------+----------|\n| AccountingHandler | rejectUnapprovedSell   | 2033  | 0       | 0        |\n|-------------------+------------------------+-------+---------+----------|\n| AccountingHandler | roundTrip              | 2050  | 0       | 0        |\n|-------------------+------------------------+-------+---------+----------|\n| AccountingHandler | trade                  | 2008  | 0       | 0        |\n|-------------------+------------------------+-------+---------+----------|\n| AccountingHandler | transferBetweenActors  | 2029  | 0       | 0        |\n╰-------------------+------------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 5\n  Bound result 456\n  Bound result 7545\n  Bound result 12\n  Bound result 12566\n  Bound result 999999000000000001\n  Bound result 46\n  Bound result 8644270\n  Bound result 10000000000000000\n  Bound result 500\n  Bound result 80\n  Bound result 7\n  Bound result 59971783762558826821\n  Bound result 659918\n  Bound result 99999999999999999999\n  Bound result 3651388627\n  Bound result 8\n  Bound result 244\n  Bound result 15\n  Bound result 100000000000000000000\n  Bound result 3360414709\n  Bound result 99999999000000001505\n  Bound result 99999999000000000124\n  Bound result 16\n  Bound result 13\n  Bound result 1999999999998\n  Bound result 10488\n  Bound result 123\n  Bound result 2\n  Bound result 92\n  Bound result 23\n  Bound result 335552787\n  Bound result 4373900512680\n  Bound result 206\n  Bound result 30602\n  Bound result 1024\n  Bound result 16796\n  Bound result 985\n  Bound result 4917\n  Bound result 73793763901894802702\n  Bound result 76790180897922185434\n  Bound result 59971783762558826821\n  Bound result 99999999000000014545\n  Bound result 442\n  Bound result 1\n  Bound result 12526\n  Bound result 10101010101010101\n  Bound result 32\n\n[PASS] test_handlerExercisesAllActionsAndClosesPositions() (gas: 8868282)\nLogs:\n  Bound result 100000000000000000000\n  Bound result 123\n  Bound result 456\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 100\n  Bound result 100\n  Bound result 1000000000000000000\n  Bound result 100000000000000000000\n  Bound result 100000000000000000000\n  Bound result 123\n  Bound result 456\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 100\n  Bound result 100\n  Bound result 1000000000000000000\n  Bound result 100000000000000000000\n  Bound result 100000000000000000000\n  Bound result 123\n  Bound result 456\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 1000000000000000000\n  Bound result 99\n  Bound result 100\n  Bound result 100\n  Bound result 1000000000000000000\n  Bound result 100000000000000000000\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 14.88s (14.86s CPU time)\n\nRan 10 test suites in 14.88s (32.88s CPU time): 77 tests passed, 0 failed, 0 skipped (77 total tests)\n","passed":true},{"durationMs":133,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"BurnTaxHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"BurnTaxToken.approve(address,uint256)\",\"BurnTaxToken.transfer(address,uint256)\",\"BurnTaxToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":3,\"DEPENDENCIES.md\":12,\"LICENSE\":23,\"README.md\":80,\"foundry.toml\":24,\"remappings.txt\":4,\"script/MineHook.s.sol\":30,\"src/BurnTaxHook.sol\":143,\"src/BurnTaxToken.sol\":11,\"src/HookFlags.sol\":31,\"test/AdversarialHook.t.sol\":254,\"test/Deployment.t.sol\":30,\"test/FreshManager.t.sol\":88,\"test/Hook.t.sol\":347,\"test/Invariant.t.sol\":95,\"test/README.md\":110,\"test/StatefulAccounting.t.sol\":323,\"test/Token.t.sol\":113,\"test/helpers/BatchRouter.sol\":58,\"test/helpers/BurnAssertions.sol\":85,\"test/helpers/HookFixture.sol\":85,\"test/helpers/PoolRouter.sol\":112,\"test/mocks/MockERC20.sol\":10},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"23f2cef2d7085cee6e358886238dda446009952ca14143b8116483c672019f07","verifiedTreeHash":"e8ecd54cbdaf084cb80d61dae8893453ec9c3ebc","verifierVersion":"0.1.0+61e9b7ca"},{"checks":[{"durationMs":3159,"exitCode":0,"name":"build","output":"Compiling 84 files with Solc 0.8.26\nSolc 0.8.26 finished in 3.01s\nCompiler run successful!\n","passed":true},{"durationMs":826,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 5 tests for test/Token.t.sol:TokenTest\n[PASS] testFuzz_transferConservesSupply(uint256) (runs: 256, μ: 92111, ~: 91984)\nLogs:\n  Bound result 528636\n\n[PASS] test_allowanceAndTransferFrom() (gas: 164131)\n[PASS] test_invalidTransfersRevert() (gas: 58795)\n[PASS] test_metadataAndFixedSupply() (gas: 52740)\n[PASS] test_noMintAdminOrUpgradeEvenForDeployer() (gas: 397442)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 5.61ms (6.01ms CPU time)\n\nRan 1 test for test/Settlement.t.sol:SettlementToken0Test\n[PASS] test_openTokenSyncAcrossSellPreservesFullSettlement() (gas: 971324)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 12.29ms (274.92µs CPU time)\n\nRan 1 test for test/Settlement.t.sol:SettlementToken1Test\n[PASS] test_openTokenSyncAcrossSellPreservesFullSettlement() (gas: 965057)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 14.94ms (279.38µs CPU time)\n\nRan 2 tests for test/Deployment.t.sol:DeploymentTest\n[PASS] test_exhaustedSearchReverts() (gas: 1266064)\n[PASS] test_minedAddressDeploysActualCreationCode() (gas: 15267060)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 18.23ms (17.96ms CPU time)\n\nRan 26 tests for test/Hook.t.sol:HookToken1Test\n[PASS] testFuzz_allFourModes(uint96,bool,bool) (runs: 256, μ: 573332, ~: 571337)\nLogs:\n  Bound result 11210\n\n[PASS] test_allEnabledCallbacksRejectUnauthorizedCallers() (gas: 107020)\n[PASS] test_allLaunchFeeTiersAcceptedAndUnchanged() (gas: 3542674)\n[PASS] test_buyExactInput() (gas: 578282)\n[PASS] test_buyExactOutput() (gas: 577857)\n[PASS] test_constructorRejectsZeroParameters() (gas: 6131)\n[PASS] test_dynamicPoolWithoutTokenRemainsUnaffected() (gas: 1213398)\n[PASS] test_dynamicTokenPoolRejectedBeforeInitialization() (gas: 58706)\n[PASS] test_failedInputSettlementRollsBackBurn() (gas: 323183)\n[PASS] test_initializationBeforeCodeDeploymentFails() (gas: 40478)\n[PASS] test_largeSpecifiedAmountsRejectBeforeNegationOrNarrowing() (gas: 162168)\n[PASS] test_liquidityCanBeRemovedWithoutTax() (gas: 241262)\n[PASS] test_noAdministrativeSelectors() (gas: 121760)\n[PASS] test_otherStaticFeeStillAcceptedAndUnchanged() (gas: 1218635)\n[PASS] test_permissionsAndInitialization() (gas: 61401)\n[PASS] test_poolWithoutTokenIsUnaffectedInAllModes() (gas: 2376076)\n[PASS] test_roundingBoundaries() (gas: 12291320)\n[PASS] test_runtimeHasNoProxyOrDestructionOpcodes() (gas: 2407248)\n[PASS] test_sellExactInput() (gas: 566934)\n[PASS] test_sellExactOutput() (gas: 566664)\n[PASS] test_slippageFailureRollsBackBurnAndPrice() (gas: 296663)\n[PASS] test_specifiedTokenPartialFillsRevertAtomically() (gas: 508293)\n[PASS] test_unspecifiedTokenPartialFillsTaxOnlyExecutedAmount() (gas: 903267)\n[PASS] test_wrongDeploymentFlagsRejected() (gas: 8189)\n[PASS] test_wrongKeyRejected() (gas: 80143)\n[PASS] test_zeroSwapRevertsWithoutBurn() (gas: 63885)\nSuite result: ok. 26 passed; 0 failed; 0 skipped; finished in 40.60ms (70.63ms CPU time)\n\nRan 26 tests for test/Hook.t.sol:HookToken0Test\n[PASS] testFuzz_allFourModes(uint96,bool,bool) (runs: 256, μ: 572239, ~: 570664)\nLogs:\n  Bound result 124052770376787\n\n[PASS] test_allEnabledCallbacksRejectUnauthorizedCallers() (gas: 107211)\n[PASS] test_allLaunchFeeTiersAcceptedAndUnchanged() (gas: 3532784)\n[PASS] test_buyExactInput() (gas: 564931)\n[PASS] test_buyExactOutput() (gas: 567116)\n[PASS] test_constructorRejectsZeroParameters() (gas: 6131)\n[PASS] test_dynamicPoolWithoutTokenRemainsUnaffected() (gas: 1206655)\n[PASS] test_dynamicTokenPoolRejectedBeforeInitialization() (gas: 58498)\n[PASS] test_failedInputSettlementRollsBackBurn() (gas: 310579)\n[PASS] test_initializationBeforeCodeDeploymentFails() (gas: 40478)\n[PASS] test_largeSpecifiedAmountsRejectBeforeNegationOrNarrowing() (gas: 161735)\n[PASS] test_liquidityCanBeRemovedWithoutTax() (gas: 241262)\n[PASS] test_noAdministrativeSelectors() (gas: 121760)\n[PASS] test_otherStaticFeeStillAcceptedAndUnchanged() (gas: 1231369)\n[PASS] test_permissionsAndInitialization() (gas: 61401)\n[PASS] test_poolWithoutTokenIsUnaffectedInAllModes() (gas: 2363839)\n[PASS] test_roundingBoundaries() (gas: 12217674)\n[PASS] test_runtimeHasNoProxyOrDestructionOpcodes() (gas: 2407248)\n[PASS] test_sellExactInput() (gas: 579262)\n[PASS] test_sellExactOutput() (gas: 576382)\n[PASS] test_slippageFailureRollsBackBurnAndPrice() (gas: 289509)\n[PASS] test_specifiedTokenPartialFillsRevertAtomically() (gas: 507583)\n[PASS] test_unspecifiedTokenPartialFillsTaxOnlyExecutedAmount() (gas: 902693)\n[PASS] test_wrongDeploymentFlagsRejected() (gas: 8189)\n[PASS] test_wrongKeyRejected() (gas: 80334)\n[PASS] test_zeroSwapRevertsWithoutBurn() (gas: 64076)\nSuite result: ok. 26 passed; 0 failed; 0 skipped; finished in 42.55ms (69.71ms CPU time)\n\nRan 13 tests for test/FreshManager.t.sol:FreshManagerTest\n[PASS] test_balanceEqualToFeeTransfersDirectly() (gas: 11627314)\n[PASS] test_balanceJustBelowFeeCommitsClaim() (gas: 11627183)\n[PASS] test_failedSettlementRollsBackClaimBurnAndPrice() (gas: 11533366)\n[PASS] test_firstBuyExactInputOnTokenOnlyFreshManager() (gas: 11379379)\n[PASS] test_firstBuyExactOutputOnTokenOnlyFreshManager() (gas: 11367180)\n[PASS] test_neitherDeployerNorHookCanTransferDeadClaims() (gas: 11729719)\n[PASS] test_sellExactInputAfterBuyingOutLaunchRange() (gas: 12937997)\n[PASS] test_sellExactInputIntoQuoteOnlyPoolWithPrefunding() (gas: 11377661)\n[PASS] test_sellExactInputWithoutReservesOrPrefundingCommitsBurn() (gas: 11591879)\n[PASS] test_sellExactOutputAfterBuyingOutLaunchRange() (gas: 12927750)\n[PASS] test_sellExactOutputIntoQuoteOnlyPoolWithPrefunding() (gas: 11400549)\n[PASS] test_sellExactOutputWithoutReservesOrPrefundingCommitsBurn() (gas: 11590733)\n[PASS] test_slippageFailureRollsBackClaimBurnAndPrice() (gas: 11491793)\nSuite result: ok. 13 passed; 0 failed; 0 skipped; finished in 42.54ms (140.09ms CPU time)\n\nRan 1 test for test/Invariant.t.sol:BurnTaxInvariantTest\n[PASS]\nBurnTaxInvariantTest invariants:\n[PASS] invariant_noUnsettledDeltasOrClaims\n[PASS] invariant_supplyBalancesAndBurnConserved\n BurnTaxInvariantTest invariants (runs: 64, calls: 2048, reverts: 0)\n\n╭-------------+----------+-------+---------+----------╮\n| Contract    | Selector | Calls | Reverts | Discards |\n+=====================================================+\n| SwapHandler | trade    | 2048  | 0       | 0        |\n╰-------------+----------+-------+---------+----------╯\n\nLogs:\n  Bound result 10143\n  Bound result 1720\n  Bound result 19395\n  Bound result 2248\n  Bound result 166541911940389\n  Bound result 1383\n  Bound result 3295\n  Bound result 4169656895\n  Bound result 262584999731517842\n  Bound result 17498\n  Bound result 3815\n  Bound result 16780\n  Bound result 3780\n  Bound result 994414698732\n  Bound result 58274205061245291883\n  Bound result 81321223873847086917\n  Bound result 6395\n  Bound result 94712288536150018334\n  Bound result 4927\n  Bound result 1126409556\n  Bound result 99999999999999999917\n  Bound result 6018053027107444773\n  Bound result 4312\n  Bound result 9935\n  Bound result 1335\n  Bound result 4206\n  Bound result 2251799813685249\n  Bound result 17078\n  Bound result 102\n  Bound result 2939\n  Bound result 3536\n  Bound result 889\n  Bound result 4194305\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 730.84ms (716.02ms CPU time)\n\nRan 8 test suites in 732.54ms (907.61ms CPU time): 75 tests passed, 0 failed, 0 skipped (75 total tests)\n","passed":true},{"durationMs":51,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"BurnTaxHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"BurnTaxToken.approve(address,uint256)\",\"BurnTaxToken.transfer(address,uint256)\",\"BurnTaxToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":3,\"DEPENDENCIES.md\":12,\"LICENSE\":23,\"README.md\":81,\"foundry.toml\":24,\"remappings.txt\":4,\"script/MineHook.s.sol\":30,\"src/BurnTaxHook.sol\":159,\"src/BurnTaxToken.sol\":11,\"src/HookFlags.sol\":31,\"test/Deployment.t.sol\":30,\"test/FreshManager.t.sol\":225,\"test/Hook.t.sol\":394,\"test/Invariant.t.sol\":95,\"test/Settlement.t.sol\":77,\"test/Token.t.sol\":71,\"test/helpers/HookFixture.sol\":85,\"test/helpers/PoolRouter.sol\":112,\"test/mocks/MockERC20.sol\":10},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":878,"exitCode":0,"name":"slither","output":"slither: no results at low impact or above","passed":true},{"durationMs":317,"exitCode":0,"name":"aderyn","output":"[low] internal-function-used-once at src/HookFlags.sol:24: Internal Function Used Only Once\n[low] large-numeric-literal at src/BurnTaxToken.sol:9: Large Numeric Literal\n[low] literal-instead-of-constant at src/BurnTaxHook.sol:115: Literal Instead of Constant (4 places)","passed":true},{"durationMs":1774,"exitCode":0,"name":"proof 5a277e0491ed","output":"Compiling 77 files with Solc 0.8.26\nSolc 0.8.26 finished in 1.24s\nCompiler run successful!\n\nRan 2 tests for test/imd-proof-b3bf5921/Proof_5a277e0491ed.t.sol:JudgeSellFundingTest\n[PASS] test_exactInputSellAfterBuyoutThroughOrdinaryRouter() (gas: 1181623)\n[PASS] test_exactOutputSellAfterBuyoutThroughOrdinaryRouter() (gas: 1171844)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 8.34ms (3.08ms CPU time)\n\nRan 1 test suite in 9.06ms (8.34ms CPU time): 2 tests passed, 0 failed, 0 skipped (2 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"7a19e11ffafef91a4e246dfe734da80b6e4c4eef225c9ff7fc1f624694d78da1","verifiedTreeHash":"f8528325ae64daa3b4095f57046f6cdf89257455","verifierVersion":"0.1.0+61e9b7ca"},{"checks":[{"durationMs":2871,"exitCode":0,"name":"build","output":"Compiling 83 files with Solc 0.8.26\nSolc 0.8.26 finished in 2.73s\nCompiler run successful!\n","passed":true},{"durationMs":802,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 5 tests for test/Token.t.sol:TokenTest\n[PASS] testFuzz_transferConservesSupply(uint256) (runs: 256, μ: 92245, ~: 91984)\nLogs:\n  Bound result 1470\n\n[PASS] test_allowanceAndTransferFrom() (gas: 164131)\n[PASS] test_invalidTransfersRevert() (gas: 58795)\n[PASS] test_metadataAndFixedSupply() (gas: 52740)\n[PASS] test_noMintAdminOrUpgradeEvenForDeployer() (gas: 397442)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 3.59ms (4.06ms CPU time)\n\nRan 2 tests for test/Deployment.t.sol:DeploymentTest\n[PASS] test_exhaustedSearchReverts() (gas: 1108287)\n[PASS] test_minedAddressDeploysActualCreationCode() (gas: 12163472)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 10.43ms (10.23ms CPU time)\n\nRan 5 tests for test/FreshManager.t.sol:FreshManagerTest\n[PASS] test_firstBuyExactInputOnTokenOnlyFreshManager() (gas: 20497507)\n[PASS] test_firstBuyExactOutputOnTokenOnlyFreshManager() (gas: 20485305)\n[PASS] test_sellExactInputIntoQuoteOnlyPoolWithPrefunding() (gas: 20495809)\n[PASS] test_sellExactOutputIntoQuoteOnlyPoolWithPrefunding() (gas: 20518677)\n[PASS] test_sellWithoutReservesOrPrefundingRevertsAtomically() (gas: 20481137)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 21.32ms (86.34ms CPU time)\n\nRan 23 tests for test/Hook.t.sol:HookToken1Test\n[PASS] testFuzz_allFourModes(uint96,bool,bool) (runs: 256, μ: 571188, ~: 569405)\nLogs:\n  Bound result 910072142358663912956\n\n[PASS] test_allEnabledCallbacksRejectUnauthorizedCallers() (gas: 106998)\n[PASS] test_allLaunchFeeTiersAcceptedAndUnchanged() (gas: 3533620)\n[PASS] test_buyExactInput() (gas: 576351)\n[PASS] test_buyExactOutput() (gas: 575926)\n[PASS] test_constructorRejectsZeroParameters() (gas: 6109)\n[PASS] test_failedInputSettlementRollsBackBurn() (gas: 321274)\n[PASS] test_initializationBeforeCodeDeploymentFails() (gas: 40565)\n[PASS] test_largeSpecifiedAmountsRejectBeforeNegationOrNarrowing() (gas: 162146)\n[PASS] test_liquidityCanBeRemovedWithoutTax() (gas: 241240)\n[PASS] test_noAdministrativeSelectors() (gas: 121760)\n[PASS] test_permissionsAndInitialization() (gas: 61379)\n[PASS] test_poolWithoutTokenIsUnaffectedInAllModes() (gas: 2375542)\n[PASS] test_roundingBoundaries() (gas: 12266481)\n[PASS] test_runtimeHasNoProxyOrDestructionOpcodes() (gas: 2133082)\n[PASS] test_sellExactInput() (gas: 565025)\n[PASS] test_sellExactOutput() (gas: 564733)\n[PASS] test_slippageFailureRollsBackBurnAndPrice() (gas: 294754)\n[PASS] test_specifiedTokenPartialFillsRevertAtomically() (gas: 508293)\n[PASS] test_unspecifiedTokenPartialFillsTaxOnlyExecutedAmount() (gas: 899427)\n[PASS] test_wrongDeploymentFlagsRejected() (gas: 8167)\n[PASS] test_wrongKeyRejected() (gas: 80121)\n[PASS] test_zeroSwapRevertsWithoutBurn() (gas: 63863)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 56.15ms (72.54ms CPU time)\n\nRan 23 tests for test/Hook.t.sol:HookToken0Test\n[PASS] testFuzz_allFourModes(uint96,bool,bool) (runs: 256, μ: 570057, ~: 568779)\nLogs:\n  Bound result 400758354213270036235\n\n[PASS] test_allEnabledCallbacksRejectUnauthorizedCallers() (gas: 107189)\n[PASS] test_allLaunchFeeTiersAcceptedAndUnchanged() (gas: 3524146)\n[PASS] test_buyExactInput() (gas: 563000)\n[PASS] test_buyExactOutput() (gas: 565185)\n[PASS] test_constructorRejectsZeroParameters() (gas: 6109)\n[PASS] test_failedInputSettlementRollsBackBurn() (gas: 308670)\n[PASS] test_initializationBeforeCodeDeploymentFails() (gas: 40565)\n[PASS] test_largeSpecifiedAmountsRejectBeforeNegationOrNarrowing() (gas: 161713)\n[PASS] test_liquidityCanBeRemovedWithoutTax() (gas: 241240)\n[PASS] test_noAdministrativeSelectors() (gas: 121760)\n[PASS] test_permissionsAndInitialization() (gas: 61379)\n[PASS] test_poolWithoutTokenIsUnaffectedInAllModes() (gas: 2363305)\n[PASS] test_roundingBoundaries() (gas: 12192835)\n[PASS] test_runtimeHasNoProxyOrDestructionOpcodes() (gas: 2133082)\n[PASS] test_sellExactInput() (gas: 577353)\n[PASS] test_sellExactOutput() (gas: 574451)\n[PASS] test_slippageFailureRollsBackBurnAndPrice() (gas: 287600)\n[PASS] test_specifiedTokenPartialFillsRevertAtomically() (gas: 507583)\n[PASS] test_unspecifiedTokenPartialFillsTaxOnlyExecutedAmount() (gas: 898853)\n[PASS] test_wrongDeploymentFlagsRejected() (gas: 8167)\n[PASS] test_wrongKeyRejected() (gas: 80312)\n[PASS] test_zeroSwapRevertsWithoutBurn() (gas: 64054)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 56.14ms (74.39ms CPU time)\n\nRan 1 test for test/Invariant.t.sol:BurnTaxInvariantTest\n[PASS]\nBurnTaxInvariantTest invariants:\n[PASS] invariant_noUnsettledDeltasOrClaims\n[PASS] invariant_supplyBalancesAndBurnConserved\n BurnTaxInvariantTest invariants (runs: 64, calls: 2048, reverts: 0)\n\n╭-------------+----------+-------+---------+----------╮\n| Contract    | Selector | Calls | Reverts | Discards |\n+=====================================================+\n| SwapHandler | trade    | 2048  | 0       | 0        |\n╰-------------+----------+-------+---------+----------╯\n\nLogs:\n  Bound result 2058\n  Bound result 107046155915770185\n  Bound result 15812\n  Bound result 93124552543021505221\n  Bound result 8437\n  Bound result 691\n  Bound result 17484\n  Bound result 133496\n  Bound result 16354\n  Bound result 17483\n  Bound result 12128\n  Bound result 1264811663\n  Bound result 99999999999999999908\n  Bound result 941733320204099772\n  Bound result 411\n  Bound result 16822\n  Bound result 4014\n  Bound result 740\n  Bound result 331795588790\n  Bound result 1170413884\n  Bound result 8108\n  Bound result 4206\n  Bound result 2634\n  Bound result 7942\n  Bound result 2958\n  Bound result 1441454116401617824\n  Bound result 9173\n  Bound result 539\n  Bound result 3055\n  Bound result 17695\n  Bound result 99999999999999999909\n  Bound result 836553799609979\n  Bound result 51673831653840087199\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 707.22ms (682.31ms CPU time)\n\nRan 6 test suites in 708.88ms (854.85ms CPU time): 59 tests passed, 0 failed, 0 skipped (59 total tests)\n","passed":true},{"durationMs":62,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"BurnTaxHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"BurnTaxToken.approve(address,uint256)\",\"BurnTaxToken.transfer(address,uint256)\",\"BurnTaxToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":3,\"DEPENDENCIES.md\":12,\"LICENSE\":23,\"README.md\":80,\"foundry.toml\":24,\"launch.json\":30,\"remappings.txt\":4,\"script/MineHook.s.sol\":30,\"src/BurnTaxHook.sol\":143,\"src/BurnTaxToken.sol\":11,\"src/HookFlags.sol\":31,\"test/Deployment.t.sol\":30,\"test/FreshManager.t.sol\":97,\"test/Hook.t.sol\":347,\"test/Invariant.t.sol\":95,\"test/Token.t.sol\":71,\"test/helpers/HookFixture.sol\":85,\"test/helpers/PoolRouter.sol\":112,\"test/mocks/MockERC20.sol\":10},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"a053a07f0c1801edbc60d9fe4fb216343ab33565ff44378d3198e85f01a769b9","verifiedTreeHash":"463389cf227816c98d94fb6a0730299076fac3b5","verifierVersion":"0.1.0+61e9b7ca"},{"checks":[{"durationMs":6094,"exitCode":0,"name":"build","output":"Compiling 83 files with Solc 0.8.26\nSolc 0.8.26 finished in 5.66s\nCompiler run successful!\n","passed":true},{"durationMs":1585,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 5 tests for test/Token.t.sol:TokenTest\n[PASS] testFuzz_transferConservesSupply(uint256) (runs: 256, μ: 91624, ~: 91960)\nLogs:\n  Bound result 692359188926688198590099076\n\n[PASS] test_allowanceAndTransferFrom() (gas: 164131)\n[PASS] test_invalidTransfersRevert() (gas: 58795)\n[PASS] test_metadataAndFixedSupply() (gas: 52740)\n[PASS] test_noMintAdminOrUpgradeEvenForDeployer() (gas: 397442)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 17.02ms (15.59ms CPU time)\n\nRan 2 tests for test/Deployment.t.sol:DeploymentTest\n[PASS] test_exhaustedSearchReverts() (gas: 1108287)\n[PASS] test_minedAddressDeploysActualCreationCode() (gas: 12163472)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 35.13ms (35.67ms CPU time)\n\nRan 5 tests for test/FreshManager.t.sol:FreshManagerTest\n[PASS] test_firstBuyExactInputOnTokenOnlyFreshManager() (gas: 20497507)\n[PASS] test_firstBuyExactOutputOnTokenOnlyFreshManager() (gas: 20485305)\n[PASS] test_sellExactInputIntoQuoteOnlyPoolWithPrefunding() (gas: 20495809)\n[PASS] test_sellExactOutputIntoQuoteOnlyPoolWithPrefunding() (gas: 20518677)\n[PASS] test_sellWithoutReservesOrPrefundingRevertsAtomically() (gas: 20481137)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 109.29ms (206.58ms CPU time)\n\nRan 23 tests for test/Hook.t.sol:HookToken1Test\n[PASS] testFuzz_allFourModes(uint96,bool,bool) (runs: 256, μ: 571749, ~: 578776)\nLogs:\n  Bound result 503615005\n\n[PASS] test_allEnabledCallbacksRejectUnauthorizedCallers() (gas: 106998)\n[PASS] test_allLaunchFeeTiersAcceptedAndUnchanged() (gas: 3533620)\n[PASS] test_buyExactInput() (gas: 576351)\n[PASS] test_buyExactOutput() (gas: 575926)\n[PASS] test_constructorRejectsZeroParameters() (gas: 6109)\n[PASS] test_failedInputSettlementRollsBackBurn() (gas: 321274)\n[PASS] test_initializationBeforeCodeDeploymentFails() (gas: 40565)\n[PASS] test_largeSpecifiedAmountsRejectBeforeNegationOrNarrowing() (gas: 162146)\n[PASS] test_liquidityCanBeRemovedWithoutTax() (gas: 241240)\n[PASS] test_noAdministrativeSelectors() (gas: 121760)\n[PASS] test_permissionsAndInitialization() (gas: 61379)\n[PASS] test_poolWithoutTokenIsUnaffectedInAllModes() (gas: 2375542)\n[PASS] test_roundingBoundaries() (gas: 12266481)\n[PASS] test_runtimeHasNoProxyOrDestructionOpcodes() (gas: 2133082)\n[PASS] test_sellExactInput() (gas: 565025)\n[PASS] test_sellExactOutput() (gas: 564733)\n[PASS] test_slippageFailureRollsBackBurnAndPrice() (gas: 294754)\n[PASS] test_specifiedTokenPartialFillsRevertAtomically() (gas: 508293)\n[PASS] test_unspecifiedTokenPartialFillsTaxOnlyExecutedAmount() (gas: 899427)\n[PASS] test_wrongDeploymentFlagsRejected() (gas: 8167)\n[PASS] test_wrongKeyRejected() (gas: 80121)\n[PASS] test_zeroSwapRevertsWithoutBurn() (gas: 63863)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 109.38ms (166.34ms CPU time)\n\nRan 23 tests for test/Hook.t.sol:HookToken0Test\n[PASS] testFuzz_allFourModes(uint96,bool,bool) (runs: 256, μ: 570163, ~: 568733)\nLogs:\n  Bound result 9442\n\n[PASS] test_allEnabledCallbacksRejectUnauthorizedCallers() (gas: 107189)\n[PASS] test_allLaunchFeeTiersAcceptedAndUnchanged() (gas: 3524146)\n[PASS] test_buyExactInput() (gas: 563000)\n[PASS] test_buyExactOutput() (gas: 565185)\n[PASS] test_constructorRejectsZeroParameters() (gas: 6109)\n[PASS] test_failedInputSettlementRollsBackBurn() (gas: 308670)\n[PASS] test_initializationBeforeCodeDeploymentFails() (gas: 40565)\n[PASS] test_largeSpecifiedAmountsRejectBeforeNegationOrNarrowing() (gas: 161713)\n[PASS] test_liquidityCanBeRemovedWithoutTax() (gas: 241240)\n[PASS] test_noAdministrativeSelectors() (gas: 121760)\n[PASS] test_permissionsAndInitialization() (gas: 61379)\n[PASS] test_poolWithoutTokenIsUnaffectedInAllModes() (gas: 2363305)\n[PASS] test_roundingBoundaries() (gas: 12192835)\n[PASS] test_runtimeHasNoProxyOrDestructionOpcodes() (gas: 2133082)\n[PASS] test_sellExactInput() (gas: 577353)\n[PASS] test_sellExactOutput() (gas: 574451)\n[PASS] test_slippageFailureRollsBackBurnAndPrice() (gas: 287600)\n[PASS] test_specifiedTokenPartialFillsRevertAtomically() (gas: 507583)\n[PASS] test_unspecifiedTokenPartialFillsTaxOnlyExecutedAmount() (gas: 898853)\n[PASS] test_wrongDeploymentFlagsRejected() (gas: 8167)\n[PASS] test_wrongKeyRejected() (gas: 80312)\n[PASS] test_zeroSwapRevertsWithoutBurn() (gas: 64054)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 129.44ms (123.37ms CPU time)\n\nRan 1 test for test/Invariant.t.sol:BurnTaxInvariantTest\n[PASS]\nBurnTaxInvariantTest invariants:\n[PASS] invariant_noUnsettledDeltasOrClaims\n[PASS] invariant_supplyBalancesAndBurnConserved\n BurnTaxInvariantTest invariants (runs: 64, calls: 2048, reverts: 0)\n\n╭-------------+----------+-------+---------+----------╮\n| Contract    | Selector | Calls | Reverts | Discards |\n+=====================================================+\n| SwapHandler | trade    | 2048  | 0       | 0        |\n╰-------------+----------+-------+---------+----------╯\n\nLogs:\n  Bound result 1210\n  Bound result 3201\n  Bound result 99999999999999999925\n  Bound result 94945396868988051888\n  Bound result 101\n  Bound result 185441290\n  Bound result 15207891599686459579\n  Bound result 48284685\n  Bound result 1186\n  Bound result 10693\n  Bound result 3419\n  Bound result 8695\n  Bound result 1575\n  Bound result 8891\n  Bound result 53072121398316\n  Bound result 85759263543409626051\n  Bound result 299524277\n  Bound result 19682\n  Bound result 5096\n  Bound result 84597970450006428503\n  Bound result 12013\n  Bound result 78772063819602480476\n  Bound result 62624185262\n  Bound result 14506\n  Bound result 33400247872680034\n  Bound result 16804\n  Bound result 7381\n  Bound result 4075229234501\n  Bound result 72987346710677453618\n  Bound result 18646\n  Bound result 4090335565\n  Bound result 2536\n  Bound result 3599\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.38s (1.32s CPU time)\n\nRan 6 test suites in 1.39s (1.78s CPU time): 59 tests passed, 0 failed, 0 skipped (59 total tests)\n","passed":true},{"durationMs":107,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"BurnTaxHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"BurnTaxToken.approve(address,uint256)\",\"BurnTaxToken.transfer(address,uint256)\",\"BurnTaxToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":3,\"DEPENDENCIES.md\":12,\"LICENSE\":23,\"README.md\":80,\"foundry.toml\":24,\"launch.json\":27,\"remappings.txt\":4,\"script/MineHook.s.sol\":30,\"src/BurnTaxHook.sol\":143,\"src/BurnTaxToken.sol\":11,\"src/HookFlags.sol\":31,\"test/Deployment.t.sol\":30,\"test/FreshManager.t.sol\":97,\"test/Hook.t.sol\":347,\"test/Invariant.t.sol\":95,\"test/Token.t.sol\":71,\"test/helpers/HookFixture.sol\":85,\"test/helpers/PoolRouter.sol\":112,\"test/mocks/MockERC20.sol\":10},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"launch.json: constructor argument \"$token\" is neither an address nor an integer, and a launch manifest can express nothing else","evaluation":"checks","profile":"foundry","status":"rejected","submissionHash":"e11c9143a40373415adb171f71faceadd7d4cd0e9df46eb10486fe7497433af8","verifiedTreeHash":"6a69a6024a0a1bec5cbc943a0f3c6c2c2d91205e","verifierVersion":"0.1.0+61e9b7ca"}]}