{"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":"ba1783a0-120c-41b3-a933-892a34a6e91c","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"f1065684e71faa86127ac39b0f186db3e29fb2cc10c1d3fe7785b737cbe80eb6","dependsOn":["manifest"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"9897597976b0e72440db7ca402d225aea20f3d37205ba53e7df2400ff80f29cc","skillId":"audit-imported-code","tools":[]},"key":"audit_imported_code","kind":"code","role":"review","skillHash":"9897597976b0e72440db7ca402d225aea20f3d37205ba53e7df2400ff80f29cc","skillId":"audit-imported-code","state":"accepted"},{"acceptedSubmissionHash":"2ce91b8ca9d0a7a7f3df6bd4d7defdd046693472e7cd2f798772f3b16be5853f","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"}],"objective":"Launch Curb (CURB) with the Uniswap v4 hook in src/CurbHook.sol from this repository with no changes to the production source unless an audit finding requires one; launch.json in the repository root is the manifest. Token: src/CurbToken.sol, name Curb, symbol CURB, 18 decimals, fixed 1,000,000,000 supply minted once to its deployer, no constructor arguments, no owner, mint, burn, tax or pause. Hook: src/CurbHook.sol (OpenZeppelin uniswap-hooks v1.3.0-rc.0 BaseHook), constructor arguments in order: $poolManager; $token; $factory (the only address allowed to initialize the pool); $owner (the CurbDesk contract that pays for this launch); then the literals 1000, 100, 300, 15, 900, 1800, 100000, true (bandTicks, edgeTicks, refWindow seconds, limitSeconds, haltSeconds, cooldownSeconds, minLiquidityE18, arbBlocks). Permissions beforeInitialize, beforeSwap, afterSwap (flags 0x20C0), CREATE2-mined. Pool fee 12500 static, tick spacing 60, paired with IMD. Only the launch factory may initialize the pool, once. The hook takes no fee of its own, returns no deltas and has no liquidity callbacks, so adding, removing and the factory's zero-liquidity fee collect are untouched. It refuses a swap that would end outside a 1000-tick band around a 5-minute time-weighted reference and further from it (a swap toward the reference always passes), and halts the pool both ways for at most 15 minutes when the price holds at the band edge for 15 seconds; the owner can only shorten a halt or pin the pre-move reference through the cooldown, never lengthen a halt or move funds. Tests: forge test passes offline (188 tests, fork tests skip without RH_RPC); IMD's univ4_hook protected suites pass via script/protected.sh; docs/VERIFICATION.md records a Robinhood fork rehearsal of this exact LaunchFactory.launch call.","parentJobId":null,"planHash":"e7dc0f4dbc98ed99b40838e11810bf8bd2ac7fdabe6f44fbab159554b7073fc0","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"ba1783a0-120c-41b3-a933-892a34a6e91c","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-2255-launch-curb-curb-uniswap"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"52240","feedbackHash":"aa5afec883d28aa1d16574dfaebcd8b1911838b461fe3b97970096aa9b3278ce","nodeKey":"audit_imported_code","submissionHash":"f1065684e71faa86127ac39b0f186db3e29fb2cc10c1d3fe7785b737cbe80eb6","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52593","feedbackHash":"5a7c844816571d6372ebfbfa94130c38653a03359a9624eed2eeb7a87cbc6a24","nodeKey":"manifest","submissionHash":"2ce91b8ca9d0a7a7f3df6bd4d7defdd046693472e7cd2f798772f3b16be5853f","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"22fb4d850e8e42d1a52795406e52f048b26206cfca01ea6f7e8b5f8c779b2ab2","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"da3c692507164bd58b1d855f556881091481421ab6f3b5a93ad29df961e607f6","device":"cbc3d81ff238201c","findings":[],"hash":"2ce91b8ca9d0a7a7f3df6bd4d7defdd046693472e7cd2f798772f3b16be5853f","nodeId":"bd5933d5-91ea-4102-a1a6-1e3fd45165c1","outcome":"completed","summary":"Fixed `launch.json`: all constructor arguments are strings, with `true` encoded as ABI word `\"1\"`. Only the manifest changed.\n\nValidation passed: `forge build`, seeded offline tests (188 passed, 2 fork tests skipped), and protected suites (13 passed in each token order).","treeHash":"0ca553346f5b69cf8863cf173dfddd50e236654b","usage":{"cachedInputTokens":5584896,"inputTokens":174401,"model":"gpt-6-astra","outputTokens":24337,"runtime":"codex","turns":19,"wallClockMs":1324298}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"b0001bc8a5c908cd","findings":[{"citation":"resolved","description":"fileIncident is permissionless and pays ORACLE_REQUEST (up to MAX_PRICE = 1 IMD) from the desk's treasury for every halt on any bound pool, including Kind.Drill pools. The only per-pool limit is one request per incident nonce. script/Mainnet.s.sol drill() binds a drill hook with band 300, edge 60, limitSeconds 10, haltSeconds 300, cooldownSeconds 300 and minLiquidityE18 1 on a DRILL/ETH pool seeded with liquidity 1e19 (moved with 0.0001 ETH swaps in script/drill.sh). A stranger can therefore halt that pool roughly every limit+halt+cooldown = 610 s for dust and file each halt. That is about 140 oracle payments a day, funded by the launch pool's LP-fee share and by fund() deposits. Once the treasury is empty, a real halt on the launch pool hits TreasuryShort and gets no verdict. Nothing in the drill path stops a stranger from triggering this.","line":260,"path":"src/CurbDesk.sol","reproduction":"State: desk deployed and funded with N*price IMD; drill hook bound with bindDrill as in script/Mainnet.s.sol drill(). Loop as an unprivileged EOA: (1) router.swap on the drill pool with ~1e14 wei into the edge zone (ref-300+60..ref-300); (2) warp 10 s, so status().phase == Halted; (3) roll >= 8 L2 blocks and call desk.fileIncident(drillHook), which pays intake.priceOf(ORACLE_REQUEST); (4) warp past halt+cooldown, swap back, repeat. Expected: drill incidents either can't spend the launch treasury or are restricted to the steward. Actual: every iteration moves one price of IMD from the desk to the Intake. After N iterations, desk.fileIncident(launchHook) during a genuine launch-pool halt reverts TreasuryShort(0, price). Verified locally with a scratch test that extends test/CurbDeskIncidents.t.sol: desk funded with 3*0.5 IMD; three times, an unprivileged `stranger` did moveTo(ref+950), warp LIMIT, roll 20, desk.fileIncident(hook), warp HALT+COOLDOWN+1. The desk's IMD balance ended at 0. The same loop runs on the drill hook with its 10 s limit, 300 s halt and 300 s cooldown.","severity":"medium","snippet":"    function fileIncident(address hook) external nonReentrant returns (bytes32 requestId) {","title":"Anyone can drain the desk treasury through the steward's drill pool: each drill halt lets any caller spend one oracle price via fileIncident"},{"citation":"resolved","description":"The Trade tape records tx.origin. CurbDesk asks the oracle for the single tx.origin with the largest summed volume, and classify() turns its share of the hook's windowVolume into a verdict: <=30% is Organic (resolve ends the halt now, and the reference resets to the mover's price), >=60% is Concentrated (the pre-move reference is pinned through the cooldown). Splitting addresses costs nothing, so the rule doesn't measure 'one actor drove the move' in either direction. (a) An attacker who pushes the price to the band edge from 4 EOAs, each with 25% of the window's volume, gets Organic, so the halt that was meant to stop them ends early and the band re-centres on their price. (b) Unrelated users whose swaps share one tx.origin (an ERC-4337 bundler, a relayer, a keeper or aggregator executor) are counted as one trader. Their organic move then reads as >=60% Concentrated, and the pin caps further moves through the 30-minute cooldown.","line":263,"path":"src/CurbHook.sol","reproduction":"Launch-pool fixture (band 1000, edge 100, limit 15). Case (a): with vm.prank(addr,addr) four distinct EOAs each swap equal paired volume moving tick 0 -> 950. Warp 15 s: halted. desk.fileIncident(hook). The oracle's honest answer is one of the four EOAs with figure = total/4, so classify(total/4, total) = (Organic, 2500), _settle calls hook.resolve(nonce, Organic), and the halt ends immediately with ref = 950. Expected: a move driven by one actor gets no early reopen. Case (b): 10 independent users' swaps relayed by one bundler EOA (same tx.origin) form 100% of the window. The answer is the bundler with figure = total, so classify gives (Concentrated, 10000) and the reference is pinned through cooldown against organic demand.","severity":"medium","snippet":"        emit Trade(tx.origin, volume);","title":"Verdicts key traders by tx.origin, so one actor can split across EOAs to get an Organic early reopen, or a shared relayer can trigger a Concentrated pin against organic flow"},{"citation":"resolved","description":"Between a halt's end and the swap that closes it, status() says it shows 'what the next swap will set'. Breaker._close sets newRef = rollRef(edgeRef, tick, band, edge) for a Concentrated verdict (clamped to band-edge-1 = 899 ticks of the tick) and pinRef(ref, tick, band) when the pool is illiquid at close. status() uses pinRef(edgeRef, lastTick, band) and lastTick respectively. Every halted tick sits at least band-edge from edgeRef, so in the Concentrated case the two always differ. status().lower/upper, which CurbRouter users and frontends size orders by, are wrong at exactly the moment the pool reopens.","line":160,"path":"src/CurbHook.sol","reproduction":"Concentrated case: edgeRef = 0, lastTick = 950, band 1000, edge 100, halt over but not yet closed. status() returns ref = clamp(0,-50,1950) = 0 and upper = 1000. The next swap's _close sets ref = clamp(0, 51, 1849) = 51, so the actual upper is 1051. Illiquid close: ref = 0, lastTick = 950, getLiquidity < MIN_LIQUIDITY. status() returns ref = 950 (band 0..1950), and _close sets ref = pinRef(0,950,1000) = 0 (band -1000..1000). Expected: status() equals the HaltClosed.newRef that follows. Verified locally: in the CurbDeskIncidents fixture, after _fileFunded() and a 100% share (Concentrated) delivery, warp HALT. status() returned ref 0 / upper 1000; after the next swap closed the incident, status() returned ref 51 / upper 1051.","severity":"low","snippet":"            s.ref = pin ? BandMath.pinRef(breaker.edgeRef, breaker.lastTick, c.band) : breaker.lastTick;","title":"status() reports a different post-halt reference and band than the next swap actually installs"},{"citation":"resolved","description":"The desk is the launch's requester, so LaunchFactory.claimFees (callable by anyone, and called by fileIncident) pays it 80% of the pool's LP fees in both currencies, CURB and IMD. CurbDesk has no transfer path for any token: IMD only leaves through forceApprove + Intake requests, and CURB has none at all. The CURB half of every claimed fee, and any IMD left after renounce(), is stranded permanently. The requester may intend 'cannot withdraw', but the CURB share can't even be spent on IMD work, so in practice the desk captures the IMD side and burns the CURB side.","line":271,"path":"src/CurbDesk.sol","reproduction":"After launch and bind, a buyer swaps IMD->CURB and a seller swaps CURB->IMD. Anyone calls factory.claimFees(launchNumber). The desk receives a CURB amount > 0. Search CurbDesk for any call that moves IERC20(curb): there are none, so curb.balanceOf(desk) only ever grows. Expected: the requester's CURB fee share has a defined use or recipient (e.g. sold for IMD or forwarded). Actual: it is unrecoverable.","severity":"low","snippet":"            try factory.claimFees(pool.launchNumber) {} catch {}","title":"The desk's requester share of LP fees in CURB is locked forever: nothing in CurbDesk can move any token except IMD to the Intake"}],"hash":"f1065684e71faa86127ac39b0f186db3e29fb2cc10c1d3fe7785b737cbe80eb6","nodeId":"afa2e66c-e67e-408b-b756-c3a46deb4e05","outcome":"completed","summary":"I found two medium and two low findings, and wrote them to `.imd-findings.json` with a coverage row for each of the 34 entry points. Nothing qualified as critical or high, so no finding carries a proof file. The two I could check in code I confirmed with throwaway tests, which I then deleted, so the tree is unchanged.\n\n**Findings**\n1. **Medium: anyone can drain the desk's IMD treasury** (`src/CurbDesk.sol:260`). `fileIncident` can be called by anyone, and each halt on any bound pool spends one oracle price from the treasury. That includes the drill pool, which halts cheaply: on-chain liquidity of 1e19, test-sized trades, a 10 s limit, 300 s halt and 300 s cooldown. So a stranger can force a payment about every 610 s, around 140 a day. Once the treasury is empty, a real halt on the launch pool fails with `TreasuryShort` and gets no verdict. In my test a stranger repeated halt → file three times and the desk's balance went from 1.5 IMD to 0.\n2. **Medium: the verdict rule can be gamed** (`src/CurbHook.sol:263`). The trade record names each trader by `tx.origin`. One actor who splits a move across four wallets at 25% each gets \"Organic\", so the halt ends early and the band re-centres on their price. In the other direction, many users relayed through one bundler count as a single trader and get \"Concentrated\", which pins the band against normal buying for the 30-minute cooldown. I didn't test this one: it follows directly from how volume shares map to verdicts.\n3. **Low: `status()` shows the wrong band after a halt** (`src/CurbHook.sol:160`). It uses a different clamp from the code that actually closes the halt. Confirmed in a test: `status()` showed reference 0 and upper limit 1000, and after the closing swap they were 51 and 1051.\n4. **Low: the desk's CURB share of LP fees is locked forever** (`src/CurbDesk.sol:271`). The desk receives 80% of pool fees in both tokens, but has no way to move CURB at all; IMD can only go to the Intake. Untested; it's visible from the absence of any transfer path.\n\n**What I read**\n- **In full:** `CurbHook`, `CurbToken`, `CurbDesk`, `HookFlags`, the `Breaker`, `BandMath` and `L2Block` libraries, `OracleAttestation`, `ILaunchFactory`, `CurbRouter`, `DrillToken`, the drill parameters in `script/Mainnet.s.sol`, and `launch.json`.\n- **Skimmed only:** `OracleQuestion.sol`, `ICurbHook`, `IIntake`, and the vendored OpenZeppelin `BaseHook`, which I took to be the library's v1.3.0-rc.0 release.\n- **Not reachable:** the deployed IMD LaunchFactory, Intake and oracle service. I judged their behaviour from the interfaces only.\n\n**Checks that came out clean**\n- **Manifest:** the 12 constructor arguments are in the right order, permissions match flags `0x20C0`, and fee 12500 / tick spacing 60 match what `beforeInitialize` accepts.\n- **Token:** it matches the brief, with no owner, mint, burn, tax or pause.\n- **Forbidden patterns:** nothing in `src` uses DELEGATECALL or SELFDESTRUCT, and there are no proxies or initializers.\n- **Owner powers:** the owner can only shorten a halt or pin the reference; it cannot lengthen a halt.\n\n**Not checked**\n- **`arbBlocks` is written as `\"1\"`** in `launch.json`, where the brief says `true`. The manifest schema doesn't say how a bool is written, so I left this as a note, not a finding.\n- **Full test runs:** I didn't run `forge test` across the whole repository or `script/protected.sh`. When I ran my scratch tests, the existing 36 desk incident tests passed alongside them.","treeHash":null,"usage":{"cachedInputTokens":1865172,"inputTokens":44,"model":"claude-opus-5-5","outputTokens":30259,"runtime":"claude","turns":22,"wallClockMs":670728}}],"verification":[{"checks":[{"durationMs":76956,"exitCode":0,"name":"build","output":"Compiling 143 files with Solc 0.8.26\nSolc 0.8.26 finished in 76.84s\nCompiler run successful with warnings:\nWarning (5667): Unused function parameter. Remove or comment out the variable name to silence this warning.\n  --> test/CurbHook.t.sol:57:25:\n   |\n57 |     function _initFresh(uint256 seed, PoolKey memory k, address as_) internal returns (bytes memory) {\n   |                         ^^^^^^^^^^^^\n\nWarning (2018): Function state mutability can be restricted to view\n   --> test/protected/Owners.protected.t.sol:127:5:\n    |\n127 |     function test_theHookIsNotOwnedByTheFactoryOrIMD() public {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\n","passed":true},{"durationMs":1367,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/Scaffold.t.sol:ScaffoldTest\n[PASS] test_toolchain() (gas: 7791)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 244.68µs (40.56µs CPU time)\n\nRan 2 tests for test/fork/LaunchRehearsal.t.sol:LaunchRehearsalTest\n[SKIP] test_rehearsal_curbAboveImd() (gas: 0)\n[SKIP] test_rehearsal_curbBelowImd() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 2 skipped; finished in 470.49µs (131.31µs CPU time)\n\nRan 1 test for test/oracle/OracleQuestion.t.sol:OracleQuestionTest\n[PASS] test_protocolVectorHash() (gas: 37038)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 247.26µs (99.84µs CPU time)\n\nRan 1 test for test/CurbHook.t.sol:CurbHookNativePairTest\n[PASS] test_nativePair_tapeCountsEth() (gas: 210850)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.37ms (284.43µs CPU time)\n\nRan 3 tests for test/oracle/DeskConformance.t.sol:DeskConformanceTest\n[PASS] test_acceptsAFreshSignatureFromTheVectorKey() (gas: 207653)\n[PASS] test_callbackSelectorIsCanonical() (gas: 696)\n[PASS] test_digestMatchesTheProtocol() (gas: 10300)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 4.34ms (3.64ms CPU time)\n\nRan 1 test for test/HookGas.t.sol:HookGasTest\n[PASS] test_swapOverhead() (gas: 370831)\nLogs:\n  swap with CurbHook 204767\n  swap without hook  137992\n  overhead           66775\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 5.41ms (659.93µs CPU time)\n\nRan 3 tests for test/oracle/RealAttestation.t.sol:RealAttestationTest\n[PASS] test_otherConsumerFails() (gas: 70587)\n[PASS] test_realSignatureFromLiveOracle() (gas: 18729)\n[PASS] test_tamperedFigureFails() (gas: 21693)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 7.54ms (11.17ms CPU time)\n\nRan 8 tests for test/CurbRouter.t.sol:CurbRouterTest\n[PASS] test_addLiquidity() (gas: 256252)\n[PASS] test_drillToken() (gas: 30808)\n[PASS] test_refusedSwap_needsNoBalance() (gas: 227523)\n[PASS] test_simulate_bubblesOutsideBand() (gas: 118013)\n[PASS] test_simulate_returnsDeltas() (gas: 188980)\n[PASS] test_swap_bothDirections_erc20() (gas: 397374)\n[PASS] test_swap_native_refundsExcessEth() (gas: 767890)\n[PASS] test_unlockCallback_onlyManager() (gas: 32429)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 7.96ms (4.59ms CPU time)\n\nRan 34 tests for test/CurbHook.t.sol:CurbHookCurbIsCurrency1Test\n[PASS] test_band_exactOutputPastBand_refused() (gas: 236603)\n[PASS] test_band_insideAndTowardReference_pass() (gas: 671864)\n[PASS] test_band_maxLimitSell_refused() (gas: 242501)\n[PASS] test_band_refusesPastLower() (gas: 159604)\n[PASS] test_band_refusesPastUpper_withWrappedOutsideBand() (gas: 154554)\n[PASS] test_callbacks_refuseNonPoolManager() (gas: 92516)\n[PASS] test_closeIlliquid_keepsReference() (gas: 1498644)\n[PASS] test_constructor_refusesBadParams() (gas: 115040)\n[PASS] test_dustBelowMinimum_isNotLiquidity() (gas: 1141579)\n[PASS] test_haltClosed_emittedOnFirstSwapAfter() (gas: 490024)\n[PASS] test_halted_swapRevertsWrapped() (gas: 352511)\n[PASS] test_incidentWindow_usesArbSysBlocks() (gas: 13031)\n[PASS] test_init_acceptsInitializerOnLaunchKey() (gas: 42599)\n[PASS] test_init_refusesDynamicFee() (gas: 104850)\n[PASS] test_init_refusesKeyWithoutToken() (gas: 840190)\n[PASS] test_init_refusesOtherSender() (gas: 104521)\n[PASS] test_init_refusesSecondPool() (gas: 781968)\n[PASS] test_init_refusesWrongFee() (gas: 105310)\n[PASS] test_init_refusesWrongSpacing() (gas: 105042)\n[PASS] test_l2Block_fallsBackWithoutArbSys() (gas: 290386)\n[PASS] test_l2Block_forkedArbSysCostsBoundedGas() (gas: 256418)\n[PASS] test_noForbiddenOpcodes() (gas: 3154216)\n[PASS] test_params() (gas: 11552)\n[PASS] test_permissions_are_0x20C0() (gas: 9080)\n[PASS] test_resolve_onlyOwner() (gas: 584168)\n[PASS] test_runtimeSize_under_24576() (gas: 5626)\n[PASS] test_status_phases() (gas: 360982)\n[PASS] test_trade_emitsOriginAndPairedVolume_exactIn() (gas: 558350)\n[PASS] test_trade_exactOut_countsPairedSide() (gas: 248597)\n[PASS] test_voidStart_stillCapsMovesWithinTheVoid() (gas: 876884)\n[PASS] test_voidStart_strandedReferenceIsEscapable() (gas: 2357740)\n[PASS] test_volume_sameBlockRoll() (gas: 668826)\n[PASS] test_zeroLiquidity_freePushCannotHalt() (gas: 873549)\n[PASS] test_zeroLiquidity_freePushCannotWalkReference() (gas: 1071433)\nSuite result: ok. 34 passed; 0 failed; 0 skipped; finished in 32.26ms (21.67ms CPU time)\n\nRan 26 tests for test/Breaker.t.sol:BreakerTest\n[PASS] testFuzz_resolve_neverExtends(uint64,bool) (runs: 512, μ: 135210, ~: 125193)\n[PASS] test_closeIlliquid_keepsReference() (gas: 165745)\n[PASS] test_cooldown_fromScheduledEnd_afterOrganic() (gas: 181721)\n[PASS] test_edgeEntry_startsClock() (gas: 88510)\n[PASS] test_edgeExitIntoVoid_clearsClock() (gas: 178211)\n[PASS] test_edgeExit_clearsClock() (gas: 132522)\n[PASS] test_halt_endsAtMax_thenCloses_recenters() (gas: 127653)\n[PASS] test_halt_startsAfterLimitSeconds() (gas: 125632)\n[PASS] test_limit_staysWhileInEdge() (gas: 124429)\n[PASS] test_nextHaltSpacing_atLeast_halt_plus_cooldown_plus_limit() (gas: 202352)\n[PASS] test_phase_pendingClose_reportsCooldownThenOpen() (gas: 109766)\n[PASS] test_pin_blocksRolls_untilCooldownEnd_thenRollUsesPostHaltSamplesOnly() (gas: 362321)\n[PASS] test_pin_keepsReferenceFromLimitEntry() (gas: 274270)\n[PASS] test_pin_leavesEdgeRoom_afterDump() (gas: 206462)\n[PASS] test_pin_suspendsEdgeClock() (gas: 205225)\n[PASS] test_refusedSwap_changesNothing() (gas: 72849)\n[PASS] test_resolveConcentrated_fullHalt_pinsEdgeRef() (gas: 293973)\n[PASS] test_resolveOrganic_reopensNow_recenters() (gas: 182712)\n[PASS] test_resolve_refusals() (gas: 282593)\n[PASS] test_roll_clearsLimit() (gas: 122563)\n[PASS] test_roll_followsTwap() (gas: 98452)\n[PASS] test_silentHalt_closesOnFirstSwapAfterEnd() (gas: 117541)\n[PASS] test_voidStart_admittedFromBoundary() (gas: 122731)\n[PASS] test_voidStart_boundaryTooFar() (gas: 109716)\n[PASS] test_voidStart_notWhenStartedLiquid() (gas: 48721)\n[PASS] test_zeroLiquidity_noRoll_noEdgeClock() (gas: 178279)\nSuite result: ok. 26 passed; 0 failed; 0 skipped; finished in 32.87ms (27.52ms CPU time)\n\nRan 34 tests for test/CurbHook.t.sol:CurbHookCurbIsCurrency0Test\n[PASS] test_band_exactOutputPastBand_refused() (gas: 236603)\n[PASS] test_band_insideAndTowardReference_pass() (gas: 671924)\n[PASS] test_band_maxLimitSell_refused() (gas: 242501)\n[PASS] test_band_refusesPastLower() (gas: 159619)\n[PASS] test_band_refusesPastUpper_withWrappedOutsideBand() (gas: 154563)\n[PASS] test_callbacks_refuseNonPoolManager() (gas: 92516)\n[PASS] test_closeIlliquid_keepsReference() (gas: 1498543)\n[PASS] test_constructor_refusesBadParams() (gas: 115088)\n[PASS] test_dustBelowMinimum_isNotLiquidity() (gas: 1164204)\n[PASS] test_haltClosed_emittedOnFirstSwapAfter() (gas: 490052)\n[PASS] test_halted_swapRevertsWrapped() (gas: 352543)\n[PASS] test_incidentWindow_usesArbSysBlocks() (gas: 13031)\n[PASS] test_init_acceptsInitializerOnLaunchKey() (gas: 42608)\n[PASS] test_init_refusesDynamicFee() (gas: 104724)\n[PASS] test_init_refusesKeyWithoutToken() (gas: 840181)\n[PASS] test_init_refusesOtherSender() (gas: 104512)\n[PASS] test_init_refusesSecondPool() (gas: 781968)\n[PASS] test_init_refusesWrongFee() (gas: 105184)\n[PASS] test_init_refusesWrongSpacing() (gas: 104916)\n[PASS] test_l2Block_fallsBackWithoutArbSys() (gas: 290247)\n[PASS] test_l2Block_forkedArbSysCostsBoundedGas() (gas: 256450)\n[PASS] test_noForbiddenOpcodes() (gas: 3154216)\n[PASS] test_params() (gas: 11552)\n[PASS] test_permissions_are_0x20C0() (gas: 9080)\n[PASS] test_resolve_onlyOwner() (gas: 584196)\n[PASS] test_runtimeSize_under_24576() (gas: 5626)\n[PASS] test_status_phases() (gas: 361014)\n[PASS] test_trade_emitsOriginAndPairedVolume_exactIn() (gas: 558511)\n[PASS] test_trade_exactOut_countsPairedSide() (gas: 248581)\n[PASS] test_voidStart_stillCapsMovesWithinTheVoid() (gas: 876759)\n[PASS] test_voidStart_strandedReferenceIsEscapable() (gas: 2357789)\n[PASS] test_volume_sameBlockRoll() (gas: 668922)\n[PASS] test_zeroLiquidity_freePushCannotHalt() (gas: 873438)\n[PASS] test_zeroLiquidity_freePushCannotWalkReference() (gas: 1071322)\nSuite result: ok. 34 passed; 0 failed; 0 skipped; finished in 32.90ms (30.86ms CPU time)\n\nRan 4 tests for test/CurbToken.t.sol:CurbTokenTest\n[PASS] testFuzz_transferIsExact(address,uint256) (runs: 512, μ: 77988, ~: 78343)\n[PASS] test_metadata() (gas: 24615)\n[PASS] test_mintsWholeSupplyToDeployer() (gas: 15343)\n[PASS] test_noMintSelector() (gas: 57612)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 37.65ms (36.36ms CPU time)\n\nRan 20 tests for test/CurbDesk.t.sol:CurbDeskTest\n[PASS] testFuzz_noTokenLeavesExceptIntakePrice(uint256,address) (runs: 512, μ: 762564, ~: 633408)\n[PASS] test_bindDrill_stewardOnly_ownerCheck() (gas: 490622)\n[PASS] test_bind_once() (gas: 691395)\n[PASS] test_bind_onlySteward() (gas: 289892)\n[PASS] test_bind_requiresRequesterAndOwner() (gas: 871160)\n[PASS] test_bind_unknownLaunch() (gas: 55025)\n[PASS] test_fund() (gas: 190897)\n[PASS] test_intakeIsImmutable() (gas: 8258)\n[PASS] test_launchFailure_recorded() (gas: 468122)\n[PASS] test_launch_onlySteward() (gas: 114179)\n[PASS] test_launch_paysExactPrice_viaRequestWithFailure() (gas: 450046)\n[PASS] test_launch_priceAboveCapRefused() (gas: 155066)\n[PASS] test_launch_refusedAfterBind() (gas: 501584)\n[PASS] test_launch_treasuryShort() (gas: 127825)\n[PASS] test_onResult_onlyIntake() (gas: 36205)\n[PASS] test_onResult_recordsLaunchResult() (gas: 571599)\n[PASS] test_renounce_disablesSteward() (gas: 151086)\n[PASS] test_steward_onlyStewardProposes() (gas: 32766)\n[PASS] test_timelock_executeBefore48hReverts_afterWorks() (gas: 140428)\n[PASS] test_timelock_nothingProposed() (gas: 38150)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 37.82ms (37.46ms CPU time)\n\nRan 14 tests for test/BandMath.t.sol:BandMathTest\n[PASS] testFuzz_pinRef_keepsTickInBand(int24,int24,int24) (runs: 512, μ: 2550, ~: 2641)\n[PASS] testFuzz_refused_neverTowardReference(int24,int24,int24,int24) (runs: 512, μ: 3328, ~: 3179)\n[PASS] testFuzz_rollRef_keepsTickInsideBandOutsideEdge(int24,int24,int24,int24) (runs: 512, μ: 4004, ~: 3858)\n[PASS] test_clamp() (gas: 687)\n[PASS] test_dist() (gas: 792)\n[PASS] test_inEdge() (gas: 1239)\n[PASS] test_limits_saturateAtTickBounds() (gas: 1001)\n[PASS] test_refused_insideBand_passes() (gas: 1640)\n[PASS] test_refused_outsideAndFurther() (gas: 2297)\n[PASS] test_refused_outsideButCloser_passes() (gas: 1335)\n[PASS] test_rollRef_clamps() (gas: 1774)\n[PASS] test_twap_idleWindowUsesLastTick() (gas: 801)\n[PASS] test_twap_lastSecondPushBarelyMoves() (gas: 1143)\n[PASS] test_twap_negativeFloors() (gas: 1136)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 37.85ms (105.19ms CPU time)\n\nRan 36 tests for test/CurbDeskIncidents.t.sol:CurbDeskIncidentsTest\n[PASS] test_answer_forOldNonce_neverTouchesNewIncident() (gas: 2397221)\n[PASS] test_answer_lateAfterHaltClosed_recordedNotApplied() (gas: 1961337)\n[PASS] test_answer_pushAfterCallback_refused() (gas: 1778435)\n[PASS] test_callback_fitsIn200k() (gas: 1722520)\n[PASS] test_classify_totalZero_inconclusive() (gas: 7004)\n[PASS] test_classify_zeroFigure_inconclusive() (gas: 6914)\n[PASS] test_failure_marksFailed_noRefile() (gas: 1727868)\n[PASS] test_file_bodyGolden() (gas: 171344)\n[PASS] test_file_claimRevertDoesNotBlockFiling() (gas: 1538916)\n[PASS] test_file_launchPoolSweepsFees_tryCatch() (gas: 1576836)\n[PASS] test_file_oncePerNonce() (gas: 1601329)\n[PASS] test_file_priceAboveCapRefused() (gas: 667698)\n[PASS] test_file_reentryFromFeeClaimFilesOnce() (gas: 1583108)\n[PASS] test_file_requestShape() (gas: 1755743)\n[PASS] test_file_requiresHalted() (gas: 115286)\n[PASS] test_file_treasuryShort_exactArgs() (gas: 639946)\n[PASS] test_file_unknownPool() (gas: 38269)\n[PASS] test_file_windowTooFresh() (gas: 619476)\n[PASS] test_postMortem_bodyAndResult() (gas: 4093392)\n[PASS] test_postMortem_needsTwoPrices() (gas: 1824190)\n[PASS] test_postMortem_requiresAnswer() (gas: 1576966)\n[PASS] test_question_isCanonical() (gas: 21504)\n[PASS] test_settle_badSignature() (gas: 1599803)\n[PASS] test_settle_boundary_3000Organic() (gas: 1760742)\n[PASS] test_settle_boundary_3001Inconclusive() (gas: 1746336)\n[PASS] test_settle_boundary_5999Inconclusive() (gas: 1722819)\n[PASS] test_settle_boundary_6000Concentrated() (gas: 1764630)\n[PASS] test_settle_expired() (gas: 1589001)\n[PASS] test_settle_figureAboveTotal_inconclusive() (gas: 1722809)\n[PASS] test_settle_listLengthNotOne_inconclusive() (gas: 1724155)\n[PASS] test_settle_organic_resolvesOrganic() (gas: 1772277)\n[PASS] test_settle_unknownRequest() (gas: 1582683)\n[PASS] test_settle_weakPanel() (gas: 1636000)\n[PASS] test_settle_wrongQuestion() (gas: 1582957)\n[PASS] test_settle_wrongSender() (gas: 1577811)\n[PASS] test_submitAttestation_anyoneCanPush() (gas: 1685300)\nSuite result: ok. 36 passed; 0 failed; 0 skipped; finished in 749.76ms (51.56ms CPU time)\n\nRan 2 tests for test/invariant/CurbHookInvariants.t.sol:CurbHookInvariants\n[PASS]\nCurbHookInvariants invariants:\n[PASS] invariant_1_haltNeverLongerThanHaltSeconds\n[PASS] invariant_2_haltStartsSpaced\n[PASS] invariant_3_resolveNeverExtends\n[PASS] invariant_4_liveness_noHookRevertOnTowardOrInBandOutsideHalt\n[PASS] invariant_5_priceAlwaysInsideBand\n[PASS] invariant_6_collectAlwaysSucceeds\n[PASS] invariant_7_onlyPoolManager\n[PASS] invariant_8_totalVolumeEqualsTradeSum\n CurbHookInvariants invariants (runs: 64, calls: 4096, reverts: 502)\n\n╭-------------+---------------+-------+---------+----------╮\n| Contract    | Selector      | Calls | Reverts | Discards |\n+==========================================================+\n| HookHandler | approve       | 502   | 502     | 0        |\n|-------------+---------------+-------+---------+----------|\n| HookHandler | collect       | 505   | 0       | 0        |\n|-------------+---------------+-------+---------+----------|\n| HookHandler | pressEdge     | 554   | 0       | 0        |\n|-------------+---------------+-------+---------+----------|\n| HookHandler | resolve       | 542   | 0       | 0        |\n|-------------+---------------+-------+---------+----------|\n| HookHandler | strayCallback | 471   | 0       | 0        |\n|-------------+---------------+-------+---------+----------|\n| HookHandler | swap          | 497   | 0       | 0        |\n|-------------+---------------+-------+---------+----------|\n| HookHandler | waitAndSwap   | 511   | 0       | 0        |\n|-------------+---------------+-------+---------+----------|\n| HookHandler | warp          | 514   | 0       | 0        |\n╰-------------+---------------+-------+---------+----------╯\n\nLogs:\n  swaps 16 refusals 9 halted reverts 0\n  halts closed 1 verdicts applied 0\n\n[PASS] test_soak_longRandomWalk() (gas: 535628529)\nLogs:\n  soak: swaps 1130 refusals 478 halted reverts 260\n  soak: halts closed 150 verdicts applied 47\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 1.20s (1.94s CPU time)\n\nRan 16 test suites in 1.21s (2.19s CPU time): 188 tests passed, 0 failed, 2 skipped (190 total tests)\n","passed":true},{"durationMs":71,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"CurbDesk.bind(uint64)\",\"CurbDesk.bindDrill(address)\",\"CurbDesk.commissionPostMortem(address,uint32)\",\"CurbDesk.executeOracleSigner()\",\"CurbDesk.fileIncident(address)\",\"CurbDesk.fund(uint256)\",\"CurbDesk.launch(bytes)\",\"CurbDesk.onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"CurbDesk.onRequestFailure(bytes32,uint8,bytes32,uint16,uint16,bytes)\",\"CurbDesk.onResult(bytes32,bytes32,string)\",\"CurbDesk.proposeOracleSigner(address)\",\"CurbDesk.renounce()\",\"CurbDesk.submitAttestation(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"CurbHook.afterAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"CurbHook.afterDonate(address,(address,address,uint24,int24,address),uint256,uint256,bytes)\",\"CurbHook.afterInitialize(address,(address,address,uint24,int24,address),uint160,int24)\",\"CurbHook.afterRemoveLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"CurbHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"CurbHook.beforeAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"CurbHook.beforeDonate(address,(address,address,uint24,int24,address),uint256,uint256,bytes)\",\"CurbHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"CurbHook.beforeRemoveLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"CurbHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"CurbHook.resolve(uint32,uint8)\",\"CurbRouter.addLiquidity((address,address,uint24,int24,address),int24,int24,uint128)\",\"CurbRouter.simulate((address,address,uint24,int24,address),bool,int256,uint160)\",\"CurbRouter.swap((address,address,uint24,int24,address),bool,int256,uint160)\",\"CurbRouter.unlockCallback(bytes)\",\"CurbToken.approve(address,uint256)\",\"CurbToken.transfer(address,uint256)\",\"CurbToken.transferFrom(address,address,uint256)\",\"DrillToken.approve(address,uint256)\",\"DrillToken.transfer(address,uint256)\",\"DrillToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitattributes\":1,\".gitignore\":11,\"FAILURE-MODES.md\":189,\"LICENSE\":21,\"README.md\":110,\"SECURITY.md\":112,\"docs/GAS.md\":49,\"docs/VERIFICATION.md\":108,\"foundry.toml\":42,\"launch.json\":38,\"remappings.txt\":6,\"script/Mainnet.s.sol\":141,\"script/drill.sh\":98,\"script/protected.sh\":47,\"src/CurbDesk.sol\":558,\"src/CurbHook.sol\":311,\"src/CurbToken.sol\":14,\"src/HookFlags.sol\":45,\"src/interfaces/ICurbHook.sol\":75,\"src/interfaces/IIntake.sol\":29,\"src/interfaces/ILaunchFactory.sol\":16,\"src/libraries/BandMath.sol\":79,\"src/libraries/Breaker.sol\":281,\"src/libraries/L2Block.sol\":26,\"src/oracle/OracleAttestation.sol\":221,\"src/oracle/OracleQuestion.sol\":255,\"src/tools/CurbRouter.sol\":134,\"src/tools/DrillToken.sol\":13,\"test/BandMath.t.sol\":103,\"test/Breaker.t.sol\":308,\"test/CurbDesk.t.sol\":296,\"test/CurbDeskIncidents.t.sol\":474,\"test/CurbHook.t.sol\":500,\"test/CurbRouter.t.sol\":125,\"test/CurbToken.t.sol\":46,\"test/HookGas.t.sol\":54,\"test/Scaffold.t.sol\":17,\"test/fixtures/kept-launch-input.hex\":1,\"test/fixtures/oracle_attestation_sample.json\":1,\"test/fork/LaunchRehearsal.t.sol\":306,\"test/fork/imd/LaunchTypes.sol\":64,\"test/invariant/CurbHookInvariants.t.sol\":101,\"test/invariant/HookHandler.sol\":269,\"test/oracle/DeskConformance.t.sol\":107,\"test/oracle/OracleQuestion.t.sol\":24,\"test/oracle/RealAttestation.t.sol\":70,\"test/protected/Hook.protected.t.sol\":293,\"test/protected/Owners.protected.t.sol\":209,\"test/protected/README.md\":9,\"test/protected/Token.protected.t.sol\":189,\"test/protected/support/MockERC20.sol\":11,\"test/protected/support/OwnerChecks.sol\":19,\"test/protected/support/Swapper.sol\":51,\"test/utils/BreakerHarness.sol\":69,\"test/utils/CurbFixture.sol\":165,\"test/utils/MockArbSys.sol\":12,\"test/utils/MockIntake.sol\":89,\"test/utils/MockLaunchFactory.sol\":61},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"2ce91b8ca9d0a7a7f3df6bd4d7defdd046693472e7cd2f798772f3b16be5853f","verifiedTreeHash":"0ca553346f5b69cf8863cf173dfddd50e236654b","verifierVersion":"0.1.0+6a374fcd"}]}