{"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":"c57e9ddb-49a9-49d8-9516-9ebd6ec5bbc0","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"3058e30bf9b09d65a6c580b27d0c841ecba45d0ee416786262aeee43c6b42bb6","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"c26edc76dc7a76e09a42c3634054429c1679c6e247747d647a03f77e5b332d7e","skillId":"adversarial-review","tools":[]},"key":"adversarial_review","kind":"code","role":"review","skillHash":"c26edc76dc7a76e09a42c3634054429c1679c6e247747d647a03f77e5b332d7e","skillId":"adversarial-review","state":"accepted"},{"acceptedSubmissionHash":"5b1d91a3ec60b84a16b65f2562e830735deb3b9e309b27d6459c904d30ef24e5","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"fb6887b34514bcb194265fa403f0195c6a83eaef269da1e6189e1e9c4b372a7d","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"fb6887b34514bcb194265fa403f0195c6a83eaef269da1e6189e1e9c4b372a7d","skillId":"build-contract-project","state":"accepted"}],"objective":"Build AllowlistLiquidityHook, a simple, creative Uniswap v4 hook: a hook where only addresses in an allowlist fixed at construction may add liquidity to a pool, while anyone may swap; beforeAddLiquidity reverts for everyone else and beforeRemoveLiquidity is never restricted. Tests cover an allowed and a disallowed provider and that removal always works. Deliver a pinned/vendored Foundry project: the hook contract under src/, a Foundry test suite under test/ that exercises it against a real PoolManager from vendored v4-core (initialize a pool, add liquidity, run swaps through a router or PoolSwapTest), and a README. Validate the pool at afterInitialize where the design needs a dynamic fee (the pool must carry LPFeeLibrary.DYNAMIC_FEE_FLAG) and revert otherwise. Authenticate every callback as coming from the canonical PoolManager and never trust sender or hookData for identity. Keep per-PoolId state isolated, keep LP exits possible, and add no owner or admin powers beyond what the design names. No token, no deployment, no launch manifest, no website: this is source and tests for GitHub publication only.","parentJobId":null,"planHash":"84ed74771df499d310e2ba1763ad6a039fac3c95a2e7d6e8e1610281d578f25c","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"c57e9ddb-49a9-49d8-9516-9ebd6ec5bbc0","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/Identity-md/launch-72-build-allowlistliquidityhook-simple-crea"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"50971","feedbackHash":"0db4d81be8ad03edc8dfcd91d943880c5032f7eb2db8995db43275f66d8d4b9a","nodeKey":"adversarial_review","submissionHash":"3058e30bf9b09d65a6c580b27d0c841ecba45d0ee416786262aeee43c6b42bb6","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"50955","feedbackHash":"b92e184df2aab4fe6e44da0b88540dad9335429253d70991928471bf4695feb8","nodeKey":"adversarial_review","submissionHash":"6302c110bb89c680a5f45aef36c7cb80481158cfe47fc7aa685e74309b1dd0ec","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"50957","feedbackHash":"86c79e25ec61ed0849ef5c9fbeaf03540f31673100fe05652492f3ed3432fedd","nodeKey":"build_contract_project","submissionHash":"5b1d91a3ec60b84a16b65f2562e830735deb3b9e309b27d6459c904d30ef24e5","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"50985","feedbackHash":"af3a1a809ac2caaa6da453eb0cb79870f999ed9e911186c890beddcc4170624c","nodeKey":"build_contract_project","submissionHash":"8e1aa276b3b383a428d377b1e01a6735d6fdbb0319ebbb2ec1279d6d84632b37","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"145604b5cf22806ffac5bbfdb1012bc351d4242346bf2f00426757fd95c22ddc","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"35c52a5b502e847c","findings":[],"hash":"3058e30bf9b09d65a6c580b27d0c841ecba45d0ee416786262aeee43c6b42bb6","nodeId":"1bd49566-5096-4367-be89-c2b2feea8843","outcome":"completed","summary":"Wrote `{\"findings\":[]}` to `.imd-findings.json`.\n\nAll prior findings are resolved:\n- README exists and covers the requested topics.\n- Router identity limitation is documented; the outsider-deposit regression test passes.\n- Canonical PoolManager selection is documented as a deployment trust assumption.\n\nNo remaining defects substantiated.","treeHash":null,"usage":{"cachedInputTokens":179840,"inputTokens":32078,"model":null,"outputTokens":834,"runtime":"codex","turns":2,"wallClockMs":42361}},{"artifacts":[],"attempt":1,"bundleHash":"cf78082f62109d55a074954029f7f6647d3b853f7ec7aca7e9e94b1a4bc49cb5","device":"0256823ae36e7900","findings":[],"hash":"5b1d91a3ec60b84a16b65f2562e830735deb3b9e309b27d6459c904d30ef24e5","nodeId":"9a458373-ce28-46dd-bdd4-39cb6bc837a4","outcome":"completed","summary":"Implemented the revision:\n\n- Added [README.md](/home/imd-worker/.identitymd/work/c57e9ddb-49a9-49d8-9516-9ebd6ec5bbc0/9a458373-ce28-46dd-bdd4-39cb6bc837a4/README.md) covering identity semantics, dynamic fees, `0x1800` hook flags, deployment, and operational responsibilities.\n- Added a regression test proving outsiders can deposit through an allowlisted permissionless router.\n- Documented the PoolManager address as a deployment trust assumption.\n- Recorded all finding responses in `.imd-responses.json`.\n\nValidation passed:\n\n- `forge fmt --check`\n- `forge build --offline`\n- `forge test --offline` — 41 passed, 0 failed\n- JSON validation and `git diff --check` passed.","treeHash":"b5fad506afa5e97128a9185af59fc2bc2115e9cb","usage":{"cachedInputTokens":299392,"inputTokens":44218,"model":null,"outputTokens":3854,"runtime":"codex","turns":4,"wallClockMs":102032}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"3c7630b22a73c1fb","findings":[{"description":"The assignment requires a pinned Foundry project with the hook, a test suite and a README. The repository has no README of any kind. The hook's own NatSpec defers its main integrator warning to it: 'See the README for what this means for integrators: allowlisting a permissionless shared router allowlists the whole world through it.' That warning exists nowhere a reader of the published repo can find it.","line":38,"path":"src/AllowlistLiquidityHook.sol","reproduction":"Run `git ls-files | grep -i readme` at the repo root (outside lib/): no output. `ls README*` fails with 'No such file'. Expected: a README covering the design, the sender-vs-EOA caveat, the dynamic-fee requirement, address mining/deployment flags (AFTER_INITIALIZE | BEFORE_ADD_LIQUIDITY = 0x1800) and how to run the tests.","severity":"high","title":"README deliverable is missing"},{"description":"beforeAddLiquidity checks `_allowed[sender]`, where `sender` is whoever called PoolManager.modifyLiquidity. For any routed deposit that is the router, not the person. The stated requirement is that only addresses in the allowlist may add liquidity, and the brief says never to trust `sender` for identity. The two conflict and the implementation resolves the conflict silently in favour of `sender`. The contract's NatSpec admits the consequence, but no test states it. The tests only use the same `lp` through both routers, so the bypass reads as a non-issue. The fixture's allowed provider is v4-core's PoolModifyLiquidityTest, which pays from msg.sender and is permissionless. This is a scope question for whoever owns the design, not a redesign request. If the intended list is of routers or position managers, the tests and README should say so and test the outsider case. If it is of end users, this hook cannot deliver that with `sender` alone.","line":221,"path":"src/AllowlistLiquidityHook.sol","reproduction":"In the Fixture, `hook.isAllowed(outsider) == false`, and only `allowedRouter` is on the list. Then `vm.prank(outsider); allowedRouter.modifyLiquidity(key, ModifyLiquidityParams(-600, 600, 10 ether, bytes32(0)), \"\");` succeeds and `manager.getLiquidity(key.toId()) == 10 ether`. I ran this against a copy of the repo in /tmp and it passes. Expected under the literal requirement: revert with ProviderNotAllowed(outsider). Actual: the deposit lands. Missing test: no case where a non-allowlisted person deposits through an allowlisted router. The existing test_theRouteIsWhatDecidesNotThePerson only shows the same person being refused via a different router.","severity":"medium","title":"Allowlist keys on the modifyLiquidity caller, so any EOA can add liquidity through an allowlisted router; tests never show this"},{"description":"The constructor rejects only address(0). onlyPoolManager then trusts whatever address was baked in. A hook deployed with an EOA or a non-PoolManager contract as `_poolManager` deploys cleanly, and every callback is then authenticated against the wrong address. This is a deployment-input trust assumption, not an exploitable path. It is worth stating in the README because the code does not check it.","line":94,"path":"src/AllowlistLiquidityHook.sol","reproduction":"`new AllowlistLiquidityHook{salt: s}(IPoolManager(address(0xBEEF)), 3000, providers)` with a salt mined for the 0x1800 flags does not revert. `hook.poolManager()` returns 0xBEEF, and a callback pranked from 0xBEEF is accepted. Real pool managers can never reach the hook, since PoolManager.initialize would call it and receive NotPoolManager.","severity":"info","title":"Constructor does not check that poolManager is a contract, so 'canonical' is enforced only by the deployer's argument"}],"hash":"6302c110bb89c680a5f45aef36c7cb80481158cfe47fc7aa685e74309b1dd0ec","nodeId":"1bd49566-5096-4367-be89-c2b2feea8843","outcome":"completed","summary":"I found one high, one medium and one info issue. I wrote them to `.imd-findings.json`, which is the only file I created. My repro scratch test lives in `/tmp/rv`, outside the repo.\n\n**High: the README is missing.** No README exists anywhere outside `lib/`, though it is a required deliverable. The hook's NatSpec sends integrators to \"the README\" for its main warning, and that warning exists nowhere in the repo.\n\n**Medium: the allowlist decides on the router, not the person.** `beforeAddLiquidity` checks `sender`, which is the `modifyLiquidity` caller. `outsider` is not on the allowlist, yet `allowedRouter.modifyLiquidity` called by `outsider` succeeds and puts 10 ether of liquidity into the pool. I confirmed this in a scratch copy of the repo. The tests never cover a non-allowlisted person going through an allowed router, so this bypass is invisible in them. It is a conflict between \"only allowlisted addresses may add liquidity\" and \"never trust `sender` for identity\". The finding is framed as a scope question, not a redesign request.\n\n**Info: the constructor accepts any pool manager address except zero.** \"Canonical pool manager\" is enforced only by whatever the deployer passes in. A hook built with `address(0xBEEF)` deploys cleanly and trusts that address for every callback. It is worth a line in the README.\n\nI found no defects in the rest of the implementation:\n- The permission bits, the dynamic-fee check in `afterInitialize`, the per-`PoolId` state and the removal path all behave as specified. Zero-delta fee collection is routed to `beforeRemoveLiquidity`, which the hook never claims.\n- The 40 local tests pass with `forge test --offline`.\n- A scan of the hook's deployed runtime code found no `SELFDESTRUCT`, `DELEGATECALL` or `CALLCODE`, so the protected opcode check should hold.\n- I did not run the protected test files. They need creation-code environment variables, and their import paths do not resolve from where they sit in `.imd/`.","treeHash":null,"usage":{"cachedInputTokens":562765,"inputTokens":20,"model":"claude-sonnet-5","outputTokens":9933,"runtime":"claude","turns":12,"wallClockMs":133679}},{"artifacts":[],"attempt":1,"bundleHash":"e1b39d20e1e70bc23f545067bebb3dc9f1022a79f2241f2419db939dadafd6f1","device":"6c8e29b761cc68bd","findings":[],"hash":"8e1aa276b3b383a428d377b1e01a6735d6fdbb0319ebbb2ec1279d6d84632b37","nodeId":"9a458373-ce28-46dd-bdd4-39cb6bc837a4","outcome":"completed","summary":"","treeHash":"5915cb86f0bb2dc7850afb078e34dc16f482d0d4","usage":{"cachedInputTokens":4938439,"inputTokens":120,"model":"claude-opus-5","outputTokens":61569,"runtime":"claude","turns":61,"wallClockMs":768853}}],"verification":[{"checks":[{"durationMs":2632,"exitCode":0,"name":"build","output":"Compiling 79 files with Solc 0.8.26\nSolc 0.8.26 finished in 2.53s\nCompiler run successful!\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/Fixture.sol:115:13\n    │\n115 │             token0.transfer(who, 100_000 ether);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/Fixture.sol:116:13\n    │\n116 │             token1.transfer(who, 100_000 ether);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/AllowlistLiquidityHook.t.sol:454:35\n    │\n454 │                 amountSpecified: -int256(amount),\n    │                                   ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\n","passed":true},{"durationMs":170,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 4 tests for test/HookFlags.t.sol:HookFlagsTest\n[PASS] testFuzz_matchesIsExactNotASubset(address) (runs: 256, μ: 5533, ~: 5533)\n[PASS] testFuzz_onlyTheLowFourteenBitsMatter(address,uint160) (runs: 256, μ: 3983, ~: 3983)\n[PASS] test_everyBitMatchesV4Core() (gas: 8633)\n[PASS] test_minerFindsAnAddressCarryingTheRequestedFlags() (gas: 3749456)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 34.10ms (13.58ms CPU time)\n\nRan 14 tests for test/HookAuth.t.sol:HookAuthTest\n[PASS] testFuzz_onlyThePoolManagerIsAccepted(address) (runs: 256, μ: 30499, ~: 30499)\n[PASS] test_aDifferentPoolManagerIsNotTheCanonicalOne() (gas: 22392)\n[PASS] test_afterInitializeRejectsAKeyNamingAnotherHook() (gas: 17184)\n[PASS] test_anAllowlistedProviderStillCannotCallTheHookDirectly() (gas: 25093)\n[PASS] test_claimedCallbacksRefuseCallersOtherThanThePoolManager() (gas: 25964)\n[PASS] test_constructorRejectsAFeeOverTheCeiling() (gas: 78149)\n[PASS] test_constructorRejectsAZeroPoolManager() (gas: 40213)\n[PASS] test_constructorRejectsAnAddressWithoutTheDeclaredFlags() (gas: 90457)\n[PASS] test_constructorRejectsAnEmptyAllowlist() (gas: 39939)\n[PASS] test_constructorRejectsDuplicates() (gas: 88206)\n[PASS] test_constructorRejectsTheZeroAddress() (gas: 87908)\n[PASS] test_donateStillWorksBecauseTheHookIsNotConsulted() (gas: 1420358)\n[PASS] test_twoDeploymentsDoNotShareState() (gas: 7050921)\n[PASS] test_unclaimedCallbacksRevert() (gas: 57296)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 65.71ms (75.61ms CPU time)\n\nRan 23 tests for test/AllowlistLiquidityHook.t.sol:AllowlistLiquidityHookTest\n[PASS] testFuzz_anyAddressCanSwap(address,uint128) (runs: 256, μ: 575499, ~: 575600)\nLogs:\n  Bound result 9999000000000000061\n\n[PASS] testFuzz_onlyTheAllowlistedSenderIsAccepted(address,bytes) (runs: 256, μ: 38775, ~: 38771)\n[PASS] test_aRefusedPoolLeavesNoState() (gas: 120244)\n[PASS] test_addLiquidityToAnUnconfiguredPoolIsRefused() (gas: 22342)\n[PASS] test_afterInitializeRecordsThePoolAndWritesTheHooksFee() (gas: 27446)\n[PASS] test_allowedProviderCanAddLiquidity() (gas: 317774)\n[PASS] test_allowedProviderCanWithdrawEverything() (gas: 293064)\n[PASS] test_allowlistIsReadableAndFixed() (gas: 32725)\n[PASS] test_anyoneCanSwapInBothDirections() (gas: 510858)\n[PASS] test_beforeRemoveLiquidityIsUnreachableAndRefuses() (gas: 21024)\n[PASS] test_disallowedProviderCannotAddLiquidity() (gas: 64327)\n[PASS] test_feeCollectionIsNotGatedBecauseItIsAnExit() (gas: 1546579)\n[PASS] test_hookDataCannotForgeIdentity() (gas: 144599)\n[PASS] test_initializeRevertsForAStaticFeePool() (gas: 51390)\n[PASS] test_initializeRevertsForAZeroFeePool() (gas: 51357)\n[PASS] test_noAdminSelectorCanChangeTheAllowlist() (gas: 37908)\n[PASS] test_outsiderCanDepositThroughAnAllowlistedPermissionlessRouter() (gas: 315705)\n[PASS] test_permissionsMatchTheDeployedAddress() (gas: 20340)\n[PASS] test_poolStateIsPerPoolId() (gas: 632942)\n[PASS] test_swapsPayTheHooksFee() (gas: 411220)\n[PASS] test_theAddressCannotBlockAnExit() (gas: 9221)\n[PASS] test_theRouteIsWhatDecidesNotThePerson() (gas: 342171)\n[PASS] test_withdrawalReturnsPrincipalPlusFees() (gas: 1062575)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 69.67ms (101.75ms CPU time)\n\nRan 3 test suites in 70.58ms (169.48ms CPU time): 41 tests passed, 0 failed, 0 skipped (41 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"5b1d91a3ec60b84a16b65f2562e830735deb3b9e309b27d6459c904d30ef24e5","verifiedTreeHash":"b5fad506afa5e97128a9185af59fc2bc2115e9cb","verifierVersion":"0.1.0+eab70f1b"},{"checks":[{"durationMs":2674,"exitCode":0,"name":"build","output":"Compiling 79 files with Solc 0.8.26\nSolc 0.8.26 finished in 2.58s\nCompiler run successful!\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/Fixture.sol:115:13\n    │\n115 │             token0.transfer(who, 100_000 ether);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/Fixture.sol:116:13\n    │\n116 │             token1.transfer(who, 100_000 ether);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/AllowlistLiquidityHook.t.sol:441:35\n    │\n441 │                 amountSpecified: -int256(amount),\n    │                                   ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\n","passed":true},{"durationMs":198,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 4 tests for test/HookFlags.t.sol:HookFlagsTest\n[PASS] testFuzz_matchesIsExactNotASubset(address) (runs: 256, μ: 5526, ~: 5533)\n[PASS] testFuzz_onlyTheLowFourteenBitsMatter(address,uint160) (runs: 256, μ: 3983, ~: 3983)\n[PASS] test_everyBitMatchesV4Core() (gas: 8633)\n[PASS] test_minerFindsAnAddressCarryingTheRequestedFlags() (gas: 3749456)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 10.12ms (15.33ms CPU time)\n\nRan 14 tests for test/HookAuth.t.sol:HookAuthTest\n[PASS] testFuzz_onlyThePoolManagerIsAccepted(address) (runs: 256, μ: 30499, ~: 30499)\n[PASS] test_aDifferentPoolManagerIsNotTheCanonicalOne() (gas: 22392)\n[PASS] test_afterInitializeRejectsAKeyNamingAnotherHook() (gas: 17184)\n[PASS] test_anAllowlistedProviderStillCannotCallTheHookDirectly() (gas: 25093)\n[PASS] test_claimedCallbacksRefuseCallersOtherThanThePoolManager() (gas: 25964)\n[PASS] test_constructorRejectsAFeeOverTheCeiling() (gas: 78149)\n[PASS] test_constructorRejectsAZeroPoolManager() (gas: 40213)\n[PASS] test_constructorRejectsAnAddressWithoutTheDeclaredFlags() (gas: 90457)\n[PASS] test_constructorRejectsAnEmptyAllowlist() (gas: 39939)\n[PASS] test_constructorRejectsDuplicates() (gas: 88206)\n[PASS] test_constructorRejectsTheZeroAddress() (gas: 87908)\n[PASS] test_donateStillWorksBecauseTheHookIsNotConsulted() (gas: 1420358)\n[PASS] test_twoDeploymentsDoNotShareState() (gas: 7050921)\n[PASS] test_unclaimedCallbacksRevert() (gas: 57296)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 27.86ms (32.23ms CPU time)\n\nRan 22 tests for test/AllowlistLiquidityHook.t.sol:AllowlistLiquidityHookTest\n[PASS] testFuzz_anyAddressCanSwap(address,uint128) (runs: 256, μ: 575447, ~: 575577)\nLogs:\n  Bound result 9999007937818573582\n\n[PASS] testFuzz_onlyTheAllowlistedSenderIsAccepted(address,bytes) (runs: 256, μ: 38797, ~: 38793)\n[PASS] test_aRefusedPoolLeavesNoState() (gas: 120266)\n[PASS] test_addLiquidityToAnUnconfiguredPoolIsRefused() (gas: 22364)\n[PASS] test_afterInitializeRecordsThePoolAndWritesTheHooksFee() (gas: 27381)\n[PASS] test_allowedProviderCanAddLiquidity() (gas: 317708)\n[PASS] test_allowedProviderCanWithdrawEverything() (gas: 293081)\n[PASS] test_allowlistIsReadableAndFixed() (gas: 32747)\n[PASS] test_anyoneCanSwapInBothDirections() (gas: 510858)\n[PASS] test_beforeRemoveLiquidityIsUnreachableAndRefuses() (gas: 21024)\n[PASS] test_disallowedProviderCannotAddLiquidity() (gas: 64327)\n[PASS] test_feeCollectionIsNotGatedBecauseItIsAnExit() (gas: 1546601)\n[PASS] test_hookDataCannotForgeIdentity() (gas: 144621)\n[PASS] test_initializeRevertsForAStaticFeePool() (gas: 51390)\n[PASS] test_initializeRevertsForAZeroFeePool() (gas: 51357)\n[PASS] test_noAdminSelectorCanChangeTheAllowlist() (gas: 37930)\n[PASS] test_permissionsMatchTheDeployedAddress() (gas: 20340)\n[PASS] test_poolStateIsPerPoolId() (gas: 632942)\n[PASS] test_swapsPayTheHooksFee() (gas: 411220)\n[PASS] test_theAddressCannotBlockAnExit() (gas: 9221)\n[PASS] test_theRouteIsWhatDecidesNotThePerson() (gas: 342148)\n[PASS] test_withdrawalReturnsPrincipalPlusFees() (gas: 1062575)\nSuite result: ok. 22 passed; 0 failed; 0 skipped; finished in 90.73ms (114.02ms CPU time)\n\nRan 3 test suites in 91.74ms (128.72ms CPU time): 40 tests passed, 0 failed, 0 skipped (40 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"8e1aa276b3b383a428d377b1e01a6735d6fdbb0319ebbb2ec1279d6d84632b37","verifiedTreeHash":"5915cb86f0bb2dc7850afb078e34dc16f482d0d4","verifierVersion":"0.1.0+eab70f1b"}]}