{"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":"a38b37bd-6caa-4756-9aa2-6033c44ac713","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":null,"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":"working"},{"acceptedSubmissionHash":null,"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":"working"},{"acceptedSubmissionHash":null,"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":null,"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":"working"},{"acceptedSubmissionHash":null,"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":"working"},{"acceptedSubmissionHash":"883df1c6d0150dfd1c1d34edd453ef6f4484f1c3dbf3e053cf5b7b24e9cd31b6","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"587567a5ef71546b5973ceaf6ef1dbbd590f49503b5ac9a6973ed86b89584857","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"587567a5ef71546b5973ceaf6ef1dbbd590f49503b5ac9a6973ed86b89584857","skillId":"build-contract-project","state":"accepted"},{"acceptedSubmissionHash":null,"dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"failed"},{"acceptedSubmissionHash":null,"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":"working"}],"objective":"Build a token with a Uniswap v4 hook and an NFT reward distributor for the Swarm Pepe collection (SPEPE, 0x999ce0CE8C5f7661e0c74a568FfE27CEB9177bDB, Ethereum mainnet). The collection contract cannot be changed and has no transfer hooks. Minting is still open (verify onchain; totalSupply() reverts, use totalMinted()). Launch kind univ4_hook on Ethereum mainnet, paired with ETH: the launch's standard token and pool with our hook, plus our distributor and auction contracts. Deploy in the launch. No website in this job: an existing site will integrate the contracts later, so keep clean ABIs, events and the views below. No owner powers after launch, no upgradeability, no pause.\n\nToken name: OG. Symbol: OG. The launch's standard token (1,000,000,000, 18 decimals, plain transfers); \"burn\" in this spec means sending to 0x000000000000000000000000000000000000dEaD, counted in a public totalBurned.\n\nWhen the hook acts: on every swap in this pool, taking its fee from the settled ETH deltas (beforeSwap/afterSwap with return deltas), and enforcing the launch protection below.\n\nHOOK FEE: 3.5% on every buy and every sell, always taken in ETH (from the ETH input on buys, from the ETH output on sells), computed on actual settled deltas for exact-input and exact-output swaps. Of it: 2.5% of the trade to the distributor, 1% of the trade to the team wallet 0x90738ABe9b04622Dc0b3d015a3964Cc7D1Fd1859.\n\nLAUNCH PROTECTION: open to everyone from the first block. For the first 60 minutes after the pool opens, the buy fee decays linearly from 50% to the normal 3.5%. Everything above 3.5% goes to the distributor backlog, none to the team. After minute 60: normal fees.\n\nDISTRIBUTOR (per tokenId, weighted, no loops):\n- An NFT earns nothing until activated. Levels and weights: L1 = 1, L2 = 2, L3 = 4.\n- Activation burns OG. Cumulative cost: L1 = 50,000, L2 = 150,000, L3 = 400,000 OG (upgrading pays only the difference). Costs fixed in code, no oracle. Only the current ownerOf(tokenId) can activate or upgrade. Also activation with ETH: the contract buys the exact OG amount through the pool (paying the hook fee like any buyer) and burns it.\n- Accrual: accPerWeight += eth * SCALE / totalWeight; pending(id) = weight[id] * accPerWeight / SCALE - debt[id]. A new activation or upgrade settles pending first and sets debt at the current accumulator, so it never earns past fees.\n- Level and pending ETH belong to the tokenId and travel with the NFT on any transfer or marketplace sale.\n- Backlog: fees that arrive while totalWeight = 0 (and the launch-protection surplus) are held and streamed into the accumulator linearly over 30 days once something is active, never paid as a windfall to the first activator.\n\nEXIT (the only way to get ETH):\n- No claim that keeps the NFT. To receive its pending ETH, the owner hands the NFT to the contract and is paid everything accrued on it in the same transaction. Its level is cleared and its weight leaves totalWeight.\n- Exit is not allowed within 24 hours after the NFT's last activation or upgrade.\n\nAUCTION:\n- The exited NFT is immediately listed in a Dutch auction priced in OG.\n- Start price = max(10x the previous auction's sale price, 500,000 OG). Exponential decay over 36 hours down to a floor of 50,000 OG; at the floor it stays listed until someone buys.\n- 100% of auction proceeds are burned. The buyer receives the NFT at level 0 with zero accrual and must activate it to earn.\n\nVIEWS for the existing website (also emit an event for every activation, upgrade, exit, auction listing, sale and fee split): totalWeight, active NFTs per level, pending(id), level(id), backlog left and its stream end, current auctions with live prices, last sale price, total burned, launch fee now and minutes left of the decay.\n\nTESTS (Foundry, mainnet fork): fee in ETH on both sides and both exact modes and the 2.5/1 split; launch fee decay over 60 minutes and surplus to backlog; weighted accrual and upgrade math; no retroactive rewards; backlog streaming with zero active; level and pending travelling with transfers; exit payout and the 24h lock; auction start/decay/floor and burn; reentrancy on ETH sends and ERC-721 transfers; ETH solvency and weight conservation invariants. Independent review of the economics and every contract.","parentJobId":null,"planHash":"1808a70bcde7c2656aa03cfca6cc0e3a4625e88acae31e8041d3e6f176b733b9","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"a38b37bd-6caa-4756-9aa2-6033c44ac713","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-1036-og-symbol-og-the-launch-s-standard-token"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"51353","feedbackHash":"0a27e2a2df86225272613ad288745bc815dd742093742fd34d4116c7c8c89c95","nodeKey":"build_contract_project","submissionHash":"883df1c6d0150dfd1c1d34edd453ef6f4484f1c3dbf3e053cf5b7b24e9cd31b6","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"e92af49968aec7153bf1501d17b8e3f6c244e4ac2ccfa8b174f3ae4002d34513","state":"blocked","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"45733b6bb4e97b16","findings":[],"hash":"07efc3938d9b714a655761a958f6ea0b6d09cf82184e91e874c7d5e94cac5178","nodeId":"36afc9ae-8254-4456-a379-7036c71c5c27","outcome":"failed","summary":"needs input: The required launch.json pool.initialPrice has no production value in the brief or accepted work. docs/launch-config.json lists initial sqrtPriceX96 as unresolved, and README.md identifies its numeric price as a test fixture only. The schema requires a decimal sqrtPriceX96 and provides no price placeholder; choosing a production price would invent an economic launch parameter. — What initial production price should the ETH/OG pool use, expressed as decimal sqrtPriceX96 (currency0 = native ETH, currency1 = OG), or equivalently as OG per ETH?","treeHash":null,"usage":{"cachedInputTokens":894080,"inputTokens":64825,"model":"gpt-6-astra","outputTokens":3057,"runtime":"codex","turns":5,"wallClockMs":267544}},{"artifacts":[],"attempt":1,"bundleHash":"8d918c729607f1be5c14bc1b4d2e4b162b6f121f8462e77dad3af25760b1d064","device":"60f85cbc35c28a7e","findings":[],"hash":"883df1c6d0150dfd1c1d34edd453ef6f4484f1c3dbf3e053cf5b7b24e9cd31b6","nodeId":"aff73ce5-9206-4d77-be01-c757511afbbd","outcome":"completed","summary":"Implemented OG, the ETH-fee hook, NFT rewards, Dutch auctions, launch wiring, ABIs, and documentation.\n\n- Build and formatting checks pass.\n- Offline: 35 passed, 1 explicit fork skip.\n- Mainnet fork: 36 passed, no failures.\n- SPEPE minting verified open: 1,242 minted.\n- Independent review completed; claim-timing issue fixed.\n\nSee [README](README.md) and [validation results](docs/validation.md). No transactions broadcast; launch price and liquidity parameters remain documented deployment inputs.","treeHash":"ccefb3434f346154f341f50c2a9169e4bd8ceb31","usage":{"cachedInputTokens":5849600,"inputTokens":152124,"model":"gpt-6-astra","outputTokens":56281,"runtime":"codex","turns":13,"wallClockMs":2637793}}],"verification":[{"checks":[{"durationMs":37969,"exitCode":0,"name":"build","output":"Compiling 85 files with Solc 0.8.26\nSolc 0.8.26 finished in 37.84s\nCompiler run successful!\nwarning[missing-events-access-control]: `unfundedFees` is changed without an event but is used for access control\n    ╭▸ src/OGDistributor.sol:121:9\n    │\n121 │         unfundedFees += normal + surplus;\n    │         ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/OGAuction.sol:38:48\n   │\n38 │     constructor(OG token_, ISpepe collection_, address distributor_) {\n   │                                                ━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-events-access-control]: `unfundedFees` is changed without an event but is used for access control\n    ╭▸ src/OGDistributor.sol:127:9\n    │\n127 │         unfundedFees -= msg.value;\n    │         ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-events-access-control]: `level` is changed without an event but is used for access control\n    ╭▸ src/OGDistributor.sol:205:16\n    │\n205 │         delete level[id];\n    │                ━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/OGDistributor.sol:46:71\n   │\n46 │     constructor(OG token_, ISpepe collection_, IPoolManager manager_, address hook_) {\n   │                                                                       ━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/OGDistributor.sol:77:24\n   │\n77 │         uint256 now_ = block.timestamp < streamEnd ? block.timestamp : streamEnd;\n   │                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/OGHook.sol:117:16\n    │\n117 │         return elapsed >= DECAY ? NORMAL_FEE : NORMAL_FEE + 0.465e18 * (DECAY - elapsed) / DECAY;\n    │                ━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/OGHook.sol:123:16\n    │\n123 │         return elapsed >= DECAY ? 0 : (DECAY - elapsed + 59) / 60;\n    │                ━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/OGAuction.sol:60:13\n   │\n60 │         if (elapsed >= DURATION) return FLOOR;\n   │             ━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[arbitrary-send-eth]: ETH is sent to a user-controlled destination; restrict the destination or the caller\n   ╭▸ src/Interfaces.sol:30:22\n   │\n30 │         (bool ok,) = to.call{value: amount}(\"\");\n   │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/arbitrary-send-eth\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/OGAuction.sol:61:13\n   │\n61 │         if (elapsed == 0) return a.startPrice;\n   │             ━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/OGAuction.sol:62:34\n   │\n62 │         int256 logarithm = wadLn(int256(FLOOR * 1e18 / a.startPrice));\n   │                                  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'int256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/OGAuction.sol:63:41\n   │\n63 │         uint256 result = a.startPrice * uint256(wadExp(logarithm * int256(elapsed) / int256(DURATION))) / 1e18;\n   │                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/OGAuction.sol:63:68\n   │\n63 │         uint256 result = a.startPrice * uint256(wadExp(logarithm * int256(elapsed) / int256(DURATION))) / 1e18;\n   │                                                                    ━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'int256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/OGAuction.sol:63:86\n   │\n63 │         uint256 result = a.startPrice * uint256(wadExp(logarithm * int256(elapsed) / int256(DURATION))) / 1e18;\n   │                                                                                      ━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'int256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-no-eth]: external call can be reentered before `entered` is updated\n   ╭▸ src/OGAuction.sol:79:17\n   │\n79 │         require(token.transferFrom(msg.sender, token.DEAD(), cost));\n   │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `entered` is updated\n   ╭▸ src/OGAuction.sol:80:9\n   │\n80 │         collection.safeTransferFrom(address(this), recipient, id);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/OGHook.sol:163:25\n    │\n163 │             quotedFee = fee;\n    │                         ━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/OGAuction.sol:70:13\n   │\n70 │         if (block.timestamp > deadline || cost > maxPrice) revert SlippageOrExpired();\n   │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/OGAuction.sol:81:9\n   │\n81 │         emit AuctionSold(id, msg.sender, recipient, cost);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OGHook.sol:146:33\n    │\n146 │             uint256 requested = uint256(params.amountSpecified < 0 ? -params.amountSpecified : params.amountSpecified);\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OGHook.sol:149:48\n    │\n149 │                 quoteParams.amountSpecified = -int256(requested - fee);\n    │                                                ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OGHook.sol:152:29\n    │\n152 │                 if (gross > uint256(uint128(type(int128).max))) revert InvalidAmount();\n    │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OGHook.sol:152:37\n    │\n152 │                 if (gross > uint256(uint128(type(int128).max))) revert InvalidAmount();\n    │                                     ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OGHook.sol:153:47\n    │\n153 │                 quoteParams.amountSpecified = 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://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OGHook.sol:158:31\n    │\n158 │                 if (actual != uint256(-quoteParams.amountSpecified)) fee = actual * rate / (WAD - rate);\n    │                               ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-no-eth]: external call can be reentered before `level` is updated\n    ╭▸ src/OGDistributor.sol:147:17\n    │\n147 │         require(token.transferFrom(msg.sender, token.DEAD(), cost));\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OGDistributor.sol:109:9\n    │\n109 │         emit StreamScheduled(backlog, streamStart, streamEnd);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OGDistributor.sol:192:23\n    │\n192 │         if (old == 0) emit Activated(id, msg.sender, newLevel, cost);\n    │                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OGDistributor.sol:193:14\n    │\n193 │         else emit Upgraded(id, msg.sender, old, newLevel, cost);\n    │              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OGHook.sol:172:40\n    │\n172 │             if (reason.length != 36 || bytes4(reason) != QuoteResult.selector) {\n    │                                        ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'bytes4' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-no-eth]: external call can be reentered before `level` is updated\n    ╭▸ src/OGDistributor.sol:160:36\n    │\n160 │         uint256 spent = abi.decode(poolManager.unlock(abi.encode(cost, msg.value, sqrtPriceLimitX96)), (uint256));\n    │                                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-eth]: uncapped ETH transfer can be reentered before `entered` is updated\n   ╭▸ src/Interfaces.sol:30:22\n   │\n30 │         (bool ok,) = to.call{value: amount}(\"\");\n   │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-eth\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/OGDistributor.sol:157:13\n    │\n157 │         if (block.timestamp > deadline) revert SlippageOrExpired();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OGDistributor.sol:170:69\n    │\n170 │         BalanceDelta delta = poolManager.swap(key, SwapParams(true, int256(cost), limit), \"\");\n    │                                                                     ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OGDistributor.sol:171:25\n    │\n171 │         uint256 spent = uint256(-int256(delta.amount0()));\n    │                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OGDistributor.sol:172:32\n    │\n172 │         if (delta.amount1() != int256(cost) || spent > budget) revert SlippageOrExpired();\n    │                                ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OGDistributor.sol:174:9\n    │\n174 │         poolManager.settle{value: spent}();\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-eth]: uncapped ETH transfer can be reentered before `teamCredit` is updated\n    ╭▸ src/OGHook.sol:250:22\n    │\n250 │         (bool ok,) = TEAM.call{value: amount}(\"\");\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `busy` is updated\n    ╭▸ src/OGHook.sol:216:17\n    │\n216 │                 poolManager.mint(address(this), 0, fee);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `busy` is updated\n    ╭▸ src/OGHook.sol:220:17\n    │\n220 │                 distributor.receiveFeeClaims(normal, surplus);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `busy` is updated\n    ╭▸ src/OGHook.sol:222:17\n    │\n222 │                 poolManager.take(key.currency0, address(this), fee);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `level` is updated\n    ╭▸ src/OGDistributor.sol:199:32\n    │\n199 │         if (unfundedFees != 0) IOGPool(hook).redeemFees();\n    │                                ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OGHook.sol:252:14\n    │\n252 │         else emit TeamPaid(amount);\n    │              ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OGHook.sol:226:9\n    │\n226 │         emit FeeSplit(sender, params.zeroForOne, gross, normal, team, surplus, asClaim);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `entered` is updated\n    ╭▸ src/OGDistributor.sol:210:9\n    │\n210 │         auction.list(id);\n    │         ━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `entered` is updated\n    ╭▸ src/OGDistributor.sol:211:9\n    │\n211 │         collection.safeTransferFrom(msg.sender, address(auction), id);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OGHook.sol:232:16\n    │\n232 │         return uint256(value < 0 ? -int256(value) : int256(value));\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OGHook.sol:236:21\n    │\n236 │         if (value > uint256(uint128(type(int128).max))) revert InvalidAmount();\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OGHook.sol:236:29\n    │\n236 │         if (value > uint256(uint128(type(int128).max))) revert InvalidAmount();\n    │                             ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OGHook.sol:237:16\n    │\n237 │         return int128(int256(value));\n    │                ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OGHook.sol:237:23\n    │\n237 │         return int128(int256(value));\n    │                       ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/OGDistributor.sol:198:13\n    │\n198 │         if (block.timestamp < lastActivation[id] + EXIT_LOCK) revert Locked();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OGDistributor.sol:213:9\n    │\n213 │         emit Exited(id, msg.sender, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `busy` is updated\n    ╭▸ src/OGHook.sol:270:9\n    │\n270 │         poolManager.unlock(abi.encode(normal, surplus, team));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OGHook.sol:270:9\n    │\n270 │         poolManager.unlock(abi.encode(normal, surplus, team));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OGHook.sol:283:9\n    │\n283 │         emit ClaimsRedeemed(total);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Distributor.t.sol:124:17\n    │\n124 │         vm.warp(block.timestamp + 40 days);\n    │         ────────━━━━━━━━━━━━━━━─────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Distributor.t.sol:127:27\n    │\n127 │         uint256 started = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n128 │         assertEq(dist.streamEnd(), started + 30 days);\n129 │         vm.warp(started + 15 days);\n    │         ────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Distributor.t.sol:143:17\n    │\n143 │         vm.warp(block.timestamp + 10 days);\n    │         ────────━━━━━━━━━━━━━━━─────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Distributor.t.sol:150:17\n    │\n150 │         vm.warp(block.timestamp + 100 days);\n    │         ────────━━━━━━━━━━━━━━━──────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Distributor.t.sol:162:17\n    │\n162 │         vm.warp(block.timestamp + 15 days);\n    │         ────────━━━━━━━━━━━━━━━─────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Distributor.t.sol:286:25\n    │\n286 │         uint256 start = block.timestamp;\n    │                         ━━━━━━━━━━━━━━━\n287 │         vm.warp(start + 18 hours);\n    │         ───────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Distributor.t.sol:295:43\n    │\n295 │         auction.buy(1, 50_000 ether, BOB, block.timestamp);\n    │                                           ━━━━━━━━━━━━━━━\n    ‡\n305 │         vm.warp(vm.getBlockTimestamp() + 24 hours);\n    │         ────────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Distributor.t.sol:351:25\n    │\n351 │         uint256 start = block.timestamp;\n    │                         ━━━━━━━━━━━━━━━\n352 │         vm.warp(start + first);\n    │         ────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/MainnetFork.t.sol:50:17\n   │\n50 │         vm.warp(block.timestamp + 24 hours);\n   │         ────────━━━━━━━━━━━━━━━──────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/MainnetFork.t.sol:57:17\n   │\n57 │         vm.warp(block.timestamp + 36 hours);\n   │         ────────━━━━━━━━━━━━━━━──────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\n","passed":true},{"durationMs":1676,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/MainnetFork.t.sol:MainnetForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 306.88µs (0.00ns CPU time)\n\nRan 2 tests for test/Hook.t.sol:FreshManagerTest\n[PASS] test_claimRewardsPrecedeLaterActivationAndExitRedeems() (gas: 10251951)\n[PASS] test_firstBuyWithTokensOnlyMintsAndRedeemsClaims() (gas: 9411287)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 1.51ms (2.33ms CPU time)\n\nRan 2 tests for test/ActivationETH.t.sol:ActivationETHTest\n[PASS] test_exactOGBoughtBurnedWithFeeAndRefund() (gas: 650895)\n[PASS] test_slippageExpiryPartialFillAndInsufficientETHRevert() (gas: 493035)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 1.86ms (611.97µs CPU time)\n\nRan 4 tests for test/Distributor.t.sol:AuctionTest\n[PASS] testFuzz_monotonicPrice(uint32,uint32) (runs: 256, μ: 32122, ~: 32334)\n[PASS] test_auctionFailuresAndReceiverReentry() (gas: 998954)\n[PASS] test_boundedAuctionViewsAndUnexpectedNFTRejected() (gas: 194948)\n[PASS] test_exponentialDecayFloorBurnAndResaleStart() (gas: 1229353)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 3.80ms (3.62ms CPU time)\n\nRan 2 tests for test/Token.t.sol:TokenTest\n[PASS] testFuzz_plainTransfers(uint256) (runs: 256, μ: 69478, ~: 69726)\n[PASS] test_supplyPlainTransferAllowanceAndBurn() (gas: 309826)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.07ms (4.18ms CPU time)\n\nRan 12 tests for test/Hook.t.sol:HookTest\n[PASS] testFuzz_feeBuyAndSell(uint96,bool,bool) (runs: 256, μ: 299241, ~: 315797)\n[PASS] test_decayAndSurplus() (gas: 873559)\n[PASS] test_exactModesRespectAmount() (gas: 826933)\n[PASS] test_feeAllFourModes() (gas: 1006218)\n[PASS] test_partialBuyExactInput() (gas: 325611)\n[PASS] test_partialBuyExactOutput() (gas: 271589)\n[PASS] test_partialSellExactInput() (gas: 266994)\n[PASS] test_partialSellExactOutput() (gas: 325482)\n[PASS] test_permissionsAndUnauthorizedCallbacks() (gas: 148720)\n[PASS] test_rejectingTeamDoesNotBlockSwap() (gas: 482167)\n[PASS] test_sellsHaveNoLaunchSurplus() (gas: 514246)\n[PASS] test_wrongPoolRejected() (gas: 78296)\nSuite result: ok. 12 passed; 0 failed; 0 skipped; finished in 21.37ms (24.97ms CPU time)\n\nRan 11 tests for test/Distributor.t.sol:DistributorTest\n[PASS] testFuzz_roundingConservesETH(uint96) (runs: 256, μ: 1211380, ~: 1211274)\n[PASS] test_backlogWaitsAndStreamsWithoutWindfall() (gas: 706836)\n[PASS] test_claimAccountingAtSwapTimeNotRedemption() (gas: 558784)\n[PASS] test_costsAndUnauthorizedOrInvalidActions() (gas: 512441)\n[PASS] test_exitETHReentryAndFailedPayoutRollBack() (gas: 1600994)\n[PASS] test_noRetroactiveRewardsIncludingNewlyMintedNFT() (gas: 630233)\n[PASS] test_streamPausesWithZeroWeightAndRestarts() (gas: 870021)\n[PASS] test_surplusStreamsEvenWithActiveWeight() (gas: 533624)\n[PASS] test_transferCarriesLevelPendingAndLock() (gas: 750683)\n[PASS] test_upgradeResetsLockAndExitNeedsNFTApproval() (gas: 650137)\n[PASS] test_weightedAccrualAndUpgradePreservesPending() (gas: 746507)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 21.97ms (24.40ms CPU time)\n\nRan 1 test for test/Launch.t.sol:LaunchTest\n[PASS] test_realCreate2DeploymentInitializesAllContracts() (gas: 38829158)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 23.50ms (23.22ms CPU time)\n\nRan 1 test for test/Invariants.t.sol:AccountingInvariantTest\n[PASS]\nAccountingInvariantTest invariants:\n[PASS] invariant_ETHSolvencyAndConservation\n[PASS] invariant_burnAccountingAndSupply\n[PASS] invariant_weightAndLevelCountsConserved\n AccountingInvariantTest invariants (runs: 128, calls: 8192, reverts: 0)\n\n╭---------------+----------+-------+---------+----------╮\n| Contract      | Selector | Calls | Reverts | Discards |\n+=======================================================+\n| RewardHandler | activate | 1643  | 0       | 0        |\n|---------------+----------+-------+---------+----------|\n| RewardHandler | advance  | 1576  | 0       | 0        |\n|---------------+----------+-------+---------+----------|\n| RewardHandler | buy      | 1636  | 0       | 0        |\n|---------------+----------+-------+---------+----------|\n| RewardHandler | exit     | 1642  | 0       | 0        |\n|---------------+----------+-------+---------+----------|\n| RewardHandler | fees     | 1695  | 0       | 0        |\n╰---------------+----------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.59s (1.59s CPU time)\n\nRan 9 test suites in 1.59s (1.67s CPU time): 35 tests passed, 0 failed, 1 skipped (36 total tests)\n","passed":true},{"durationMs":41,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"OG.approve(address,uint256)\",\"OG.transfer(address,uint256)\",\"OG.transferFrom(address,address,uint256)\",\"OGAuction.buy(uint256,uint256,address,uint256)\",\"OGAuction.list(uint256)\",\"OGDistributor.activate(uint256,uint8)\",\"OGDistributor.activateWithETH(uint256,uint8,uint160,uint256)\",\"OGDistributor.checkpoint()\",\"OGDistributor.exit(uint256)\",\"OGDistributor.fundFeeClaims()\",\"OGDistributor.receiveFeeClaims(uint256,uint256)\",\"OGDistributor.receiveFees(uint256,uint256)\",\"OGDistributor.unlockCallback(bytes)\",\"OGHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"OGHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"OGHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"OGHook.payTeam()\",\"OGHook.quoteNative((address,address,uint24,int24,address),(bool,int256,uint160))\",\"OGHook.receive()\",\"OGHook.redeemFees()\",\"OGHook.unlockCallback(bytes)\"],\"files\":{\".gitignore\":7,\"README.md\":117,\"abi/OG.json\":260,\"abi/OGAuction.json\":383,\"abi/OGDistributor.json\":713,\"abi/OGHook.json\":837,\"docs/checks/mainnet-all-tests.txt\":86,\"docs/checks/mainnet-lifecycle.txt\":7,\"docs/checks/offline-tests.txt\":86,\"docs/checks/source-sha256.json\":21,\"docs/dependencies.txt\":3,\"docs/independent-review.md\":46,\"docs/launch-config.json\":31,\"docs/mainnet-verification.json\":548,\"docs/validation.md\":27,\"foundry.toml\":19,\"script/PrepareLaunch.s.sol\":32,\"src/HookFlags.sol\":30,\"src/Interfaces.sol\":33,\"src/OG.sol\":48,\"src/OGAuction.sol\":107,\"src/OGDistributor.sol\":219,\"src/OGHook.sol\":290,\"test/ActivationETH.t.sol\":45,\"test/Distributor.t.sol\":360,\"test/Hook.t.sol\":192,\"test/Invariants.t.sol\":123,\"test/Launch.t.sol\":60,\"test/MainnetFork.t.sol\":64,\"test/PoolRouter.sol\":65,\"test/SystemBase.sol\":97,\"test/Token.t.sol\":40,\"test/mocks/MockERC20.sol\":9,\"test/mocks/MockSpepe.sol\":24},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":3436,"exitCode":0,"name":"slither","output":"[high/medium] reentrancy-eth at src/OGHook.sol:187: Reentrancy in OGHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/OGHook.sol#187-229):\n[high/medium] reentrancy-eth at src/OGHook.sol:246: Reentrancy in OGHook._payTeam() (src/OGHook.sol#246-253):\n[medium/high] incorrect-equality at src/OGDistributor.sol:75: OGDistributor._vested() (src/OGDistributor.sol#75-79) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/Interfaces.sol:28: Guard._sendETH(address,uint256) (src/Interfaces.sol#28-32) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/OGDistributor.sol:104: OGDistributor._schedule() (src/OGDistributor.sol#104-110) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/OGAuction.sol:56: OGAuction.price(uint256) (src/OGAuction.sol#56-65) uses a dangerous strict equality:\n[medium/medium] reentrancy-no-eth at src/OGDistributor.sol:144: Reentrancy in OGDistributor.activate(uint256,uint8) (src/OGDistributor.sol#144-149):\n[medium/medium] reentrancy-no-eth at src/OGDistributor.sol:151: Reentrancy in OGDistributor.activateWithETH(uint256,uint8,uint160,uint256) (src/OGDistributor.sol#151-164):\n[medium/medium] reentrancy-no-eth at src/OGDistributor.sol:196: Reentrancy in OGDistributor.exit(uint256) (src/OGDistributor.sol#196-214):\n[medium/medium] uninitialized-local at src/OGHook.sol:141: OGHook.beforeSwap(address,PoolKey,SwapParams,bytes).fee (src/OGHook.sol#141) is a local variable never initialized\n[medium/medium] unused-return at src/OGHook.sol:261: OGHook.redeemFees() (src/OGHook.sol#261-272) ignores return value by poolManager.unlock(abi.encode(normal,surplus,team)) (src/OGHook.sol#270)\n[medium/medium] unused-return at src/OGDistributor.sol:166: OGDistributor.unlockCallback(bytes) (src/OGDistributor.sol#166-177) ignores return value by poolManager.settle{value: spent}() (src/OGDistributor.sol#174)\n[medium/high] write-after-write at src/OGDistributor.sol:35: OGDistributor.buying (src/OGDistributor.sol#35) is written in both\n[low/medium] missing-zero-check at src/OGAuction.sol:38: OGAuction.constructor(OG,ISpepe,address).distributor_ (src/OGAuction.sol#38) lacks a zero-check on :\n[low/medium] missing-zero-check at src/OGDistributor.sol:46: OGDistributor.constructor(OG,ISpepe,IPoolManager,address).hook_ (src/OGDistributor.sol#46) lacks a zero-check on :\n[low/medium] reentrancy-benign at src/OGDistributor.sol:151: Reentrancy in OGDistributor.activateWithETH(uint256,uint8,uint160,uint256) (src/OGDistributor.sol#151-164):\n[low/medium] reentrancy-benign at src/OGHook.sol:129: Reentrancy in OGHook.beforeSwap(address,PoolKey,SwapParams,bytes) (src/OGHook.sol#129-166):\n[low/medium] reentrancy-benign at src/OGHook.sol:240: Reentrancy in OGHook._distribute(uint256,uint256,uint256) (src/OGHook.sol#240-244):\n[low/medium] reentrancy-benign at src/OGHook.sol:274: Reentrancy in OGHook.unlockCallback(bytes) (src/OGHook.sol#274-285):\n[low/medium] reentrancy-benign at src/OGHook.sol:187: Reentrancy in OGHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/OGHook.sol#187-229):\n[low/medium] reentrancy-benign at src/OGDistributor.sol:196: Reentrancy in OGDistributor.exit(uint256) (src/OGDistributor.sol#196-214):\n[low/medium] reentrancy-benign at src/OGHook.sol:261: Reentrancy in OGHook.redeemFees() (src/OGHook.sol#261-272):\n[low/medium] reentrancy-benign at src/OGDistributor.sol:144: Reentrancy in OGDistributor.activate(uint256,uint8) (src/OGDistributor.sol#144-149):\n[low/medium] reentrancy-events at src/OGHook.sol:274: Reentrancy in OGHook.unlockCallback(bytes) (src/OGHook.sol#274-285):\n[low/medium] reentrancy-events at src/OGHook.sol:240: Reentrancy in OGHook._distribute(uint256,uint256,uint256) (src/OGHook.sol#240-244):\n[low/medium] reentrancy-events at src/OGHook.sol:246: Reentrancy in OGHook._payTeam() (src/OGHook.sol#246-253):\n[low/medium] reentrancy-events at src/OGHook.sol:187: Reentrancy in OGHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/OGHook.sol#187-229):\n[low/medium] reentrancy-events at src/OGHook.sol:187: Reentrancy in OGHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/OGHook.sol#187-229):\n[low/medium] timestamp at src/OGAuction.sol:67: OGAuction.buy(uint256,uint256,address,uint256) (src/OGAuction.sol#67-82) uses timestamp for comparisons\n[low/medium] timestamp at src/OGDistributor.sol:91: OGDistributor._checkpoint() (src/OGDistributor.sol#91-98) uses timestamp for comparisons\n[low/medium] timestamp at src/OGDistributor.sol:151: OGDistributor.activateWithETH(uint256,uint8,uint160,uint256) (src/OGDistributor.sol#151-164) uses timestamp for comparisons\n[low/medium] timestamp at src/OGHook.sol:235: OGHook._int128(uint256) (src/OGHook.sol#235-238) uses timestamp for comparisons\n[low/medium] timestamp at src/OGAuction.sol:101: OGAuction.onERC721Received(address,address,uint256,bytes) (src/OGAuction.sol#101-106) uses timestamp for comparisons\n[low/medium] timestamp at src/OGHook.sol:129: OGHook.beforeSwap(address,PoolKey,SwapParams,bytes) (src/OGHook.sol#129-166) uses timestamp for comparisons\n[low/medium] timestamp at src/OGAuction.sol:44: OGAuction.list(uint256) (src/OGAuction.sol#44-53) uses timestamp for comparisons\n[low/medium] timestamp at src/OGHook.sol:120: OGHook.decayMinutesLeft() (src/OGHook.sol#120-124) uses timestamp for comparisons\n[low/medium] timestamp at src/OGDistributor.sol:75: OGDistributor._vested() (src/OGDistributor.sol#75-79) uses timestamp for comparisons\n[low/medium] timestamp at src/OGAuction.sol:56: OGAuction.price(uint256) (src/OGAuction.sol#56-65) uses timestamp for comparisons\n[low/medium] timestamp at src/OGDistributor.sol:196: OGDistributor.exit(uint256) (src/OGDistributor.sol#196-214) uses timestamp for comparisons\n[low/medium] timestamp at src/OGHook.sol:187: OGHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/OGHook.sol#187-229) uses timestamp for comparisons\n[low/medium] timestamp at src/OGHook.sol:114: OGHook.launchFeeNow() (src/OGHook.sol#114-118) uses timestamp for comparisons\n[low/medium] timestamp at src/OGDistributor.sol:104: OGDistributor._schedule() (src/OGDistributor.sol#104-110) uses timestamp for comparisons","passed":true},{"durationMs":390,"exitCode":0,"name":"aderyn","output":"[high] eth-send-unchecked-address at src/OGHook.sol:256: ETH transferred without address checks\n[high] reentrancy-state-change at src/OGDistributor.sol:156: Reentrancy: State change after external call (11 places)\n[low] empty-require-revert at src/OGAuction.sol:79: Empty `require()` / `revert()` Statement (2 places)\n[low] internal-function-used-once at src/HookFlags.sol:23: Internal Function Used Only Once\n[low] large-numeric-literal at src/OG.sol:9: Large Numeric Literal (6 places)\n[low] literal-instead-of-constant at src/OGAuction.sol:62: Literal Instead of Constant (11 places)\n[low] missing-inheritance at src/OG.sol:5: Missing Inheritance (2 places)\n[low] require-revert-in-loop at src/OGAuction.sol:94: Loop Contains `require`/`revert`\n[low] state-change-without-event at src/OGDistributor.sol:100: State Change Without Event (4 places)\n[low] unchecked-return at src/OGHook.sol:270: Unchecked Return\n[low] unused-public-function at src/OGDistributor.sol:87: Public Function Not Used Internally (2 places)","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"883df1c6d0150dfd1c1d34edd453ef6f4484f1c3dbf3e053cf5b7b24e9cd31b6","verifiedTreeHash":"ccefb3434f346154f341f50c2a9169e4bd8ceb31","verifierVersion":"0.1.0+ad90ce4c"}]}