{"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":"5980e47a-66dc-4496-bdbf-c573be7a8cec","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"ede516288b00243e4ad647c7961ceee5df587ed86ecd379eba4622f8d023ca95","dependsOn":["build_contract_project","manifest"],"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":"df09258fc3676538c0e190f2a0197af4ef0c15ef803642d08c48bde2a1a847eb","dependsOn":[],"execution":{"mustProduce":["src/LaunchToken.sol"],"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":"6eed625d88f5d83a73787f28e81c7bb9367aba5bf8eddb542271d0de2db7d7e4","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"}],"objective":"LaunchGuard: a Uniswap v4 hook that makes the first minutes of a new token pool hostile to sniper bots and fair for people buying by hand.\n\nThe pool creator opens a guarded pool through the hook itself (v4 initialize passes no hookData): one hook call stores the settings and initializes the pool (dynamic-fee flag) in the same transaction, and pools initialized any other way are rejected. Settings: a launch window in blocks (max 300) and a start fee. During the window:\n- Dynamic fee on buys (swaps that take the new token out of the pool) starts at the start fee (max 50%) and decays linearly to the pool's normal fee (1%) by the end of the window. Sells pay the normal fee from the start.\n- Max buy per swap and max total bought per address during the window, both set at initialization as a share of the token supply in the pool (e.g. 0.5% and 1%).\n- Only one buy per address per block; buys in the pool's first block are rejected entirely.\n- The extra fee collected above the normal fee goes to the pool's liquidity providers (donate to the pool), not to the hook owner.\nAfter the window the hook adds nothing but the 1% fee; nobody can change a pool's settings after initialization, and there is no owner withdraw.\n\nDeliver: the hook (correct permission flags and a mined address), a Foundry test suite against a local PoolManager covering the fee decay curve, buy limits per swap and per address, the one-buy-per-block rule, first-block rejection, sells during the window, behaviour after the window, and exact-input and exact-output swaps. Deploy on Sepolia with a demo token pool. README explaining the rules and the known limits (a sniper can still split across many addresses).","parentJobId":null,"planHash":"a7c1396947c78350ea47eee4beec39c74ddca81466e35b793903b7ae9a72c663","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"5980e47a-66dc-4496-bdbf-c573be7a8cec","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-379-launchguard-uniswap-v4-hook"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"50955","feedbackHash":"f5a11c38d67a6fe917c8a69f29f3201c22c5bbad1a2188ecd16fbc6cfef2e6a5","nodeKey":"adversarial_review","submissionHash":"ede516288b00243e4ad647c7961ceee5df587ed86ecd379eba4622f8d023ca95","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51046","feedbackHash":"6818b503981f58afea4e7cd87b9895ce17971cc6df0231d354269ca0ebef0f2f","nodeKey":"build_contract_project","submissionHash":"df09258fc3676538c0e190f2a0197af4ef0c15ef803642d08c48bde2a1a847eb","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"50971","feedbackHash":"add9c69e2ad3af967ce0f3cb6a5fe8e954107318a38704b1c268ab6ee297ce69","nodeKey":"manifest","submissionHash":"6eed625d88f5d83a73787f28e81c7bb9367aba5bf8eddb542271d0de2db7d7e4","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"3c8af3a134375823174061dd9f0f2448a7434dbdf1f8b6dc4857951e66b5f81c","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"9d8583129a474e66e8745d3bc88e5122d7494c98d1a03424827aaa483ee77806","device":"35c52a5b502e847c","findings":[],"hash":"6eed625d88f5d83a73787f28e81c7bb9367aba5bf8eddb542271d0de2db7d7e4","nodeId":"d380f7b5-be86-4c2d-975d-2b408e939b85","outcome":"completed","summary":"Created [launch.json](/home/identitymd5/.identitymd/work/5980e47a-66dc-4496-bdbf-c573be7a8cec/d380f7b5-be86-4c2d-975d-2b408e939b85/launch.json) with matching token metadata, LaunchGuard’s constructor argument, and the unhooked pool.\n\nValidation passed: schema/ABI checks, `forge build`, and all 43 tests, including protected checks. Only the manifest changed outside permitted scratch files.\n\nNotes document hook-address mining, the [official Sepolia PoolManager](https://developers.uniswap.org/docs/protocols/v4/deployments), and the existing simulation-only deployment status.","treeHash":"9ab889e8307e043274dd21dcadb80ed24bd0d66d","usage":{"cachedInputTokens":391040,"inputTokens":45116,"model":"gpt-6-astra","outputTokens":5647,"runtime":"codex","turns":4,"wallClockMs":204721}},{"artifacts":[],"attempt":1,"bundleHash":"f2bb0313e3a45815c8f90591a28c5fd806a659108cf7dc38256652d1c615a04b","device":"02ae6543274731ab","findings":[],"hash":"df09258fc3676538c0e190f2a0197af4ef0c15ef803642d08c48bde2a1a847eb","nodeId":"5403fc82-6ca9-413e-8afe-a2ebd44c8069","outcome":"completed","summary":"Implemented the hook, authenticated router, fixed-supply token, mined CREATE2 address, deployment scripts, and documentation.\n\nVerified:\n\n- `forge build` passes.\n- All 35 tests pass.\n- `forge fmt --check` passes.\n- Sepolia deployment simulation passes.\n\n**Live Sepolia deployment remains pending because no funded signer was supplied.** Parameters and instructions are in [README.md](/home/imd-worker/.identitymd/work/5980e47a-66dc-4496-bdbf-c573be7a8cec/5403fc82-6ca9-413e-8afe-a2ebd44c8069/README.md).","treeHash":"46bd19eea755472f263eb5b789aa3934eb0658c1","usage":{"cachedInputTokens":1845888,"inputTokens":131238,"model":"gpt-6-astra","outputTokens":37565,"runtime":"codex","turns":9,"wallClockMs":1291226}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"c4f696e22e7a36f7","findings":[],"hash":"e107ae26533528ccb06971f4729d54f9e570fd82a81f0eea874177db5759891b","nodeId":"40e556d9-2b2e-4eef-b71e-3f0857c5b5ea","outcome":"failed","summary":"This content was flagged for possible cybersecurity risk. If this seems wrong, try rephrasing your request. If you’re doing authorized security work that requires more cyber permissive safeguards, apply for Daybreak access via https://platform.openai.com/settings/organization/status-and-access before retrying.","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":null,"outputTokens":0,"runtime":"codex","turns":4,"wallClockMs":271543}},{"artifacts":[],"attempt":2,"bundleHash":null,"device":"3c7630b22a73c1fb","findings":[{"description":"launch.json lists LaunchGuard as a project contract with constructorArgs [Sepolia PoolManager]. The constructor calls Hooks.validateHookPermissions(IHooks(address(this)), ...) (src/LaunchGuard.sol:83), which reverts with HookAddressNotValid unless (address & 0x3fff) == 0x20cc. Only about 1 in 16,384 salts gives such an address. The protected floor (Project.protected.t.sol) deploys IMD_PROJECT_CODE_0 with CREATE2 from the factory address and the service-supplied IMD_PROJECT_SALT_0, and fails with 'project constructor failed' if the constructor reverts. The factory contract (evm-project-launch reference) documents constructor-only deployment with no salt mining for hook flags. The requirement appears only in the manifest notes ('the deployment factory must mine a CREATE2 salt'), and notes carry no deployment authority. Unless the service can show that its factory salt derivation targets this mask for the exact factory address, creation code and manager argument, this launch cannot pass the protected floor or deploy. Hook-side validation is correct and should stay. The fix is a scope decision: either the service supplies a mined salt, or LaunchGuard is removed from the factory's contracts list and deployed through its own mined CREATE2 path, as script/DeploySepolia.s.sol does.","line":11,"path":"launch.json","reproduction":"Scratch test outside the repo: a CREATE2 probe contract deploys abi.encodePacked(type(LaunchGuard).creationCode, abi.encode(0xE03A1074c86CFeDd5C142C4F04F1a1536e203543)) with salts bytes32(0)..bytes32(63). Result: 0 of 64 deployments succeed (create2 returns address(0) for each; the constructor reverts HookAddressNotValid). Expected for a factory-deployable manifest contract: the deploy succeeds for the salt the service assigns. Actual: success only for the ~1/16384 salts whose resulting address has low 14 bits 0x20cc (e.g. 0x9c75 for the recorded deployer 0x61991b4DEB3dD7cE70e4F95179cFa0E54fDC8cE0).","severity":"medium","title":"Manifest deploys LaunchGuard through the project factory, but its constructor reverts for any CREATE2 salt that is not mined to the 0x20cc permission mask"},{"description":"The test uses sqrtPriceLimitX96 = PRICE + 1, so the swap produces zero output. Both calls revert through the zero-output guard (InvalidSwap, LaunchGuard.sol:223), not the PartialFill checks at LaunchGuard.sol:235 and :237 or LaunchRouter.sol:133/136. It also uses a bare vm.expectRevert(), so any revert passes. No test in the suite expects PartialFill. The implementation does handle a real partial fill correctly (verified below), so this is a coverage gap, not a behavioural defect. A regression that removed the fill checks would not be caught. Unused input in an exact-input buy would still have the full surcharge reserved against it, or an exact-output buy could deliver less than requested.","line":436,"path":"test/LaunchGuard.t.sol","reproduction":"Run `forge test --match-test test_PartialFillsRevertForBothModes -vvvv`: both inner reverts are InvalidSwap() (selector 0x11157667 inside WrappedError), not PartialFill(). A real partial fill that no test covers: at START+1, ALICE calls router.swap(key, SwapParams(false, -3000 ether, TickMath.getSqrtPriceAtTick(10)), 0, deadline). Nonzero output stops at tick 10, and the call reverts WrappedError(..., PartialFill 0xd964f528). The exact-output variant (amountSpecified = +3000 ether, same limit) reverts the same way. The implementation is correct, but these inputs appear in no test.","severity":"low","title":"test_PartialFillsRevertForBothModes never reaches a partial-fill check; the hook's PartialFill branches are untested"},{"description":"The manifest pool (native ETH, fee 3000, tickSpacing 60, no hook) is what the factory seeds with the launch token. None of the LaunchGuard rules apply to it: first-block rejection, decaying fee, caps, one buy per block and donation. Even if deployed, the LaunchGuard instance from the contracts list has no initialized pool. Nobody calls initialize, and the factory makes no initialization calls. So the launch token's real market has no sniper protection. The manifest notes and README disclose this, and the reference says factory pools carry no hook, so this is not a code defect. It is recorded so admission does not read the launch as sniper-protected.","line":17,"path":"launch.json","reproduction":"After a factory launch, compute the manifest pool's PoolId (currency0 = 0x0, currency1 = token, fee 3000, tickSpacing 60, hooks = 0). LaunchGuard.launch(thatId).ready is false and currentBuyFee(thatId) reverts UnknownPool. A buy at the pool's first block with any size succeeds at the static 0.3% fee. The guarded behaviour applies only to a pool created later via LaunchGuard.initialize with creator funding.","severity":"info","title":"The factory-deployed hook guards no launch pool; the manifest's GUARD market is an ordinary unhooked 0.3% pool"}],"hash":"ede516288b00243e4ad647c7961ceee5df587ed86ecd379eba4622f8d023ca95","nodeId":"40e556d9-2b2e-4eef-b71e-3f0857c5b5ea","outcome":"completed","summary":"I found no defect in the hook's own logic. There are three findings, ranked by severity, in `.imd-findings.json` (valid JSON). I changed no other files; scratch probes ran in a throwaway copy in `/tmp`, which I've deleted.\n\n**Findings**\n\n1. **Medium: `launch.json:11` can't be deployed through the project factory as it stands.** The `LaunchGuard` constructor (`src/LaunchGuard.sol:83`) checks its own address and reverts unless the low 14 bits equal `0x20cc`. Only about 1 in 16,384 CREATE2 salts gives such an address. I deployed the real creation code, with the Sepolia PoolManager as argument, using salts 0–63: all 64 reverted. The protected project test deploys with a salt the service supplies, and nothing I read says that service picks salts to hit a hook address mask. So unless it does, setup fails with \"project constructor failed\". The check in the constructor is correct and should stay. Fixing this is a scope decision: either the service supplies a salt found by search for this address, or `LaunchGuard` comes out of the factory's contract list and gets deployed separately, as `DeploySepolia` does.\n\n2. **Low: `test/LaunchGuard.t.sol:436` doesn't test partial fills despite its name.** Its price limit is `PRICE + 1`, so the swap produces zero output and both calls revert with `InvalidSwap`, not `PartialFill`. It also accepts any revert, and no test anywhere expects `PartialFill`. I checked a real partial fill (price limit at tick 10, 3000 ether, both exact-input and exact-output): the hook correctly reverts with `PartialFill`. So the code is right, but that input appears in no test.\n\n3. **Info: the launch token's real pool has no protection.** The manifest's pool is a plain ETH pool with a 0.3% fee and no hook. The hook the factory deploys never gets a pool through `initialize`, so none of the launch rules apply to the launch token's actual market. The README and notes disclose this. I recorded it so nobody reads this launch as sniper-protected.\n\n**What I checked and found correct**\n- **Permissions:** the `0x20cc` flags match the five callbacks the hook enables.\n- **Initialization:** the only way in is through the hook's own `initialize` call; any other initialization is rejected.\n- **Fees:** exact-input and exact-output surcharges come out to the effective rate `f`. I derived this algebraically, and the fuzz tests compare both modes against real pools.\n- **Accounting:** the hook's donation debt and credit cancel exactly, so the hook keeps nothing.\n- **Buyer identity:** a buyer can't be faked. Direct calls from other routers and reentrancy from a token callback are both rejected.\n- **Launch rules:** first-block rejection, the window boundary, sells being charged 1%, and state rolling back on any revert all behave as specified.\n- **Recorded values:** the CREATE2 values in `deployments/sepolia.json` match the current build.\n\nThe full suite passes (35 tests).\n\nTwo things I didn't count as defects:\n- **No Sepolia deployment.** It wasn't broadcast, but contributor tasks are forbidden to broadcast and the README says so.\n- **Known limits.** Front-running pool creation, other LPs adding liquidity just before a buy to share the donation, and splitting buys across addresses are all accepted in the README.","treeHash":null,"usage":{"cachedInputTokens":1034937,"inputTokens":28,"model":"claude-fable-5-1","outputTokens":27669,"runtime":"claude","turns":18,"wallClockMs":403556}}],"verification":[{"checks":[{"durationMs":21674,"exitCode":0,"name":"build","output":"Compiling 80 files with Solc 0.8.26\nSolc 0.8.26 finished in 21.59s\nCompiler run successful!\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/LaunchToken.t.sol:15:9\n   │\n15 │         token.transfer(address(1), 100 ether);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/LaunchRouter.sol:61:13\n   │\n61 │         if (block.timestamp > deadline) revert Expired();\n   │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/LaunchToken.t.sol:19:9\n   │\n19 │         token.transferFrom(address(this), address(1), 50 ether);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/LaunchRouter.sol:92:13\n   │\n92 │         if (block.timestamp > deadline) revert Expired();\n   │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n   ╭▸ test/helpers/RawRouter.sol:67:85\n   │\n67 │             require(ERC20(Currency.unwrap(c)).transferFrom(payer, address(manager), uint256(-int256(delta))));\n   │                                                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n   ╭▸ test/helpers/RawRouter.sol:70:36\n   │\n70 │             manager.take(c, payer, uint128(delta));\n   │                                    ━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint128' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchRouter.sol:102:27\n    │\n102 │         if (amount < 0 && uint256(-amount) > current) revert InsufficientLiquidity();\n    │                           ━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchRouter.sol:104:36\n    │\n104 │         next = amount < 0 ? next - uint256(-amount) : next + uint256(amount);\n    │                                    ━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchRouter.sol:104:62\n    │\n104 │         next = amount < 0 ? next - uint256(-amount) : next + uint256(amount);\n    │                                                              ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/LaunchToken.t.sol:24:9\n   │\n24 │         token.transferFrom(address(this), address(1), 1);\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    ╭▸ src/LaunchRouter.sol:106:44\n    │\n106 │         liquidityOf[key.toId()][account] = uint128(next);\n    │                                            ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchRouter.sol:130:28\n    │\n130 │             uint256 paid = uint256(-int256(input));\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchGuard.sol:139:33\n    │\n139 │         l.initialTokenReserve = uint256(-int256(tokenDelta));\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchRouter.sol:131:32\n    │\n131 │             uint256 received = uint128(output);\n    │                                ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchRouter.sol:160:30\n    │\n160 │             if (delta < 0 && uint256(-int256(delta)) > limit) revert Slippage();\n    │                              ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchGuard.sol:204:31\n    │\n204 │             toBeforeSwapDelta(int128(uint128(surcharge)), 0),\n    │                               ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchGuard.sol:204:38\n    │\n204 │             toBeforeSwapDelta(int128(uint128(surcharge)), 0),\n    │                                      ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchRouter.sol:161:33\n    │\n161 │         } else if (delta < 0 || uint128(delta) < limit) {\n    │                                 ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/LaunchGuard.t.sol:77:13\n   │\n77 │             token0.transfer(user, 10_000_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/LaunchGuard.t.sol:78:13\n   │\n78 │             token1.transfer(user, 10_000_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    ╭▸ src/LaunchRouter.sol:169:90\n    │\n169 │             ERC20(Currency.unwrap(currency)).safeTransferFrom(account, address(manager), uint256(-int256(delta)));\n    │                                                                                          ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchRouter.sol:172:45\n    │\n172 │             manager.take(currency, account, uint128(delta));\n    │                                             ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:229:21\n    │\n229 │         _buy(ALICE, int256(cap + 1));\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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchGuard.sol:224:28\n    │\n224 │         uint256 received = uint128(output);\n    │                            ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:232:21\n    │\n232 │         _buy(ALICE, int256(cap));\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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchGuard.sol:235:17\n    │\n235 │             if (uint256(-int256(input)) != gross - surcharge) revert PartialFill();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:248:21\n    │\n248 │         _buy(ALICE, int256(cap));\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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:249:23\n    │\n249 │         _sell(ALICE, -int256(cap));\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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchGuard.sol:238:33\n    │\n238 │             uint256 numerator = uint256(-int256(input)) * (fee - NORMAL_FEE);\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:252:21\n    │\n252 │         _buy(ALICE, int256(remainder));\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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchGuard.sol:242:24\n    │\n242 │             returned = int128(uint128(surcharge));\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchGuard.sol:242:31\n    │\n242 │             returned = int128(uint128(surcharge));\n    │                               ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:331:67\n    │\n331 │         BalanceDelta expected = raw.swap(control, _params(false, -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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:332:44\n    │\n332 │         BalanceDelta actual = _buy(ALICE, -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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:333:37\n    │\n333 │         assertEq(actual.amount1(), -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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:343:66\n    │\n343 │         BalanceDelta expected = raw.swap(control, _params(false, 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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:344:43\n    │\n344 │         BalanceDelta actual = _buy(ALICE, 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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:345:36\n    │\n345 │         assertEq(actual.amount0(), 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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:355:39\n    │\n355 │         BalanceDelta d = _buy(ALICE, -int256(gross));\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\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/LaunchGuard.t.sol:465:9\n    │\n465 │         token0.transfer(address(manager), 100_000 ether);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\n","passed":true},{"durationMs":182,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 2 tests for test/LaunchToken.t.sol:LaunchTokenTest\n[PASS] test_FixedSupplyTransferAndAllowance() (gas: 675117)\n[PASS] test_NoAdminOrMintEntrypoints() (gas: 628440)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 486.96µs (388.31µs CPU time)\n\nRan 1 test for test/Deployment.t.sol:DeploymentTest\n[PASS] test_ExactDemoDeploymentPathAndRuntimeConstraints() (gas: 106404642)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 62.67ms (62.24ms CPU time)\n\nRan 32 tests for test/LaunchGuard.t.sol:LaunchGuardTest\n[PASS] testFuzz_ExactInputEffectiveFeeMatchesRealV4Fee(uint96,uint8) (runs: 256, μ: 540331, ~: 540518)\nLogs:\n  Bound result 2514284144633524143295\n  Bound result 39\n\n[PASS] testFuzz_ExactOutputEffectiveFeeMatchesRealV4Fee(uint96,uint8) (runs: 256, μ: 538966, ~: 539000)\nLogs:\n  Bound result 3999999999999000019205\n  Bound result 57\n\n[PASS] testFuzz_FeeDecayRoundingAndMaximumWindow(uint16,uint24) (runs: 256, μ: 836047, ~: 797999)\nLogs:\n  Bound result 183\n  Bound result 490316\n\n[PASS] test_AddressCapAndSellingDoesNotRestoreAllowance() (gas: 405743)\n[PASS] test_AfterWindowNoLimitsAndExternalRouting() (gas: 746622)\n[PASS] test_CallbacksAndSeedCannotBeCalledDirectly() (gas: 54078)\n[PASS] test_CumulativeCapAlsoRejectsExactInput() (gas: 323107)\n[PASS] test_DirectInitializationRejected() (gas: 43552)\n[PASS] test_DirectTransfersAndExtraLiquidityDoNotInflateCaps() (gas: 169076)\n[PASS] test_ExternalRouterSellsDuringWindow() (gas: 139209)\n[PASS] test_FailedSeedRollsBackInitialization() (gas: 781490)\n[PASS] test_FeeCurveEveryBlockAndEndBoundary() (gas: 358045)\n[PASS] test_FirstBlockRejectsBothSwapModes() (gas: 128156)\n[PASS] test_InvalidSettingsAndStaticFeeRejected() (gas: 59929)\n[PASS] test_MaxBuyExactInputUsesActualTokenOutput() (gas: 324647)\n[PASS] test_MaxBuyExactOutputBoundaryAndRevertRollback() (gas: 321676)\n[PASS] test_MinedPermissionsAndActualSeedReserve() (gas: 56535)\n[PASS] test_NormalStartingFeeStillEnforcesLimitsAndDoesNotDonate() (gas: 594872)\n[PASS] test_OneBlockWindowHasOnlyFirstBlockRejection() (gas: 571639)\n[PASS] test_OneBuyPerAddressPerBlockAndIndependentAddresses() (gas: 450087)\n[PASS] test_OnlyLPMayRemoveItsLiquidityAndCollectItsFees() (gas: 338367)\n[PASS] test_PartialFillsRevertForBothModes() (gas: 263059)\n[PASS] test_PaymentFailureRollsBackDonationAndLimits() (gas: 423853)\n[PASS] test_ProtocolFeeFailsClosed() (gas: 281686)\n[PASS] test_ReverseTokenOrientationAndIndependentPools() (gas: 906544)\n[PASS] test_SellsFirstBlockBothModesChargeOnlyNormalFee() (gas: 571306)\n[PASS] test_SettingsCannotBeChanged() (gas: 43340)\n[PASS] test_SlippageAndDeadlineRollbackBuyState() (gas: 541641)\n[PASS] test_SurplusDonatedAndCollectibleByLPExactInput() (gas: 323518)\n[PASS] test_SurplusDonatedAndCollectibleByLPExactOutput() (gas: 609928)\n[PASS] test_TinySwapCannotCreateFreeOutput() (gas: 345605)\n[PASS] test_UntrustedRouterCannotSpoofBuyer() (gas: 83417)\nSuite result: ok. 32 passed; 0 failed; 0 skipped; finished in 100.27ms (203.98ms CPU time)\n\nRan 3 test suites in 101.02ms (163.42ms CPU time): 35 tests passed, 0 failed, 0 skipped (35 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"6eed625d88f5d83a73787f28e81c7bb9367aba5bf8eddb542271d0de2db7d7e4","verifiedTreeHash":"9ab889e8307e043274dd21dcadb80ed24bd0d66d","verifierVersion":"0.1.0+ff982c0f"},{"checks":[{"durationMs":24674,"exitCode":0,"name":"build","output":"Compiling 80 files with Solc 0.8.26\nSolc 0.8.26 finished in 24.58s\nCompiler run successful!\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/LaunchRouter.sol:61:13\n   │\n61 │         if (block.timestamp > deadline) revert Expired();\n   │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/LaunchToken.t.sol:15:9\n   │\n15 │         token.transfer(address(1), 100 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/LaunchToken.t.sol:19:9\n   │\n19 │         token.transferFrom(address(this), address(1), 50 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/LaunchGuard.t.sol:77:13\n   │\n77 │             token0.transfer(user, 10_000_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/LaunchGuard.t.sol:78:13\n   │\n78 │             token1.transfer(user, 10_000_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/helpers/RawRouter.sol:67:85\n   │\n67 │             require(ERC20(Currency.unwrap(c)).transferFrom(payer, address(manager), uint256(-int256(delta))));\n   │                                                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n   ╭▸ test/helpers/RawRouter.sol:70:36\n   │\n70 │             manager.take(c, payer, uint128(delta));\n   │                                    ━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint128' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/LaunchRouter.sol:92:13\n   │\n92 │         if (block.timestamp > deadline) revert Expired();\n   │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:229:21\n    │\n229 │         _buy(ALICE, int256(cap + 1));\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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:232:21\n    │\n232 │         _buy(ALICE, int256(cap));\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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchGuard.sol:139:33\n    │\n139 │         l.initialTokenReserve = uint256(-int256(tokenDelta));\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/LaunchToken.t.sol:24:9\n   │\n24 │         token.transferFrom(address(this), address(1), 1);\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/LaunchGuard.t.sol:248:21\n    │\n248 │         _buy(ALICE, int256(cap));\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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:249:23\n    │\n249 │         _sell(ALICE, -int256(cap));\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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:252:21\n    │\n252 │         _buy(ALICE, int256(remainder));\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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchGuard.sol:204:31\n    │\n204 │             toBeforeSwapDelta(int128(uint128(surcharge)), 0),\n    │                               ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchRouter.sol:102:27\n    │\n102 │         if (amount < 0 && uint256(-amount) > current) revert InsufficientLiquidity();\n    │                           ━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchRouter.sol:104:36\n    │\n104 │         next = amount < 0 ? next - uint256(-amount) : next + uint256(amount);\n    │                                    ━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:331:67\n    │\n331 │         BalanceDelta expected = raw.swap(control, _params(false, -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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchRouter.sol:104:62\n    │\n104 │         next = amount < 0 ? next - uint256(-amount) : next + uint256(amount);\n    │                                                              ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchRouter.sol:106:44\n    │\n106 │         liquidityOf[key.toId()][account] = uint128(next);\n    │                                            ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:332:44\n    │\n332 │         BalanceDelta actual = _buy(ALICE, -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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchGuard.sol:204:38\n    │\n204 │             toBeforeSwapDelta(int128(uint128(surcharge)), 0),\n    │                                      ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:333:37\n    │\n333 │         assertEq(actual.amount1(), -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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:343:66\n    │\n343 │         BalanceDelta expected = raw.swap(control, _params(false, 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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchRouter.sol:130:28\n    │\n130 │             uint256 paid = uint256(-int256(input));\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:344:43\n    │\n344 │         BalanceDelta actual = _buy(ALICE, 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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchGuard.sol:224:28\n    │\n224 │         uint256 received = uint128(output);\n    │                            ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:345:36\n    │\n345 │         assertEq(actual.amount0(), 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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/LaunchGuard.t.sol:355:39\n    │\n355 │         BalanceDelta d = _buy(ALICE, -int256(gross));\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\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchRouter.sol:131:32\n    │\n131 │             uint256 received = uint128(output);\n    │                                ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchGuard.sol:235:17\n    │\n235 │             if (uint256(-int256(input)) != gross - surcharge) revert PartialFill();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchRouter.sol:160:30\n    │\n160 │             if (delta < 0 && uint256(-int256(delta)) > limit) revert Slippage();\n    │                              ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchGuard.sol:238:33\n    │\n238 │             uint256 numerator = uint256(-int256(input)) * (fee - NORMAL_FEE);\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchRouter.sol:161:33\n    │\n161 │         } else if (delta < 0 || uint128(delta) < limit) {\n    │                                 ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchGuard.sol:242:24\n    │\n242 │             returned = int128(uint128(surcharge));\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchRouter.sol:169:90\n    │\n169 │             ERC20(Currency.unwrap(currency)).safeTransferFrom(account, address(manager), uint256(-int256(delta)));\n    │                                                                                          ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchGuard.sol:242:31\n    │\n242 │             returned = int128(uint128(surcharge));\n    │                               ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LaunchRouter.sol:172:45\n    │\n172 │             manager.take(currency, account, uint128(delta));\n    │                                             ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/LaunchGuard.t.sol:465:9\n    │\n465 │         token0.transfer(address(manager), 100_000 ether);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\n","passed":true},{"durationMs":186,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 2 tests for test/LaunchToken.t.sol:LaunchTokenTest\n[PASS] test_FixedSupplyTransferAndAllowance() (gas: 675117)\n[PASS] test_NoAdminOrMintEntrypoints() (gas: 628440)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 1.86ms (1.63ms CPU time)\n\nRan 1 test for test/Deployment.t.sol:DeploymentTest\n[PASS] test_ExactDemoDeploymentPathAndRuntimeConstraints() (gas: 106404642)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 77.91ms (77.42ms CPU time)\n\nRan 32 tests for test/LaunchGuard.t.sol:LaunchGuardTest\n[PASS] testFuzz_ExactInputEffectiveFeeMatchesRealV4Fee(uint96,uint8) (runs: 256, μ: 540276, ~: 540511)\nLogs:\n  Bound result 3999999999999000101715\n  Bound result 1\n\n[PASS] testFuzz_ExactOutputEffectiveFeeMatchesRealV4Fee(uint96,uint8) (runs: 256, μ: 538892, ~: 539000)\nLogs:\n  Bound result 3999999999999000013766\n  Bound result 11\n\n[PASS] testFuzz_FeeDecayRoundingAndMaximumWindow(uint16,uint24) (runs: 256, μ: 830535, ~: 766181)\nLogs:\n  Bound result 101\n  Bound result 491746\n\n[PASS] test_AddressCapAndSellingDoesNotRestoreAllowance() (gas: 405743)\n[PASS] test_AfterWindowNoLimitsAndExternalRouting() (gas: 746622)\n[PASS] test_CallbacksAndSeedCannotBeCalledDirectly() (gas: 54078)\n[PASS] test_CumulativeCapAlsoRejectsExactInput() (gas: 323107)\n[PASS] test_DirectInitializationRejected() (gas: 43552)\n[PASS] test_DirectTransfersAndExtraLiquidityDoNotInflateCaps() (gas: 169076)\n[PASS] test_ExternalRouterSellsDuringWindow() (gas: 139209)\n[PASS] test_FailedSeedRollsBackInitialization() (gas: 781490)\n[PASS] test_FeeCurveEveryBlockAndEndBoundary() (gas: 358045)\n[PASS] test_FirstBlockRejectsBothSwapModes() (gas: 128156)\n[PASS] test_InvalidSettingsAndStaticFeeRejected() (gas: 59929)\n[PASS] test_MaxBuyExactInputUsesActualTokenOutput() (gas: 324647)\n[PASS] test_MaxBuyExactOutputBoundaryAndRevertRollback() (gas: 321676)\n[PASS] test_MinedPermissionsAndActualSeedReserve() (gas: 56535)\n[PASS] test_NormalStartingFeeStillEnforcesLimitsAndDoesNotDonate() (gas: 594872)\n[PASS] test_OneBlockWindowHasOnlyFirstBlockRejection() (gas: 571639)\n[PASS] test_OneBuyPerAddressPerBlockAndIndependentAddresses() (gas: 450087)\n[PASS] test_OnlyLPMayRemoveItsLiquidityAndCollectItsFees() (gas: 338367)\n[PASS] test_PartialFillsRevertForBothModes() (gas: 263059)\n[PASS] test_PaymentFailureRollsBackDonationAndLimits() (gas: 423853)\n[PASS] test_ProtocolFeeFailsClosed() (gas: 281686)\n[PASS] test_ReverseTokenOrientationAndIndependentPools() (gas: 906544)\n[PASS] test_SellsFirstBlockBothModesChargeOnlyNormalFee() (gas: 571306)\n[PASS] test_SettingsCannotBeChanged() (gas: 43340)\n[PASS] test_SlippageAndDeadlineRollbackBuyState() (gas: 541641)\n[PASS] test_SurplusDonatedAndCollectibleByLPExactInput() (gas: 323518)\n[PASS] test_SurplusDonatedAndCollectibleByLPExactOutput() (gas: 609928)\n[PASS] test_TinySwapCannotCreateFreeOutput() (gas: 345605)\n[PASS] test_UntrustedRouterCannotSpoofBuyer() (gas: 83417)\nSuite result: ok. 32 passed; 0 failed; 0 skipped; finished in 103.99ms (228.93ms CPU time)\n\nRan 3 test suites in 104.87ms (183.76ms CPU time): 35 tests passed, 0 failed, 0 skipped (35 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"df09258fc3676538c0e190f2a0197af4ef0c15ef803642d08c48bde2a1a847eb","verifiedTreeHash":"46bd19eea755472f263eb5b789aa3934eb0658c1","verifierVersion":"0.1.0+ff982c0f"}]}