{"assessments":[],"deployments":[],"fuzz":[],"identity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"interpretation":"Records acceptance and evidence. Neither completion nor an AI assessment establishes correctness, safety, or independent review.","jobId":"9df471c0-b9f9-474e-b2e1-1aa86c7f7412","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"3088583369882903a3facea6db4ea6ac316237e3802d23db95f276a89af21109","dependsOn":["build_contract_project","manifest"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"c26edc76dc7a76e09a42c3634054429c1679c6e247747d647a03f77e5b332d7e","skillId":"adversarial-review","tools":[]},"key":"adversarial_review","kind":"code","role":"review","skillHash":"c26edc76dc7a76e09a42c3634054429c1679c6e247747d647a03f77e5b332d7e","skillId":"adversarial-review","state":"accepted"},{"acceptedSubmissionHash":"55d68e99a6e3fc4f734560f92bbe40daa7da4de077dfffeb1ab9566e8a961998","dependsOn":[],"execution":{"mustProduce":["src/LaunchToken.sol"],"network":false,"profile":"foundry","requires":[],"skillHash":"47381b166d1f406a34f0ebdc740ee21bc0383e56e7ad9084b26abf1bf7570904","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"47381b166d1f406a34f0ebdc740ee21bc0383e56e7ad9084b26abf1bf7570904","skillId":"build-contract-project","state":"accepted"},{"acceptedSubmissionHash":"0eee1dc80119e4b09534e658969de826e48ecbb1340cd0b6ce05c751afbbefcb","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"}],"objective":"pleasr build a contract that lets users deposit any token which zaps into wbtc, deposits into fx protocol (fx.aladdin.club) using their fxmint feature, then borrow 50% ltv, swap the $fxusd into $OHM, wrap thr $ohm to $gohm, put the $gohm into cooler loans which is $ohms built in credit facility and buy more wbtc to put into fx protocol. the user should be left with a 33% ltv on fx. the user can then deposit more money at anytime which runs the loop again. the user would get a receipt back in their wallet representing the deposited capital. there needs to be a way to unwind and get capital back out and should be a website to manage all of this.\n\nWho can call what: contracts should be immutable\nUpgrades and pausing: not upgradable","parentJobId":null,"planHash":"1d49867e9580ab7478e028dc2c221a35b5baaa3c26d47da615977076ddbbaa87","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"9df471c0-b9f9-474e-b2e1-1aa86c7f7412","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-409-pleasr-build-contract-lets"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"50971","feedbackHash":"50ac56decda87418f5a7646fd3c407dcd0c55305c8eba7f76e3c796b7bb34d7e","nodeKey":"adversarial_review","submissionHash":"bfb43807044aa82c0d9a70354aed855f8be28809d57953e074021c0f309b2a54","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"50959","feedbackHash":"2b6199c3740ceaa41d30bd9e77d2d2f0ddbe297b5dcd2012928a514c1d60a8ae","nodeKey":"adversarial_review","submissionHash":"3088583369882903a3facea6db4ea6ac316237e3802d23db95f276a89af21109","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"50971","feedbackHash":"0cadecb35fa38d0229b6585ba101c2fc40e3c8ecba4fa04a9b06c82f00cb0dae","nodeKey":"build_contract_project","submissionHash":"55d68e99a6e3fc4f734560f92bbe40daa7da4de077dfffeb1ab9566e8a961998","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"50904","feedbackHash":"3451027f2caaf56a896174ab74bfaa1b95a5c45d495e4f1bfc27d903beeb0b6d","nodeKey":"build_contract_project","submissionHash":"83c690683a1962a2418ed9eef668957a4e0d0af0a1bf3a9e4be5a09489e34de5","tag1":"verification:checks","tag2":"acceptance-v2","value":0},{"agentId":"50971","feedbackHash":"69e3d1b46463a6529f0f1e04ed1a8a8b4505a5c25bc588575e6792d957731955","nodeKey":"manifest","submissionHash":"0eee1dc80119e4b09534e658969de826e48ecbb1340cd0b6ce05c751afbbefcb","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"50904","feedbackHash":"80e511edd569273442920e5c6d7f38921ec638306800faa45ef9a0cb3fed69a3","nodeKey":"manifest","submissionHash":"e598a3bed7f1e5b956b54b71cd9b0b5a7ac76bf4ce5c411a39b2853a07789a16","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"a5602ad2bbf8c3d7b0f7e79f39f6eb028c97301538d8350b91e22b9167c9eadc","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"135fb4f9b857003f15b3474a30e01b5896ea62b759eb023c42e7cf053801dad4","device":"35c52a5b502e847c","findings":[],"hash":"0eee1dc80119e4b09534e658969de826e48ecbb1340cd0b6ce05c751afbbefcb","nodeId":"ee77781b-b466-4e3a-9199-dc0a5e9722b2","outcome":"completed","summary":"Updated only `launch.json`, correcting the notes for Morpho flash-funded deposits and the f(x) transaction lock. Existing contract order and constructor arguments remain unchanged.\n\nValidation passed: JSON schema, compiled constructor ABIs, `forge build`, and `forge test`—56 passed, 0 failed. Live dependency compatibility remains unverified.","treeHash":"d017ae653c3e53f8b4ba14382792c82862ea00d3","usage":{"cachedInputTokens":316800,"inputTokens":43059,"model":"gpt-6-astra","outputTokens":3850,"runtime":"codex","turns":3,"wallClockMs":142828}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"468e82a89b9bfe18","findings":[{"description":"Confirmed fixed. deposit() now performs exactly one PoolManager.operate per transaction: it flash-borrows coolerBorrow USDS from Morpho (line 155), buys the reinvestment WBTC first (line 176), supplies capital + reinvestment + top-up while borrowing fxUSD in a single _openFx/_operate (lines 177, 200), and repays Morpho from the later Cooler disbursement (lines 189-191, 292, 305). No other _operate call exists on the deposit path; close(), addCollateral() and repayFx() each make one. The 49-50% initial-borrow check is applied to the initial capital's pro rata share of credited collateral (line 204) and the whole-position 33% cap is re-checked under both price views (line 158). Live checks at Ethereum block 26070440: pool 0xab709e26fa6b0a30c119d8c55b887ded24952473 getDebtRatioRange() = (1e14, 8.55e17) so a 33% position is admissible; WBTC scaling factor = 1e28; Morpho Blue 0xbbbb...ffcb holds 923264.36 USDS; MonoCooler debtToken is USDS and its CoolerTreasuryBorrower disburses via SUSDS.withdraw(amountInWad, recipient, ...), so the exact-delta check at line 191 is satisfied by the real protocol.","line":177,"path":"src/LoopPosition.sol","reproduction":"Re-ran forge build --offline, forge test --offline (56 passed), forge fmt --check, and forge test --isolate for testDepositWithTransactionWideFxLock, testEntryFlashCallbackFailuresRollback and testRepeatedDeposits (all pass). With MockFxManager.setTransactionLock(true) emulating the transient transaction-wide lock, FxLockProbe.operateTwice reverts with ErrorPoolManagerLocked() while the full deposit succeeds with operateCalls == 1 and the expected 1.5225 WBTC / 50000 fxUSD / 31250 USDS position; a repeat deposit in the next transaction reaches 3.045 WBTC / 100000 fxUSD, and close() settles both debts returning the lender's exact USDS balance. No defect remains.","severity":"info","title":"Resolved: second f(x) operate per deposit removed (prior id ae636d60f1458580d960f6abf16ed7a1455f028204acfcd9e0baeeb79c5a5acf)"},{"description":"Confirmed fixed. refresh() commits account and loadedPositionId only after all reads succeed (line 120); an input event on the Receipt ID field clears the displayed account and disables management (lines 18-24, 250); verify() rejects any management action when the input no longer parses to loadedPositionId (lines 47-53); transfer() submits safeTransferFrom with loadedPositionId rather than the editable input (line 243).","line":243,"path":"web/app.js","reproduction":"Re-ran node --check web/app.js and node --test web/*.test.cjs (9 passed). position.test.cjs executes the real app.js in a Node VM with two owned receipts: after loading #1, editing the input to 2 (with or without an input event) and clicking Transfer produces no simulation and no transfer, the Transfer button is disabled, and the old account is no longer displayed; loading #2 and transferring moves only #2; a failed load of #99 leaves nothing actionable. The previously observed transferredReceipt='2' while '#1' was displayed no longer reproduces.","severity":"info","title":"Resolved: receipt transfer bound to the loaded position (prior id c41ad1d6f9098775ccc7195601ba68fa74cb87827445d05b1ba0374a17662c50)"}],"hash":"3088583369882903a3facea6db4ea6ac316237e3802d23db95f276a89af21109","nodeId":"062a3bcd-7407-4a27-909b-1487835c587f","outcome":"completed","summary":"Both prior findings are fixed. No new defects were found, so the findings file contains only two informational resolution records and nothing that reopens a revision.\n\n**High finding, transaction-wide f(x) lock: fixed.** The deposit path now calls `PoolManager.operate` exactly once. It flash-borrows the Cooler amount in USDS from Morpho, buys the reinvestment WBTC first, supplies capital plus reinvestment plus top-up while borrowing fxUSD in one operation, and repays Morpho from the later Cooler disbursement. I traced every path in `src/LoopPosition.sol` and found no second manager call in deposit, close, addCollateral or repayFx. The regression test emulates the transient lock in the mock manager, proves the probe with two calls reverts with the real error, and shows the full deposit succeeds with one call. It passes in both default and isolate modes. Live reads at Ethereum block 26070440 confirm the assumptions the fix leans on:\n\n| Check | Result |\n|---|---|\n| WBTC pool debt ratio range | 0.01% to 85.5%, so 33% is admissible |\n| WBTC scaling factor | 1e28, matches the constructor guard |\n| USDS held by Morpho Blue | about 923,264, enough for the flash bridge |\n| MonoCooler debt token | USDS |\n| Treasury borrower disbursement | `SUSDS.withdraw(amountInWad, recipient, ...)`, exact amount, so the strict delta check holds |\n\n**Medium finding, receipt transfer used the edited ID: fixed.** The interface now tracks the loaded position ID separately, clears the displayed account when the input changes, refuses management actions when the input no longer matches the loaded ID, and transfers only the loaded ID. The new tests run the real `web/app.js` in a Node VM and cover editing with and without an input event, failed loads and successful transfers.\n\n**Verification run:**\n\n```\nforge build --offline          ok\nforge test --offline           56 passed, 0 failed\nforge fmt --check              clean\nforge test --offline --isolate (lock, callback, repeat tests)  3 passed\nnode --check web/app.js && node --test web/*.test.cjs          9 passed\n```\n\nFindings were written to `.imd-findings.json` at the repository root. No project files were modified.","treeHash":null,"usage":{"cachedInputTokens":691726,"inputTokens":258,"model":"claude-fable-5-1","outputTokens":15604,"runtime":"claude","turns":19,"wallClockMs":343156}},{"artifacts":[],"attempt":2,"bundleHash":"4f02f8a6f8050b0af744e85f9f70232b4728ff2e801157426edcffe5a338b307","device":"35c52a5b502e847c","findings":[],"hash":"55d68e99a6e3fc4f734560f92bbe40daa7da4de077dfffeb1ab9566e8a961998","nodeId":"7b9ae8a5-6297-40d9-9d9e-ab48a3b216fd","outcome":"completed","summary":"Both findings reproduced and are fixed:\n\n- Deposits use one f(x) operation, with temporary Morpho USDS funding.\n- Receipt transfers are bound to the loaded position.\n\nPassed: `forge build`, all 56 Foundry tests, 9 browser tests, and `forge fmt --check`.\n\nDocumented the entry-liquidity requirement and recorded both verdicts in `.imd-responses.json`.","treeHash":"e27a7b3ce368514e37ebb0c4f3c91db3d57d6e41","usage":{"cachedInputTokens":2615296,"inputTokens":119679,"model":"gpt-6-astra","outputTokens":23908,"runtime":"codex","turns":7,"wallClockMs":835123}},{"artifacts":[],"attempt":1,"bundleHash":"15c8c93568206bfad6f9a0b1309deceab1a358650056970b11ae14dc456827cb","device":"c4f696e22e7a36f7","findings":[],"hash":"83c690683a1962a2418ed9eef668957a4e0d0af0a1bf3a9e4be5a09489e34de5","nodeId":"7b9ae8a5-6297-40d9-9d9e-ab48a3b216fd","outcome":"completed","summary":"Reproduced and fixed both findings:\n\n- Deposits now use one f(x) operation with a temporary USDS flash bridge.\n- Receipt transfers use the displayed position’s ID.\n\nRecorded responses in [.imd-responses.json](/root/.identitymd/work/9df471c0-b9f9-474e-b2e1-1aa86c7f7412/7b9ae8a5-6297-40d9-9d9e-ab48a3b216fd/.imd-responses.json).\n\nValidation passed: build, formatting, 57 Solidity tests with 1,000 fuzz runs, and 7 browser tests.\n\nDocumented the entry liquidity requirement. No production fork rehearsal or deployment was performed.","treeHash":"349d1a7f26c2dbfa64422d3cedebaae684ff3ca9","usage":{"cachedInputTokens":2252544,"inputTokens":105706,"model":"gpt-6-astra","outputTokens":19943,"runtime":"codex","turns":7,"wallClockMs":718418}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"35c52a5b502e847c","findings":[{"description":"deposit calls PoolManager.operate first through _openFx at line 189 and again here to reinvest Cooler proceeds. The configured f(x) implementation locks its PoolConfiguration for the entire transaction; returning from operate does not release that lock, and unlock requires UNLOCK_ROLE. Consequently, a deposit that reaches the reinvestment call reverts with ErrorPoolManagerLocked(), rolling back the entire loop. Neither this account nor its routing path invokes the privileged unlock operation. MockFxManager.operate omits this behavior, so the successful loop and repeated-deposit tests do not exercise this production restriction. Sources: [PoolManager lock modifier](https://github.com/AladdinDAO/fx-protocol-contracts/blob/5e198e93657db008a57129e7eea21a996618f17f/contracts/core/PoolManager.sol#L250-L253), [transaction-wide lock and restricted unlock](https://github.com/AladdinDAO/fx-protocol-contracts/blob/5e198e93657db008a57129e7eea21a996618f17f/contracts/core/PoolConfiguration.sol#L359-L378).","line":169,"path":"src/LoopPosition.sol","reproduction":"At Ethereum block 26070119, configuration() on the manifest's manager 0x250893ca4ba5d05626c785e8da758026928fcd24 returns 0x16b334f2644cc00b85db1a1eff0c2c395e00c28d. In one eth_call, use Multicall3 at 0xcA11bde05977b3631167028862bE2a173976CA11 with tryAggregate(false, calls) to call that configuration's lock(manager,0x00000000) twice. Observed results: [(true,0x),(false,0x86e4722b)], where 0x86e4722b is ErrorPoolManagerLocked(). Replacing the second call with manager.operate(0xab709e26fa6b0a30c119d8c55b887ded24952473,0,100000000,50000000000000000000000) produces the same error. For the strategy reproduction, run test/Loop.t.sol's testDepositLoopAndReceipt with the mock manager enforcing this same transaction-wide lock: its existing 1 WBTC deposit, 50000 fxUSD borrow, 31250 USDS Cooler borrow, and 0.21 WBTC top-up should produce the tested 1.5225 WBTC position, but the second _operate reverts instead. Both initial and subsequent loops necessarily make these two manager calls. The RPC lock and manager error results were reproduced read-only; project files were not modified.","severity":"high","title":"The second f(x) operation makes the deposit loop revert against the configured protocol"},{"description":"Position balances, ownership state, and other management actions use the account selected by refresh(), but transfer() takes its token ID directly from the editable receiptId input. Editing this field only invalidates deposit and withdrawal quotes; it leaves Transfer all position rights enabled and preserves the old account display. verify() checks the deployment and wallet but does not bind the receipt ID to the loaded account. A user who owns both IDs can therefore transfer a different position, including all its collateral and liabilities, from the one whose details are displayed. The browser smoke test only checks action wiring and misses this target mismatch.","line":227,"path":"web/app.js","reproduction":"Own receipts #1 and #2 with different funded accounts. Load position #1 so its account, balances, and owner are displayed. Change the Receipt ID input to 2 without clicking Load position, enter another wallet as the recipient, and click Transfer all position rights. Expected: transfer the loaded/displayed receipt #1, or reject until #2 is loaded. Actual: safeTransferFrom(wallet,recipient,2) is simulated and submitted while #1's details remain displayed until the transaction finishes. A Node VM execution of the actual web/app.js with mocked wallet/receipt transport reproduced displayed='Loaded account for receipt #1', transferredReceipt='2', and transferEnabledAfterEditingId=true.","severity":"medium","title":"Receipt transfer uses an edited ID instead of the displayed, loaded position"}],"hash":"bfb43807044aa82c0d9a70354aed855f8be28809d57953e074021c0f309b2a54","nodeId":"062a3bcd-7407-4a27-909b-1487835c587f","outcome":"completed","summary":"Wrote two findings to [.imd-findings.json](/home/identitymd5/.identitymd/work/9df471c0-b9f9-474e-b2e1-1aa86c7f7412/062a3bcd-7407-4a27-909b-1487835c587f/.imd-findings.json):\n\n- **High:** f(x)’s transaction-wide lock blocks the deposit’s second operation.\n- **Medium:** The website can transfer a different receipt from the displayed position.\n\nIncluded concrete reproductions. Project source and tests remain unchanged.","treeHash":null,"usage":{"cachedInputTokens":1318272,"inputTokens":101841,"model":"gpt-6-astra","outputTokens":9977,"runtime":"codex","turns":5,"wallClockMs":373532}},{"artifacts":[],"attempt":1,"bundleHash":"1d070fb762fb30e76c13c88e0a578e31bfef53558beb836ca2e350fa502730ba","device":"c4f696e22e7a36f7","findings":[],"hash":"d0f9ecdc070f47056abcc6da64f0ea3ba77e5ef9d51ca8a449cbe144eb9e2b7a","nodeId":"7b9ae8a5-6297-40d9-9d9e-ab48a3b216fd","outcome":"completed","summary":"Implemented immutable contracts, transferable receipts, repeat deposits, full unwind, protocol adapters, and a management website.\n\nPassed: Solidity 0.8.26 build, formatting, 51 contract tests with 1,000 fuzz runs, and five website tests.\n\nThe 33% LTV ceiling may require an explicitly quoted WBTC top-up. No deployment performed; fork validation and independent audit remain.\n\nSetup and assumptions: [README.md](/root/.identitymd/work/9df471c0-b9f9-474e-b2e1-1aa86c7f7412/7b9ae8a5-6297-40d9-9d9e-ab48a3b216fd/README.md).","treeHash":"5c8adcfc6db08f279971ac8047360af354f9cc3b","usage":{"cachedInputTokens":3512960,"inputTokens":161039,"model":"gpt-6-astra","outputTokens":63327,"runtime":"codex","turns":10,"wallClockMs":2065315}},{"artifacts":[],"attempt":1,"bundleHash":"5efa977f98aede1826299acb4368ae95515a8c7807777d831ae0afeb9dc7c5bc","device":"c4f696e22e7a36f7","findings":[],"hash":"e598a3bed7f1e5b956b54b71cd9b0b5a7ac76bf4ce5c411a39b2853a07789a16","nodeId":"ee77781b-b466-4e3a-9199-dc0a5e9722b2","outcome":"completed","summary":"Created [launch.json](/root/.identitymd/work/9df471c0-b9f9-474e-b2e1-1aa86c7f7412/ee77781b-b466-4e3a-9199-dc0a5e9722b2/launch.json) with five contracts in dependency order.\n\nSchema and constructor ABI checks passed. `forge build` passed; `forge test --fuzz-runs 1000` passed all 51 tests.\n\nOnly the manifest changed. Live mainnet dependency deployment remains unverified.","treeHash":"86b22e428a531173d95dfb78e855fb21077efb1c","usage":{"cachedInputTokens":415488,"inputTokens":44890,"model":"gpt-6-astra","outputTokens":6214,"runtime":"codex","turns":4,"wallClockMs":233026}}],"verification":[{"checks":[{"durationMs":17263,"exitCode":0,"name":"build","output":"Compiling 53 files with Solc 0.8.26\nSolc 0.8.26 finished in 17.14s\nCompiler run successful!\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/LoopAccountDeployer.sol:10:17\n   │\n10 │     constructor(address config_) {\n   │                 ━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/WbtcUsdFeed.sol:33:35\n   │\n33 │         if (value == 0 || value > uint256(type(int256).max)) revert InvalidPrice();\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/LoopConfig.sol:33:9\n   │\n33 │         address cooler_,\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/LoopConfig.sol:26:9\n   │\n26 │         address wbtc_,\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/LoopConfig.sol:32:9\n   │\n32 │         address pool_,\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/FxSwapRouter.sol:34:83\n   │\n34 │     constructor(address router_, address quoter_, address curve_, address fxUSD_, address usdc_) {\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/FxSwapRouter.sol:34:67\n   │\n34 │     constructor(address router_, address quoter_, address curve_, address fxUSD_, address usdc_) {\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/FxSwapRouter.sol:34:51\n   │\n34 │     constructor(address router_, address quoter_, address curve_, address fxUSD_, address usdc_) {\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/FxSwapRouter.sol:34:34\n   │\n34 │     constructor(address router_, address quoter_, address curve_, address fxUSD_, address usdc_) {\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/FxSwapRouter.sol:34:17\n   │\n34 │     constructor(address router_, address quoter_, address curve_, address fxUSD_, address usdc_) {\n   │                 ━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/WbtcUsdFeed.sol:35:20\n   │\n35 │         return (1, int256(value), timestamp, timestamp, 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/LoopConfig.sol:37:9\n   │\n37 │         address priceFeed_,\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/LoopConfig.sol:34:9\n   │\n34 │         address staking_,\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/LoopConfig.sol:30:9\n   │\n30 │         address usds_,\n   │         ━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/WbtcUsdFeed.sol:41:44\n   │\n41 │             answer <= 0 || updated == 0 || updated > block.timestamp || answeredRound < round\n   │                                            ━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/WbtcUsdFeed.sol:42:20\n   │\n42 │                 || block.timestamp - updated > maxAge\n   │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-oz-erc721-mint]: `ERC721._mint` does not check that the recipient can receive the token; use `_safeMint`\n   ╭▸ src/LoopReceipt.sol:30:9\n   │\n30 │         _mint(msg.sender, id);\n   │         ━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-oz-erc721-mint\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/LoopConfig.sol:27:9\n   │\n27 │         address fxUSD_,\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/LoopConfig.sol:29:9\n   │\n29 │         address gohm_,\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/LoopConfig.sol:35:9\n   │\n35 │         address router_,\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/LoopConfig.sol:36:9\n   │\n36 │         address morpho_,\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/LoopConfig.sol:28:9\n   │\n28 │         address ohm_,\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/LoopConfig.sol:31:9\n   │\n31 │         address manager_,\n   │         ━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-events-access-control]: `pendingHash` is changed without an event but is used for access control\n    ╭▸ src/LoopPosition.sol:258:9\n    │\n258 │         pendingHash = keccak256(data);\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/LoopReceipt.sol:31:9\n   │\n31 │         emit PositionCreated(msg.sender, id, account);\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/WbtcUsdFeed.sol:39:81\n   │\n39 │         (uint80 round, int256 answer,, uint256 updated, uint80 answeredRound) = feed.latestRoundData();\n   │                                                                                 ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/WbtcUsdFeed.sol:44:17\n   │\n44 │         return (uint256(answer), updated);\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]: `pendingAssets` is changed without an event but is used for access control\n    ╭▸ src/LoopPosition.sol:259:9\n    │\n259 │         pendingAssets = assets;\n    │         ━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-events-access-control]: `flashBalanceBefore` is changed without an event but is used for access control\n    ╭▸ src/LoopPosition.sol:260:9\n    │\n260 │         flashBalanceBefore = _balance(config.usds());\n    │         ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n   ╭▸ src/LoopConfig.sol:44:51\n   │\n44 │             if (dependencies[i].code.length == 0) revert InvalidConfiguration();\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/LoopConfig.sol:46:57\n   │\n46 │                 if (dependencies[i] == dependencies[j]) revert InvalidConfiguration();\n   │                                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/LoopPosition.sol:122:46\n    │\n122 │             answer <= 0 || updatedAt == 0 || updatedAt > block.timestamp || answeredInRound < round\n    │                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/LoopPosition.sol:123:20\n    │\n123 │                 || block.timestamp - updatedAt > config.maxPriceAge()\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/LoopPosition.sol:120:13\n    │\n120 │             IPriceFeed(config.priceFeed()).latestRoundData();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LoopPosition.sol:125:16\n    │\n125 │         return uint256(answer) * 1e10;\n    │                ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-no-eth]: external call can be reentered before `entered` is updated\n    ╭▸ src/FxSwapRouter.sol:142:9\n    │\n142 │         IV3Router(v3Router).exactInput(ExactInputParams(path, address(this), deadline, amount, minimum));\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/FxSwapRouter.sol:168:9\n    │\n168 │         ICurveFxPool(curve).exchange(i, j, amount, minimum, address(this));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `state` is updated\n    ╭▸ src/LoopPosition.sol:415:9\n    │\n415 │ ┏         IV3Router(config.router())\n416 │ ┃             .exactInput(IV3Router.ExactInputParams(path, address(this), deadline, amount, minimum));\n    │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `state` is updated\n    ╭▸ src/LoopPosition.sol:262:9\n    │\n262 │         IMorpho(config.morpho()).flashLoan(config.usds(), assets, data);\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/LoopPosition.sol:162:9\n    │\n162 │ ┏         emit Deposited(\n163 │ ┃             msg.sender,\n164 │ ┃             p.token,\n165 │ ┃             p.amount,\n    ‡ ┃\n168 │ ┃             ICooler(config.cooler()).accountPosition(address(this)).currentDebt\n169 │ ┃         );\n    │ ┗━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `entered` is updated\n    ╭▸ src/FxSwapRouter.sol:156:9\n    │\n156 │         IV3Router(v3Router).exactOutput(ExactOutputParams(path, address(this), deadline, amount, maximum));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/LoopPosition.sol:181:9\n    │\n181 │         IStaking(config.staking()).stake(address(this), ohmReceived, false, true);\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/LoopPosition.sol:189:9\n    │\n189 │         ICooler(cooler).borrow(p.coolerBorrow, address(this), address(this));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `fxPositionId` is updated\n    ╭▸ src/LoopPosition.sol:393:22\n    │\n393 │         uint256 id = IFxManager(config.manager()).operate(config.pool(), fxPositionId, collateral, debt);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `fxPositionId` is updated\n    ╭▸ src/LoopPosition.sol:430:9\n    │\n430 │ ┏         IV3Router(config.router())\n431 │ ┃             .exactOutput(IV3Router.ExactOutputParams(path, address(this), deadline, amount, maximum));\n    │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `closed` is updated\n    ╭▸ src/LoopPosition.sol:312:13\n    │\n312 │             ICooler(config.cooler()).repay(_u128(cp.currentDebt), address(this));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `closed` is updated\n    ╭▸ src/LoopPosition.sol:316:13\n    │\n316 │ ┏             ICooler(config.cooler())\n317 │ ┃                 .withdrawCollateral(\n318 │ ┃                     _u128(cp.collateral), address(this), address(this), new ICooler.DelegationRequest[](0)\n319 │ ┃                 );\n    │ ┗━━━━━━━━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `closed` is updated\n    ╭▸ src/LoopPosition.sol:325:13\n    │\n325 │             IStaking(config.staking()).unstake(address(this), gohmBalance, false, false);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `closed` is updated\n    ╭▸ src/LoopPosition.sol:415:9\n    │\n415 │ ┏         IV3Router(config.router())\n416 │ ┃             .exactInput(IV3Router.ExactInputParams(path, address(this), deadline, amount, minimum));\n    │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `state` is updated\n    ╭▸ src/LoopPosition.sol:242:9\n    │\n242 │         receipt.burn(receiptId);\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/LoopPosition.sol:252:9\n    │\n252 │         emit Closed(msg.sender, p.outputToken, output);\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/FxSwapRouter.sol:142:9\n    │\n142 │         IV3Router(v3Router).exactInput(ExactInputParams(path, address(this), deadline, amount, minimum));\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/FxSwapRouter.sol:156:9\n    │\n156 │         IV3Router(v3Router).exactOutput(ExactOutputParams(path, address(this), deadline, amount, maximum));\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/FxSwapRouter.sol:168:9\n    │\n168 │         ICurveFxPool(curve).exchange(i, j, amount, minimum, address(this));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FxSwapRouter.sol:192:25\n    │\n192 │         for (uint256 i; i < 16 && high - low > 1; ++i) {\n    │                         ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FxSwapRouter.sol:191:14\n    │\n191 │         if (!sufficient) revert SwapFailed();\n    │              ━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FxSwapRouter.sol:184:17\n    │\n184 │             if (ICurveFxPool(curve).get_dy(0, 1, high) >= output) {\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FxSwapRouter.sol:194:17\n    │\n194 │             if (ICurveFxPool(curve).get_dy(0, 1, mid) >= output) high = mid;\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/FxSwapRouter.sol:216:31\n    │\n216 │         if (msg.value != 0 || block.timestamp > deadline || recipient == address(0) || recipient == address(this)) {\n    │                               ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FxSwapRouter.sol:226:30\n    │\n226 │         for (uint256 offset; offset < path.length - 20; offset += 23) {\n    │                              ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/FxSwapRouter.sol:240:19\n    │\n240 │                 ) revert InvalidRoute();\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/FxSwapRouter.sol:242:17\n    │\n242 │                 revert InvalidRoute();\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/LoopPosition.sol:312:13\n    │\n312 │             ICooler(config.cooler()).repay(_u128(cp.currentDebt), address(this));\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/LoopPosition.sol:316:13\n    │\n316 │ ┏             ICooler(config.cooler())\n317 │ ┃                 .withdrawCollateral(\n318 │ ┃                     _u128(cp.collateral), address(this), address(this), new ICooler.DelegationRequest[](0)\n319 │ ┃                 );\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/LoopPosition.sol:325:13\n    │\n325 │             IStaking(config.staking()).unstake(address(this), gohmBalance, false, false);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/LoopPosition.sol:362:9\n    │\n362 │         emit CollateralAdded(amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/LoopPosition.sol:370:9\n    │\n370 │         emit DebtRepaid(config.fxUSD(), debtAmount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `state` is updated\n    ╭▸ src/LoopPosition.sol:377:26\n    │\n377 │         uint128 repaid = ICooler(config.cooler()).repay(amount, address(this));\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/LoopPosition.sol:379:9\n    │\n379 │         emit DebtRepaid(config.usds(), repaid);\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/LoopPosition.sol:415:9\n    │\n415 │ ┏         IV3Router(config.router())\n416 │ ┃             .exactInput(IV3Router.ExactInputParams(path, address(this), deadline, amount, minimum));\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/LoopPosition.sol:430:9\n    │\n430 │ ┏         IV3Router(config.router())\n431 │ ┃             .exactOutput(IV3Router.ExactOutputParams(path, address(this), deadline, amount, maximum));\n    │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LoopPosition.sol:467:22\n    │\n467 │         if (amount > uint256(type(int256).max)) revert InvalidInput();\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/LoopPosition.sol:468:16\n    │\n468 │         return int256(amount);\n    │                ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LoopPosition.sol:473:16\n    │\n473 │         return uint128(amount);\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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/LoopPosition.sol:477:13\n    │\n477 │         if (block.timestamp > deadline) revert Expired();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\n","passed":true},{"durationMs":223,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/Loop.t.sol:LaunchTokenTest\n[PASS] testSupplyTransferAndNoMint() (gas: 113863)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 317.73µs (199.90µs CPU time)\n\nRan 1 test for test/Adapters.t.sol:CompositeFeedTest\n[PASS] testCompositePriceIncludesWrappedBitcoinBasisAndFreshness() (gas: 1172117)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 871.10µs (751.03µs CPU time)\n\nRan 11 tests for test/Adapters.t.sol:AdapterTest\n[PASS] testAdapterDonationsCannotBeTakenBySwap() (gas: 307045)\n[PASS] testBoundedV3AndCurveExactOutputRefundsUnspentInput() (gas: 428713)\n[PASS] testCurveApproximateInverseIsVerifiedBeforeSwapping() (gas: 502349)\n[PASS] testCurveOnlyBothDirections() (gas: 410538)\n[PASS] testCurveThenV3ExactInput() (gas: 398386)\n[PASS] testFuzzExactOutputBounds(uint96) (runs: 256, μ: 426232, ~: 426298)\nLogs:\n  Bound result 99999999999000000000268\n\n[PASS] testMalformedRoutesAndWrongCurveEndpoints() (gas: 115441)\n[PASS] testPureV3Passthrough() (gas: 387033)\n[PASS] testRouterRuntimeWithinLaunchConstraints() (gas: 3030716)\n[PASS] testSlippageAndAllowanceRevocation() (gas: 302425)\n[PASS] testV3ThenCurveExactInput() (gas: 393763)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 32.55ms (39.60ms CPU time)\n\nRan 43 tests for test/Loop.t.sol:LoopTest\n[PASS] testAccruedDebtsAndRepaymentFeePaidFromCapital() (gas: 1713132)\n[PASS] testAnyRoutableErc20SixDecimalsAndFullExitToSameToken() (gas: 1741058)\n[PASS] testApprovedNftOperatorCannotSpendPositionFunds() (gas: 933896)\n[PASS] testAuthorizedOwnerCallbackHitsReentrancyGuard() (gas: 1583975)\n[PASS] testCoolerMinimumAndMaxBorrow() (gas: 1744795)\n[PASS] testDeadlineAndZeroAmount() (gas: 151365)\n[PASS] testDebtTokenMigrationCanExitAfterExternalFullRepayment() (gas: 1547733)\n[PASS] testDependencyChangesFailClosed() (gas: 251246)\n[PASS] testDeploymentRuntimeHasNoEscapeOpcodes() (gas: 35300370)\n[PASS] testDepositLoopAndReceipt() (gas: 951220)\n[PASS] testDepositWithTransactionWideFxLock() (gas: 2900623)\n[PASS] testDirectFxBurnCannotExceedRepaymentBudget() (gas: 1720592)\n[PASS] testDonationsRecoverableBeforeAndAfterBurn() (gas: 1768556)\n[PASS] testEntryCallbackPreservesDynamicRoutesWithNoncanonicalInputOffsets() (gas: 1221608)\n[PASS] testEntryFlashCallbackFailuresRollback() (gas: 3598934)\n[PASS] testEntryRejectsShortCoolerDisbursementEvenWithIdleFunds() (gas: 1081101)\n[PASS] testEntryRequiresFlashLiquidityAndPreservesIdleUsds() (gas: 1224938)\n[PASS] testExitSlippageAndUnderfundingAreAtomic() (gas: 2567731)\n[PASS] testFeeOnTransferDepositRejected() (gas: 200549)\n[PASS] testFullLoopAndUnwindThroughCurveBridge() (gas: 8483758)\n[PASS] testFullUnwindConservesCapitalAndFlashLiquidity() (gas: 1715544)\n[PASS] testFullyLiquidatedPositionCanCloseWithExplicitZeroReturn() (gas: 1030955)\n[PASS] testFuzzRepeatedLoopsConserveCapital(uint96,uint8) (runs: 256, μ: 2409918, ~: 2311014)\nLogs:\n  Bound result 3\n  Bound result 1\n\n[PASS] testIndependentPositions() (gas: 7137457)\n[PASS] testInitialBorrowMustBeNearFiftyPercent() (gas: 1108365)\n[PASS] testInsufficientReinvestmentRevertsEverything() (gas: 983787)\n[PASS] testInvalidAndStaleFeed() (gas: 391149)\n[PASS] testLenderCannotSkipCallbackOrLieAboutAmountOrFunding() (gas: 2275280)\n[PASS] testOtherUsersCannotBurnOrWithdraw() (gas: 903102)\n[PASS] testOwnerCanReduceRiskWithStaleOracle() (gas: 1255450)\n[PASS] testPoolOracleAlsoEnforcesFinalLtv() (gas: 992018)\n[PASS] testReceiptTransferMovesAllRights() (gas: 1646956)\n[PASS] testRejectsWrongPathEndpointsAndMalformedPath() (gas: 1116488)\n[PASS] testRepeatedDeposits() (gas: 1449145)\n[PASS] testSupplyAndBorrowFeesRequireAdjustedQuote() (gas: 1452614)\n[PASS] testSwapCannotReenterUnwind() (gas: 1442997)\n[PASS] testSwapCannotTransferReceiptMidOperation() (gas: 1049103)\n[PASS] testSwapFailureAndMisreportedOutputRollback() (gas: 983115)\n[PASS] testTaxedOutputCannotUndercutWalletMinimum() (gas: 1814514)\n[PASS] testTopUpCanCoverMarketLossOnExit() (gas: 1530134)\n[PASS] testUnauthorizedAndReplayedCallbackRejected() (gas: 1705375)\n[PASS] testUnwindWithoutFlashLoanUsesOwnerBridgeFunds() (gas: 1446955)\n[PASS] testWarmupOrCoolerBorrowFailureRollsBack() (gas: 1708297)\nSuite result: ok. 43 passed; 0 failed; 0 skipped; finished in 135.94ms (254.69ms CPU time)\n\nRan 4 test suites in 138.44ms (169.68ms CPU time): 56 tests passed, 0 failed, 0 skipped (56 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"0eee1dc80119e4b09534e658969de826e48ecbb1340cd0b6ce05c751afbbefcb","verifiedTreeHash":"d017ae653c3e53f8b4ba14382792c82862ea00d3","verifierVersion":"0.1.0+e4d213a5"},{"checks":[{"durationMs":18373,"exitCode":0,"name":"build","output":"Compiling 53 files with Solc 0.8.26\nSolc 0.8.26 finished in 18.21s\nCompiler run successful!\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/LoopAccountDeployer.sol:10:17\n   │\n10 │     constructor(address config_) {\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/LoopConfig.sol:27:9\n   │\n27 │         address fxUSD_,\n   │         ━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/WbtcUsdFeed.sol:33:35\n   │\n33 │         if (value == 0 || value > uint256(type(int256).max)) revert InvalidPrice();\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/WbtcUsdFeed.sol:35:20\n   │\n35 │         return (1, int256(value), timestamp, timestamp, 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/FxSwapRouter.sol:34:51\n   │\n34 │     constructor(address router_, address quoter_, address curve_, address fxUSD_, address usdc_) {\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/FxSwapRouter.sol:34:34\n   │\n34 │     constructor(address router_, address quoter_, address curve_, address fxUSD_, address usdc_) {\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/FxSwapRouter.sol:34:67\n   │\n34 │     constructor(address router_, address quoter_, address curve_, address fxUSD_, address usdc_) {\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/LoopConfig.sol:33:9\n   │\n33 │         address cooler_,\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/LoopConfig.sol:26:9\n   │\n26 │         address wbtc_,\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/FxSwapRouter.sol:34:83\n   │\n34 │     constructor(address router_, address quoter_, address curve_, address fxUSD_, address usdc_) {\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/FxSwapRouter.sol:34:17\n   │\n34 │     constructor(address router_, address quoter_, address curve_, address fxUSD_, address usdc_) {\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/LoopConfig.sol:34:9\n   │\n34 │         address staking_,\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/LoopConfig.sol:35:9\n   │\n35 │         address router_,\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/LoopConfig.sol:32:9\n   │\n32 │         address pool_,\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/LoopConfig.sol:36:9\n   │\n36 │         address morpho_,\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/LoopConfig.sol:28:9\n   │\n28 │         address ohm_,\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/LoopConfig.sol:30:9\n   │\n30 │         address usds_,\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/LoopConfig.sol:37:9\n   │\n37 │         address priceFeed_,\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/LoopConfig.sol:31:9\n   │\n31 │         address manager_,\n   │         ━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/WbtcUsdFeed.sol:41:44\n   │\n41 │             answer <= 0 || updated == 0 || updated > block.timestamp || answeredRound < round\n   │                                            ━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/WbtcUsdFeed.sol:42:20\n   │\n42 │                 || block.timestamp - updated > maxAge\n   │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[missing-events-access-control]: `pendingHash` is changed without an event but is used for access control\n    ╭▸ src/LoopPosition.sol:258:9\n    │\n258 │         pendingHash = keccak256(data);\n    │         ━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-events-access-control]: `pendingAssets` is changed without an event but is used for access control\n    ╭▸ src/LoopPosition.sol:259:9\n    │\n259 │         pendingAssets = assets;\n    │         ━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-events-access-control]: `flashBalanceBefore` is changed without an event but is used for access control\n    ╭▸ src/LoopPosition.sol:260:9\n    │\n260 │         flashBalanceBefore = _balance(config.usds());\n    │         ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[unsafe-oz-erc721-mint]: `ERC721._mint` does not check that the recipient can receive the token; use `_safeMint`\n   ╭▸ src/LoopReceipt.sol:30:9\n   │\n30 │         _mint(msg.sender, id);\n   │         ━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-oz-erc721-mint\n\nwarning[unused-return]: return value of an external call is not used\n   ╭▸ src/WbtcUsdFeed.sol:39:81\n   │\n39 │         (uint80 round, int256 answer,, uint256 updated, uint80 answeredRound) = feed.latestRoundData();\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/LoopConfig.sol:29:9\n   │\n29 │         address gohm_,\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/LoopReceipt.sol:31:9\n   │\n31 │         emit PositionCreated(msg.sender, id, account);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/WbtcUsdFeed.sol:44:17\n   │\n44 │         return (uint256(answer), updated);\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/LoopConfig.sol:44:51\n   │\n44 │             if (dependencies[i].code.length == 0) revert InvalidConfiguration();\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/LoopConfig.sol:46:57\n   │\n46 │                 if (dependencies[i] == dependencies[j]) revert InvalidConfiguration();\n   │                                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/LoopPosition.sol:122:46\n    │\n122 │             answer <= 0 || updatedAt == 0 || updatedAt > block.timestamp || answeredInRound < round\n    │                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/LoopPosition.sol:123:20\n    │\n123 │                 || block.timestamp - updatedAt > config.maxPriceAge()\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/LoopPosition.sol:120:13\n    │\n120 │             IPriceFeed(config.priceFeed()).latestRoundData();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LoopPosition.sol:125:16\n    │\n125 │         return uint256(answer) * 1e10;\n    │                ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-no-eth]: external call can be reentered before `entered` is updated\n    ╭▸ src/FxSwapRouter.sol:142:9\n    │\n142 │         IV3Router(v3Router).exactInput(ExactInputParams(path, address(this), deadline, amount, minimum));\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/FxSwapRouter.sol:168:9\n    │\n168 │         ICurveFxPool(curve).exchange(i, j, amount, minimum, address(this));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `state` is updated\n    ╭▸ src/LoopPosition.sol:415:9\n    │\n415 │ ┏         IV3Router(config.router())\n416 │ ┃             .exactInput(IV3Router.ExactInputParams(path, address(this), deadline, amount, minimum));\n    │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `state` is updated\n    ╭▸ src/LoopPosition.sol:262:9\n    │\n262 │         IMorpho(config.morpho()).flashLoan(config.usds(), assets, data);\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/LoopPosition.sol:162:9\n    │\n162 │ ┏         emit Deposited(\n163 │ ┃             msg.sender,\n164 │ ┃             p.token,\n165 │ ┃             p.amount,\n    ‡ ┃\n168 │ ┃             ICooler(config.cooler()).accountPosition(address(this)).currentDebt\n169 │ ┃         );\n    │ ┗━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `entered` is updated\n    ╭▸ src/FxSwapRouter.sol:156:9\n    │\n156 │         IV3Router(v3Router).exactOutput(ExactOutputParams(path, address(this), deadline, amount, maximum));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/LoopPosition.sol:181:9\n    │\n181 │         IStaking(config.staking()).stake(address(this), ohmReceived, false, true);\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/LoopPosition.sol:189:9\n    │\n189 │         ICooler(cooler).borrow(p.coolerBorrow, address(this), address(this));\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/FxSwapRouter.sol:142:9\n    │\n142 │         IV3Router(v3Router).exactInput(ExactInputParams(path, address(this), deadline, amount, minimum));\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/FxSwapRouter.sol:156:9\n    │\n156 │         IV3Router(v3Router).exactOutput(ExactOutputParams(path, address(this), deadline, amount, maximum));\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/FxSwapRouter.sol:168:9\n    │\n168 │         ICurveFxPool(curve).exchange(i, j, amount, minimum, address(this));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FxSwapRouter.sol:192:25\n    │\n192 │         for (uint256 i; i < 16 && high - low > 1; ++i) {\n    │                         ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FxSwapRouter.sol:191:14\n    │\n191 │         if (!sufficient) revert SwapFailed();\n    │              ━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FxSwapRouter.sol:184:17\n    │\n184 │             if (ICurveFxPool(curve).get_dy(0, 1, high) >= output) {\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FxSwapRouter.sol:194:17\n    │\n194 │             if (ICurveFxPool(curve).get_dy(0, 1, mid) >= output) high = mid;\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/FxSwapRouter.sol:216:31\n    │\n216 │         if (msg.value != 0 || block.timestamp > deadline || recipient == address(0) || recipient == address(this)) {\n    │                               ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FxSwapRouter.sol:226:30\n    │\n226 │         for (uint256 offset; offset < path.length - 20; offset += 23) {\n    │                              ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/FxSwapRouter.sol:240:19\n    │\n240 │                 ) revert InvalidRoute();\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/FxSwapRouter.sol:242:17\n    │\n242 │                 revert InvalidRoute();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[reentrancy-no-eth]: external call can be reentered before `fxPositionId` is updated\n    ╭▸ src/LoopPosition.sol:393:22\n    │\n393 │         uint256 id = IFxManager(config.manager()).operate(config.pool(), fxPositionId, collateral, debt);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `fxPositionId` is updated\n    ╭▸ src/LoopPosition.sol:430:9\n    │\n430 │ ┏         IV3Router(config.router())\n431 │ ┃             .exactOutput(IV3Router.ExactOutputParams(path, address(this), deadline, amount, maximum));\n    │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `closed` is updated\n    ╭▸ src/LoopPosition.sol:312:13\n    │\n312 │             ICooler(config.cooler()).repay(_u128(cp.currentDebt), address(this));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `closed` is updated\n    ╭▸ src/LoopPosition.sol:316:13\n    │\n316 │ ┏             ICooler(config.cooler())\n317 │ ┃                 .withdrawCollateral(\n318 │ ┃                     _u128(cp.collateral), address(this), address(this), new ICooler.DelegationRequest[](0)\n319 │ ┃                 );\n    │ ┗━━━━━━━━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `closed` is updated\n    ╭▸ src/LoopPosition.sol:325:13\n    │\n325 │             IStaking(config.staking()).unstake(address(this), gohmBalance, false, false);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `closed` is updated\n    ╭▸ src/LoopPosition.sol:415:9\n    │\n415 │ ┏         IV3Router(config.router())\n416 │ ┃             .exactInput(IV3Router.ExactInputParams(path, address(this), deadline, amount, minimum));\n    │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `state` is updated\n    ╭▸ src/LoopPosition.sol:242:9\n    │\n242 │         receipt.burn(receiptId);\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/LoopPosition.sol:252:9\n    │\n252 │         emit Closed(msg.sender, p.outputToken, output);\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/LoopPosition.sol:312:13\n    │\n312 │             ICooler(config.cooler()).repay(_u128(cp.currentDebt), address(this));\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/LoopPosition.sol:316:13\n    │\n316 │ ┏             ICooler(config.cooler())\n317 │ ┃                 .withdrawCollateral(\n318 │ ┃                     _u128(cp.collateral), address(this), address(this), new ICooler.DelegationRequest[](0)\n319 │ ┃                 );\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/LoopPosition.sol:325:13\n    │\n325 │             IStaking(config.staking()).unstake(address(this), gohmBalance, false, false);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/LoopPosition.sol:362:9\n    │\n362 │         emit CollateralAdded(amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/LoopPosition.sol:370:9\n    │\n370 │         emit DebtRepaid(config.fxUSD(), debtAmount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `state` is updated\n    ╭▸ src/LoopPosition.sol:377:26\n    │\n377 │         uint128 repaid = ICooler(config.cooler()).repay(amount, address(this));\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/LoopPosition.sol:379:9\n    │\n379 │         emit DebtRepaid(config.usds(), repaid);\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/LoopPosition.sol:415:9\n    │\n415 │ ┏         IV3Router(config.router())\n416 │ ┃             .exactInput(IV3Router.ExactInputParams(path, address(this), deadline, amount, minimum));\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/LoopPosition.sol:430:9\n    │\n430 │ ┏         IV3Router(config.router())\n431 │ ┃             .exactOutput(IV3Router.ExactOutputParams(path, address(this), deadline, amount, maximum));\n    │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LoopPosition.sol:467:22\n    │\n467 │         if (amount > uint256(type(int256).max)) revert InvalidInput();\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/LoopPosition.sol:468:16\n    │\n468 │         return int256(amount);\n    │                ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LoopPosition.sol:473:16\n    │\n473 │         return uint128(amount);\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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/LoopPosition.sol:477:13\n    │\n477 │         if (block.timestamp > deadline) revert Expired();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\n","passed":true},{"durationMs":214,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/Loop.t.sol:LaunchTokenTest\n[PASS] testSupplyTransferAndNoMint() (gas: 113863)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 430.81µs (281.14µs CPU time)\n\nRan 1 test for test/Adapters.t.sol:CompositeFeedTest\n[PASS] testCompositePriceIncludesWrappedBitcoinBasisAndFreshness() (gas: 1172117)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 993.51µs (839.48µs CPU time)\n\nRan 11 tests for test/Adapters.t.sol:AdapterTest\n[PASS] testAdapterDonationsCannotBeTakenBySwap() (gas: 307045)\n[PASS] testBoundedV3AndCurveExactOutputRefundsUnspentInput() (gas: 428713)\n[PASS] testCurveApproximateInverseIsVerifiedBeforeSwapping() (gas: 502349)\n[PASS] testCurveOnlyBothDirections() (gas: 410538)\n[PASS] testCurveThenV3ExactInput() (gas: 398386)\n[PASS] testFuzzExactOutputBounds(uint96) (runs: 256, μ: 426224, ~: 426298)\nLogs:\n  Bound result 99999999999000000001113\n\n[PASS] testMalformedRoutesAndWrongCurveEndpoints() (gas: 115441)\n[PASS] testPureV3Passthrough() (gas: 387033)\n[PASS] testRouterRuntimeWithinLaunchConstraints() (gas: 3030716)\n[PASS] testSlippageAndAllowanceRevocation() (gas: 302425)\n[PASS] testV3ThenCurveExactInput() (gas: 393763)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 122.10ms (34.30ms CPU time)\n\nRan 43 tests for test/Loop.t.sol:LoopTest\n[PASS] testAccruedDebtsAndRepaymentFeePaidFromCapital() (gas: 1713132)\n[PASS] testAnyRoutableErc20SixDecimalsAndFullExitToSameToken() (gas: 1741058)\n[PASS] testApprovedNftOperatorCannotSpendPositionFunds() (gas: 933896)\n[PASS] testAuthorizedOwnerCallbackHitsReentrancyGuard() (gas: 1583975)\n[PASS] testCoolerMinimumAndMaxBorrow() (gas: 1744795)\n[PASS] testDeadlineAndZeroAmount() (gas: 151365)\n[PASS] testDebtTokenMigrationCanExitAfterExternalFullRepayment() (gas: 1547733)\n[PASS] testDependencyChangesFailClosed() (gas: 251246)\n[PASS] testDeploymentRuntimeHasNoEscapeOpcodes() (gas: 35300370)\n[PASS] testDepositLoopAndReceipt() (gas: 951220)\n[PASS] testDepositWithTransactionWideFxLock() (gas: 2900623)\n[PASS] testDirectFxBurnCannotExceedRepaymentBudget() (gas: 1720592)\n[PASS] testDonationsRecoverableBeforeAndAfterBurn() (gas: 1768556)\n[PASS] testEntryCallbackPreservesDynamicRoutesWithNoncanonicalInputOffsets() (gas: 1221608)\n[PASS] testEntryFlashCallbackFailuresRollback() (gas: 3598934)\n[PASS] testEntryRejectsShortCoolerDisbursementEvenWithIdleFunds() (gas: 1081101)\n[PASS] testEntryRequiresFlashLiquidityAndPreservesIdleUsds() (gas: 1224938)\n[PASS] testExitSlippageAndUnderfundingAreAtomic() (gas: 2567731)\n[PASS] testFeeOnTransferDepositRejected() (gas: 200549)\n[PASS] testFullLoopAndUnwindThroughCurveBridge() (gas: 8483758)\n[PASS] testFullUnwindConservesCapitalAndFlashLiquidity() (gas: 1715544)\n[PASS] testFullyLiquidatedPositionCanCloseWithExplicitZeroReturn() (gas: 1030955)\n[PASS] testFuzzRepeatedLoopsConserveCapital(uint96,uint8) (runs: 256, μ: 2453100, ~: 2311076)\nLogs:\n  Bound result 2\n  Bound result 1\n\n[PASS] testIndependentPositions() (gas: 7137457)\n[PASS] testInitialBorrowMustBeNearFiftyPercent() (gas: 1108365)\n[PASS] testInsufficientReinvestmentRevertsEverything() (gas: 983787)\n[PASS] testInvalidAndStaleFeed() (gas: 391149)\n[PASS] testLenderCannotSkipCallbackOrLieAboutAmountOrFunding() (gas: 2275280)\n[PASS] testOtherUsersCannotBurnOrWithdraw() (gas: 903102)\n[PASS] testOwnerCanReduceRiskWithStaleOracle() (gas: 1255450)\n[PASS] testPoolOracleAlsoEnforcesFinalLtv() (gas: 992018)\n[PASS] testReceiptTransferMovesAllRights() (gas: 1646956)\n[PASS] testRejectsWrongPathEndpointsAndMalformedPath() (gas: 1116488)\n[PASS] testRepeatedDeposits() (gas: 1449145)\n[PASS] testSupplyAndBorrowFeesRequireAdjustedQuote() (gas: 1452614)\n[PASS] testSwapCannotReenterUnwind() (gas: 1442997)\n[PASS] testSwapCannotTransferReceiptMidOperation() (gas: 1049103)\n[PASS] testSwapFailureAndMisreportedOutputRollback() (gas: 983115)\n[PASS] testTaxedOutputCannotUndercutWalletMinimum() (gas: 1814514)\n[PASS] testTopUpCanCoverMarketLossOnExit() (gas: 1530134)\n[PASS] testUnauthorizedAndReplayedCallbackRejected() (gas: 1705375)\n[PASS] testUnwindWithoutFlashLoanUsesOwnerBridgeFunds() (gas: 1446955)\n[PASS] testWarmupOrCoolerBorrowFailureRollsBack() (gas: 1708297)\nSuite result: ok. 43 passed; 0 failed; 0 skipped; finished in 122.29ms (251.56ms CPU time)\n\nRan 4 test suites in 123.81ms (245.82ms CPU time): 56 tests passed, 0 failed, 0 skipped (56 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"55d68e99a6e3fc4f734560f92bbe40daa7da4de077dfffeb1ab9566e8a961998","verifiedTreeHash":"e27a7b3ce368514e37ebb0c4f3c91db3d57d6e41","verifierVersion":"0.1.0+e4d213a5"},{"checks":[{"durationMs":18260,"exitCode":0,"name":"build","output":"Compiling 53 files with Solc 0.8.26\nSolc 0.8.26 finished in 18.14s\nCompiler run successful!\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/LoopAccountDeployer.sol:10:17\n   │\n10 │     constructor(address config_) {\n   │                 ━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/WbtcUsdFeed.sol:33:35\n   │\n33 │         if (value == 0 || value > uint256(type(int256).max)) revert InvalidPrice();\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/LoopConfig.sol:33:9\n   │\n33 │         address cooler_,\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/LoopConfig.sol:28:9\n   │\n28 │         address ohm_,\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/LoopConfig.sol:31:9\n   │\n31 │         address manager_,\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/LoopConfig.sol:34:9\n   │\n34 │         address staking_,\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/LoopConfig.sol:35:9\n   │\n35 │         address router_,\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/LoopConfig.sol:32:9\n   │\n32 │         address pool_,\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/LoopConfig.sol:36:9\n   │\n36 │         address morpho_,\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/LoopConfig.sol:29:9\n   │\n29 │         address gohm_,\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/LoopConfig.sol:37:9\n   │\n37 │         address priceFeed_,\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/LoopConfig.sol:26:9\n   │\n26 │         address wbtc_,\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/LoopConfig.sol:27:9\n   │\n27 │         address fxUSD_,\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/LoopConfig.sol:30:9\n   │\n30 │         address usds_,\n   │         ━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/WbtcUsdFeed.sol:35:20\n   │\n35 │         return (1, int256(value), timestamp, timestamp, 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/LoopConfig.sol:44:51\n   │\n44 │             if (dependencies[i].code.length == 0) revert InvalidConfiguration();\n   │                                                   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/WbtcUsdFeed.sol:41:44\n   │\n41 │             answer <= 0 || updated == 0 || updated > block.timestamp || answeredRound < round\n   │                                            ━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/WbtcUsdFeed.sol:42:20\n   │\n42 │                 || block.timestamp - updated > maxAge\n   │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n   ╭▸ src/LoopConfig.sol:46:57\n   │\n46 │                 if (dependencies[i] == dependencies[j]) revert InvalidConfiguration();\n   │                                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/FxSwapRouter.sol:34:67\n   │\n34 │     constructor(address router_, address quoter_, address curve_, address fxUSD_, address usdc_) {\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/FxSwapRouter.sol:34:51\n   │\n34 │     constructor(address router_, address quoter_, address curve_, address fxUSD_, address usdc_) {\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/FxSwapRouter.sol:34:34\n   │\n34 │     constructor(address router_, address quoter_, address curve_, address fxUSD_, address usdc_) {\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/FxSwapRouter.sol:34:83\n   │\n34 │     constructor(address router_, address quoter_, address curve_, address fxUSD_, address usdc_) {\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/FxSwapRouter.sol:34:17\n   │\n34 │     constructor(address router_, address quoter_, address curve_, address fxUSD_, address usdc_) {\n   │                 ━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unused-return]: return value of an external call is not used\n   ╭▸ src/WbtcUsdFeed.sol:39:81\n   │\n39 │         (uint80 round, int256 answer,, uint256 updated, uint80 answeredRound) = feed.latestRoundData();\n   │                                                                                 ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/WbtcUsdFeed.sol:44:17\n   │\n44 │         return (uint256(answer), updated);\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-oz-erc721-mint]: `ERC721._mint` does not check that the recipient can receive the token; use `_safeMint`\n   ╭▸ src/LoopReceipt.sol:30:9\n   │\n30 │         _mint(msg.sender, id);\n   │         ━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-oz-erc721-mint\n\nwarning[missing-events-access-control]: `pendingHash` is changed without an event but is used for access control\n    ╭▸ src/LoopPosition.sol:280:9\n    │\n280 │         pendingHash = keccak256(data);\n    │         ━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-events-access-control]: `pendingAssets` is changed without an event but is used for access control\n    ╭▸ src/LoopPosition.sol:281:9\n    │\n281 │         pendingAssets = assets;\n    │         ━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[missing-events-access-control]: `flashBalanceBefore` is changed without an event but is used for access control\n    ╭▸ src/LoopPosition.sol:282:9\n    │\n282 │         flashBalanceBefore = _balance(config.usds());\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/LoopReceipt.sol:31:9\n   │\n31 │         emit PositionCreated(msg.sender, id, account);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/LoopPosition.sol:124:46\n    │\n124 │             answer <= 0 || updatedAt == 0 || updatedAt > block.timestamp || answeredInRound < round\n    │                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/LoopPosition.sol:125:20\n    │\n125 │                 || block.timestamp - updatedAt > config.maxPriceAge()\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/LoopPosition.sol:122:13\n    │\n122 │             IPriceFeed(config.priceFeed()).latestRoundData();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LoopPosition.sol:127:16\n    │\n127 │         return uint256(answer) * 1e10;\n    │                ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-no-eth]: external call can be reentered before `state` is updated\n    ╭▸ src/LoopPosition.sol:400:9\n    │\n400 │ ┏         IV3Router(config.router())\n401 │ ┃             .exactInput(IV3Router.ExactInputParams(path, address(this), deadline, amount, minimum));\n    │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `state` is updated\n    ╭▸ src/LoopPosition.sol:284:9\n    │\n284 │         IMorpho(config.morpho()).flashLoan(config.usds(), assets, data);\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/LoopPosition.sol:164:9\n    │\n164 │ ┏         emit Deposited(\n165 │ ┃             msg.sender,\n166 │ ┃             p.token,\n167 │ ┃             p.amount,\n    ‡ ┃\n170 │ ┃             ICooler(config.cooler()).accountPosition(address(this)).currentDebt\n171 │ ┃         );\n    │ ┗━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `entered` is updated\n    ╭▸ src/FxSwapRouter.sol:142:9\n    │\n142 │         IV3Router(v3Router).exactInput(ExactInputParams(path, address(this), deadline, amount, minimum));\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/FxSwapRouter.sol:168:9\n    │\n168 │         ICurveFxPool(curve).exchange(i, j, amount, minimum, address(this));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/LoopPosition.sol:180:9\n    │\n180 │         IStaking(config.staking()).stake(address(this), ohmReceived, false, true);\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/LoopPosition.sol:188:9\n    │\n188 │         ICooler(config.cooler()).borrow(p.coolerBorrow, address(this), address(this));\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/FxSwapRouter.sol:156:9\n    │\n156 │         IV3Router(v3Router).exactOutput(ExactOutputParams(path, address(this), deadline, amount, maximum));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `fxPositionId` is updated\n    ╭▸ src/LoopPosition.sol:378:22\n    │\n378 │         uint256 id = IFxManager(config.manager()).operate(config.pool(), fxPositionId, collateral, debt);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `fxPositionId` is updated\n    ╭▸ src/LoopPosition.sol:415:9\n    │\n415 │ ┏         IV3Router(config.router())\n416 │ ┃             .exactOutput(IV3Router.ExactOutputParams(path, address(this), deadline, amount, maximum));\n    │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/FxSwapRouter.sol:142:9\n    │\n142 │         IV3Router(v3Router).exactInput(ExactInputParams(path, address(this), deadline, amount, minimum));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `closed` is updated\n    ╭▸ src/LoopPosition.sol:297:13\n    │\n297 │             ICooler(config.cooler()).repay(_u128(cp.currentDebt), address(this));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `closed` is updated\n    ╭▸ src/LoopPosition.sol:301:13\n    │\n301 │ ┏             ICooler(config.cooler())\n302 │ ┃                 .withdrawCollateral(\n303 │ ┃                     _u128(cp.collateral), address(this), address(this), new ICooler.DelegationRequest[](0)\n304 │ ┃                 );\n    │ ┗━━━━━━━━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/FxSwapRouter.sol:156:9\n    │\n156 │         IV3Router(v3Router).exactOutput(ExactOutputParams(path, address(this), deadline, amount, maximum));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `closed` is updated\n    ╭▸ src/LoopPosition.sol:310:13\n    │\n310 │             IStaking(config.staking()).unstake(address(this), gohmBalance, false, false);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `closed` is updated\n    ╭▸ src/LoopPosition.sol:400:9\n    │\n400 │ ┏         IV3Router(config.router())\n401 │ ┃             .exactInput(IV3Router.ExactInputParams(path, address(this), deadline, amount, minimum));\n    │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/FxSwapRouter.sol:168:9\n    │\n168 │         ICurveFxPool(curve).exchange(i, j, amount, minimum, address(this));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FxSwapRouter.sol:191:14\n    │\n191 │         if (!sufficient) revert SwapFailed();\n    │              ━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FxSwapRouter.sol:192:25\n    │\n192 │         for (uint256 i; i < 16 && high - low > 1; ++i) {\n    │                         ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[reentrancy-no-eth]: external call can be reentered before `state` is updated\n    ╭▸ src/LoopPosition.sol:243:9\n    │\n243 │         receipt.burn(receiptId);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FxSwapRouter.sol:184:17\n    │\n184 │             if (ICurveFxPool(curve).get_dy(0, 1, high) >= output) {\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/FxSwapRouter.sol:194:17\n    │\n194 │             if (ICurveFxPool(curve).get_dy(0, 1, mid) >= output) high = mid;\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/FxSwapRouter.sol:216:31\n    │\n216 │         if (msg.value != 0 || block.timestamp > deadline || recipient == address(0) || recipient == address(this)) {\n    │                               ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FxSwapRouter.sol:226:30\n    │\n226 │         for (uint256 offset; offset < path.length - 20; offset += 23) {\n    │                              ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/FxSwapRouter.sol:240:19\n    │\n240 │                 ) revert InvalidRoute();\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/FxSwapRouter.sol:242:17\n    │\n242 │                 revert InvalidRoute();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-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/LoopPosition.sol:253:9\n    │\n253 │         emit Closed(msg.sender, p.outputToken, output);\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/LoopPosition.sol:297:13\n    │\n297 │             ICooler(config.cooler()).repay(_u128(cp.currentDebt), address(this));\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/LoopPosition.sol:301:13\n    │\n301 │ ┏             ICooler(config.cooler())\n302 │ ┃                 .withdrawCollateral(\n303 │ ┃                     _u128(cp.collateral), address(this), address(this), new ICooler.DelegationRequest[](0)\n304 │ ┃                 );\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/LoopPosition.sol:310:13\n    │\n310 │             IStaking(config.staking()).unstake(address(this), gohmBalance, false, false);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/LoopPosition.sol:347:9\n    │\n347 │         emit CollateralAdded(amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/LoopPosition.sol:355:9\n    │\n355 │         emit DebtRepaid(config.fxUSD(), debtAmount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `state` is updated\n    ╭▸ src/LoopPosition.sol:362:26\n    │\n362 │         uint128 repaid = ICooler(config.cooler()).repay(amount, address(this));\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/LoopPosition.sol:364:9\n    │\n364 │         emit DebtRepaid(config.usds(), repaid);\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/LoopPosition.sol:400:9\n    │\n400 │ ┏         IV3Router(config.router())\n401 │ ┃             .exactInput(IV3Router.ExactInputParams(path, address(this), deadline, amount, minimum));\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/LoopPosition.sol:415:9\n    │\n415 │ ┏         IV3Router(config.router())\n416 │ ┃             .exactOutput(IV3Router.ExactOutputParams(path, address(this), deadline, amount, maximum));\n    │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LoopPosition.sol:452:22\n    │\n452 │         if (amount > uint256(type(int256).max)) revert InvalidInput();\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/LoopPosition.sol:453:16\n    │\n453 │         return int256(amount);\n    │                ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LoopPosition.sol:458:16\n    │\n458 │         return uint128(amount);\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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/LoopPosition.sol:462:13\n    │\n462 │         if (block.timestamp > deadline) revert Expired();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\n","passed":true},{"durationMs":203,"exitCode":1,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/Loop.t.sol:LaunchTokenTest\n[PASS] testSupplyTransferAndNoMint() (gas: 113863)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 385.19µs (229.44µs CPU time)\n\nRan 1 test for test/Adapters.t.sol:CompositeFeedTest\n[PASS] testCompositePriceIncludesWrappedBitcoinBasisAndFreshness() (gas: 1172117)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 928.81µs (789.75µs CPU time)\n\nRan 11 tests for test/Adapters.t.sol:AdapterTest\n[PASS] testAdapterDonationsCannotBeTakenBySwap() (gas: 307045)\n[PASS] testBoundedV3AndCurveExactOutputRefundsUnspentInput() (gas: 428713)\n[PASS] testCurveApproximateInverseIsVerifiedBeforeSwapping() (gas: 502349)\n[PASS] testCurveOnlyBothDirections() (gas: 410538)\n[PASS] testCurveThenV3ExactInput() (gas: 398386)\n[PASS] testFuzzExactOutputBounds(uint96) (runs: 256, μ: 426218, ~: 426298)\nLogs:\n  Bound result 99999999999000003004050\n\n[PASS] testMalformedRoutesAndWrongCurveEndpoints() (gas: 115441)\n[PASS] testPureV3Passthrough() (gas: 387033)\n[PASS] testRouterRuntimeWithinLaunchConstraints() (gas: 3030716)\n[PASS] testSlippageAndAllowanceRevocation() (gas: 302425)\n[PASS] testV3ThenCurveExactInput() (gas: 393763)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 125.13ms (40.02ms CPU time)\n\nRan 44 tests for test/Loop.t.sol:LoopTest\n[PASS] testAccruedDebtsAndRepaymentFeePaidFromCapital() (gas: 1730886)\n[PASS] testAnyRoutableErc20SixDecimalsAndFullExitToSameToken() (gas: 1759625)\n[PASS] testApprovedNftOperatorCannotSpendPositionFunds() (gas: 942794)\n[PASS] testAuthorizedOwnerCallbackHitsReentrancyGuard() (gas: 1592834)\n[PASS] testCoolerMinimumAndMaxBorrow() (gas: 1767914)\n[PASS] testDeadlineAndZeroAmount() (gas: 153403)\n[PASS] testDebtTokenMigrationCanExitAfterExternalFullRepayment() (gas: 1565346)\n[PASS] testDependencyChangesFailClosed() (gas: 255293)\n[PASS] testDeploymentRuntimeHasNoEscapeOpcodes() (gas: 39595037)\n[PASS] testDepositLoopAndReceipt() (gas: 962631)\n[FAIL: Error != expected error: ERC20InsufficientAllowance(0x03A6a84cD762D9707A21605b548aaaB891562aAb, 0, 1) != ErrorPoolManagerLocked()] testDepositWithTransactionWideFxLock() (gas: 1288068)\n[PASS] testDirectFxBurnCannotExceedRepaymentBudget() (gas: 1741230)\n[PASS] testDonationsRecoverableBeforeAndAfterBurn() (gas: 1786367)\n[PASS] testEntryCallbackPreservesOriginalDynamicArgumentOffsets() (gas: 1262410)\n[PASS] testEntryFlashCallbackFailuresRollback() (gas: 4934998)\n[PASS] testEntryRejectsShortCoolerDisbursementEvenWithIdleFunds() (gas: 955486)\n[PASS] testEntryRequiresFlashLiquidityAndPreservesIdleUsds() (gas: 1203643)\n[PASS] testExitSlippageAndUnderfundingAreAtomic() (gas: 2602745)\n[PASS] testFeeOnTransferDepositRejected() (gas: 191092)\n[PASS] testFullLoopAndUnwindThroughCurveBridge() (gas: 8611689)\n[PASS] testFullUnwindConservesCapitalAndFlashLiquidity() (gas: 1735561)\n[PASS] testFullyLiquidatedPositionCanCloseWithExplicitZeroReturn() (gas: 1045903)\n[PASS] testFuzzRepeatedLoopsConserveCapital(uint96,uint8) (runs: 256, μ: 2469278, ~: 2342796)\nLogs:\n  Bound result 2\n  Bound result 1\n\n[PASS] testIndependentPositions() (gas: 7274372)\n[PASS] testInitialBorrowMustBeNearFiftyPercent() (gas: 1121078)\n[PASS] testInsufficientReinvestmentRevertsEverything() (gas: 994501)\n[PASS] testInvalidAndStaleFeed() (gas: 622016)\n[PASS] testLenderCannotSkipCallbackOrLieAboutAmountOrFunding() (gas: 2305263)\n[PASS] testOtherUsersCannotBurnOrWithdraw() (gas: 911919)\n[PASS] testOwnerCanReduceRiskWithStaleOracle() (gas: 1271776)\n[PASS] testPoolOracleAlsoEnforcesFinalLtv() (gas: 1003091)\n[PASS] testReceiptTransferMovesAllRights() (gas: 1664740)\n[PASS] testRejectsWrongPathEndpointsAndMalformedPath() (gas: 1128408)\n[PASS] testRepeatedDeposits() (gas: 1469628)\n[FAIL: next call did not revert as expected] testRepeatedDepositsAndExitWithTransactionWideFxLock() (gas: 1837752)\n[PASS] testSupplyAndBorrowFeesRequireAdjustedQuote() (gas: 1470312)\n[PASS] testSwapCannotReenterUnwind() (gas: 1451969)\n[PASS] testSwapCannotTransferReceiptMidOperation() (gas: 1058079)\n[PASS] testSwapFailureAndMisreportedOutputRollback() (gas: 983004)\n[PASS] testTaxedOutputCannotUndercutWalletMinimum() (gas: 1835055)\n[PASS] testTopUpCanCoverMarketLossOnExit() (gas: 1548043)\n[PASS] testUnauthorizedAndReplayedCallbackRejected() (gas: 1728427)\n[PASS] testUnwindWithoutFlashLoanUsesOwnerBridgeFunds() (gas: 1462949)\n[PASS] testWarmupOrCoolerBorrowFailureRollsBack() (gas: 1726778)\nSuite result: FAILED. 42 passed; 2 failed; 0 skipped; finished in 125.20ms (248.23ms CPU time)\n\nRan 4 test suites in 126.10ms (251.65ms CPU time): 55 tests passed, 2 failed, 0 skipped (57 total tests)\n\nFailing tests:\nEncountered 2 failing tests in test/Loop.t.sol:LoopTest\n[FAIL: Error != expected error: ERC20InsufficientAllowance(0x03A6a84cD762D9707A21605b548aaaB891562aAb, 0, 1) != ErrorPoolManagerLocked()] testDepositWithTransactionWideFxLock() (gas: 1288068)\n[FAIL: next call did not revert as expected] testRepeatedDepositsAndExitWithTransactionWideFxLock() (gas: 1837752)\n\nEncountered a total of 2 failing tests, 55 tests succeeded\n\nTip: Run `forge test --rerun` to retry only the 2 failed tests\nTip: Run `forge test --debug --match-test <TEST_NAME>` to inspect one failing test in the debugger\n","passed":false}],"detail":"test failed with exit code 1","evaluation":"checks","profile":"foundry","status":"rejected","submissionHash":"83c690683a1962a2418ed9eef668957a4e0d0af0a1bf3a9e4be5a09489e34de5","verifiedTreeHash":"349d1a7f26c2dbfa64422d3cedebaae684ff3ca9","verifierVersion":"0.1.0+e4d213a5"},{"checks":[{"durationMs":20743,"exitCode":0,"name":"build","output":"Compiling 53 files with Solc 0.8.26\nSolc 0.8.26 finished in 20.67s\nCompiler run successful!\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/WbtcUsdFeed.sol:41:44\n   │\n41 │             answer <= 0 || updated == 0 || updated > block.timestamp || answeredRound < round\n   │                                            ━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/WbtcUsdFeed.sol:42:20\n   │\n42 │                 || block.timestamp - updated > maxAge\n   │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ test/mocks/Protocols.mock.sol:341:17\n    │\n341 │         require(block.timestamp <= p.deadline);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ test/mocks/Protocols.mock.sol:353:17\n    │\n353 │         require(block.timestamp <= p.deadline);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Adapters.t.sol:43:9\n   │\n43 │         IERC20(coins[uint128(i)]).transferFrom(msg.sender, address(this), dx);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n   ╭▸ test/Adapters.t.sol:43:22\n   │\n43 │         IERC20(coins[uint128(i)]).transferFrom(msg.sender, address(this), dx);\n   │                      ━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint128' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Adapters.t.sol:44:9\n   │\n44 │         IERC20(coins[uint128(j)]).transfer(recipient, dy);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n   ╭▸ test/Adapters.t.sol:44:22\n   │\n44 │         IERC20(coins[uint128(j)]).transfer(recipient, dy);\n   │                      ━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint128' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/FxSwapRouter.sol:216:31\n    │\n216 │         if (msg.value != 0 || block.timestamp > deadline || recipient == address(0) || recipient == address(this)) {\n    │                               ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n   ╭▸ src/WbtcUsdFeed.sol:35:20\n   │\n35 │         return (1, int256(value), timestamp, timestamp, 1);\n   │                    ━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'int256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n   ╭▸ src/WbtcUsdFeed.sol:44:17\n   │\n44 │         return (uint256(answer), updated);\n   │                 ━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:123:31\n    │\n123 │             collateral[id] += uint256(c) * 1e10;\n    │                               ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/Loop.t.sol:652:26\n    │\n652 │         d.coolerBorrow = uint128(uint256(d.coolerBorrow) * units);\n    │                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:125:74\n    │\n125 │             withdrawal = c == type(int256).min ? collateral[id] / 1e10 : uint256(-c);\n    │                                                                          ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:129:25\n    │\n129 │             debt[id] += uint256(d);\n    │                         ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/Loop.t.sol:695:9\n    │\n695 │         token.transfer(address(0xBEEF), 1e18);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:131:66\n    │\n131 │             repaid = d == type(int256).min ? debt[id] : Math.min(uint256(-d), debt[id]);\n    │                                                                  ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/LoopPosition.sol:122:46\n    │\n122 │             answer <= 0 || updatedAt == 0 || updatedAt > block.timestamp || answeredInRound < round\n    │                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/LoopPosition.sol:123:20\n    │\n123 │                 || block.timestamp - updatedAt > config.maxPriceAge()\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:135:30\n    │\n135 │         if (withdrawal != 0) IERC20(collateralToken).transfer(caller, withdrawal);\n    │                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:174:13\n    │\n174 │             IERC20(pool.collateralToken()).transferFrom(msg.sender, address(pool), uint256(c));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:174:84\n    │\n174 │             IERC20(pool.collateralToken()).transferFrom(msg.sender, address(pool), uint256(c));\n    │                                                                                    ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:175:18\n    │\n175 │             c -= int256(uint256(c) * supplyFeeBps / 10000);\n    │                  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:175:25\n    │\n175 │             c -= int256(uint256(c) * supplyFeeBps / 10000);\n    │                         ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:179:43\n    │\n179 │         if (d > 0) token.mint(msg.sender, uint256(d) - uint256(d) * borrowFeeBps / 10000);\n    │                                           ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:179:56\n    │\n179 │         if (d > 0) token.mint(msg.sender, uint256(d) - uint256(d) * borrowFeeBps / 10000);\n    │                                                        ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:201:9\n    │\n201 │         IERC20(OHM).transferFrom(msg.sender, address(this), amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:209:9\n    │\n209 │         IERC20(gOHM).transferFrom(msg.sender, address(this), amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:212:9\n    │\n212 │         IERC20(OHM).transfer(to, out);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/LoopPosition.sol:436:13\n    │\n436 │         if (block.timestamp > deadline) revert Expired();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:259:9\n    │\n259 │         IERC20(collateralToken).transferFrom(msg.sender, address(this), amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:267:9\n    │\n267 │         IERC20(debtToken).transfer(to, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:274:9\n    │\n274 │         IERC20(debtToken).transferFrom(msg.sender, address(this), paid);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:277:16\n    │\n277 │         return uint128(paid);\n    │                ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:287:9\n    │\n287 │         IERC20(collateralToken).transfer(to, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LoopPosition.sol:125:16\n    │\n125 │         return uint256(answer) * 1e10;\n    │                ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:343:9\n    │\n343 │         IERC20(from).transferFrom(msg.sender, address(this), p.amountIn);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:349:19\n    │\n349 │         if (!lie) IERC20(to).transfer(p.recipient, out);\n    │                   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:359:9\n    │\n359 │         IERC20(from).transferFrom(msg.sender, address(this), used);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:361:19\n    │\n361 │         if (!lie) IERC20(to).transfer(p.recipient, p.amountOut);\n    │                   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:379:24\n    │\n379 │         if (mode != 4) IERC20(token).transfer(msg.sender, assets);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:382:9\n    │\n382 │         IERC20(token).transferFrom(msg.sender, address(this), assets);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LoopPosition.sol:427:16\n    │\n427 │         return int256(amount);\n    │                ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LoopPosition.sol:432:16\n    │\n432 │         return uint128(amount);\n    │                ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\n","passed":true},{"durationMs":204,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/Loop.t.sol:LaunchTokenTest\n[PASS] testSupplyTransferAndNoMint() (gas: 459866)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 380.86µs (134.67µs CPU time)\n\nRan 1 test for test/Adapters.t.sol:CompositeFeedTest\n[PASS] testCompositePriceIncludesWrappedBitcoinBasisAndFreshness() (gas: 1061088)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 974.67µs (728.53µs CPU time)\n\nRan 11 tests for test/Adapters.t.sol:AdapterTest\n[PASS] testAdapterDonationsCannotBeTakenBySwap() (gas: 160429)\n[PASS] testBoundedV3AndCurveExactOutputRefundsUnspentInput() (gas: 268292)\n[PASS] testCurveApproximateInverseIsVerifiedBeforeSwapping() (gas: 320970)\n[PASS] testCurveOnlyBothDirections() (gas: 265496)\n[PASS] testCurveThenV3ExactInput() (gas: 272719)\n[PASS] testFuzzExactOutputBounds(uint96) (runs: 256, μ: 267606, ~: 267655)\nLogs:\n  Bound result 8401237942584438256\n\n[PASS] testMalformedRoutesAndWrongCurveEndpoints() (gas: 26369)\n[PASS] testPureV3Passthrough() (gas: 259990)\n[PASS] testRouterRuntimeWithinLaunchConstraints() (gas: 3030716)\n[PASS] testSlippageAndAllowanceRevocation() (gas: 226645)\n[PASS] testV3ThenCurveExactInput() (gas: 252119)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 124.01ms (33.94ms CPU time)\n\nRan 38 tests for test/Loop.t.sol:LoopTest\n[PASS] testAccruedDebtsAndRepaymentFeePaidFromCapital() (gas: 1268631)\n[PASS] testAnyRoutableErc20SixDecimalsAndFullExitToSameToken() (gas: 1389037)\n[PASS] testApprovedNftOperatorCannotSpendPositionFunds() (gas: 745922)\n[PASS] testAuthorizedOwnerCallbackHitsReentrancyGuard() (gas: 1243191)\n[PASS] testCoolerMinimumAndMaxBorrow() (gas: 1053608)\n[PASS] testDeadlineAndZeroAmount() (gas: 99993)\n[PASS] testDebtTokenMigrationCanExitAfterExternalFullRepayment() (gas: 1141904)\n[PASS] testDependencyChangesFailClosed() (gas: 119049)\n[PASS] testDeploymentRuntimeHasNoEscapeOpcodes() (gas: 33194834)\n[PASS] testDepositLoopAndReceipt() (gas: 740634)\n[PASS] testDirectFxBurnCannotExceedRepaymentBudget() (gas: 1181650)\n[PASS] testDonationsRecoverableBeforeAndAfterBurn() (gas: 1355948)\n[PASS] testExitSlippageAndUnderfundingAreAtomic() (gas: 1767443)\n[PASS] testFeeOnTransferDepositRejected() (gas: 148391)\n[PASS] testFullLoopAndUnwindThroughCurveBridge() (gas: 14032200)\n[PASS] testFullUnwindConservesCapitalAndFlashLiquidity() (gas: 1278145)\n[PASS] testFullyLiquidatedPositionCanCloseWithExplicitZeroReturn() (gas: 788276)\n[PASS] testFuzzRepeatedLoopsConserveCapital(uint96,uint8) (runs: 256, μ: 1772474, ~: 1667300)\nLogs:\n  Bound result 10\n  Bound result 4\n\n[PASS] testIndependentPositions() (gas: 5764830)\n[PASS] testInitialBorrowMustBeNearFiftyPercent() (gas: 575778)\n[PASS] testInsufficientReinvestmentRevertsEverything() (gas: 680568)\n[PASS] testInvalidAndStaleFeed() (gas: 122125)\n[PASS] testLenderCannotSkipCallbackOrLieAboutAmountOrFunding() (gas: 1551856)\n[PASS] testOtherUsersCannotBurnOrWithdraw() (gas: 716762)\n[PASS] testOwnerCanReduceRiskWithStaleOracle() (gas: 956610)\n[PASS] testPoolOracleAlsoEnforcesFinalLtv() (gas: 681370)\n[PASS] testReceiptTransferMovesAllRights() (gas: 1293588)\n[PASS] testRejectsWrongPathEndpointsAndMalformedPath() (gas: 584451)\n[PASS] testRepeatedDeposits() (gas: 1093585)\n[PASS] testSupplyAndBorrowFeesRequireAdjustedQuote() (gas: 994159)\n[PASS] testSwapCannotReenterUnwind() (gas: 1186151)\n[PASS] testSwapCannotTransferReceiptMidOperation() (gas: 845627)\n[PASS] testSwapFailureAndMisreportedOutputRollback() (gas: 694638)\n[PASS] testTaxedOutputCannotUndercutWalletMinimum() (gas: 1339156)\n[PASS] testTopUpCanCoverMarketLossOnExit() (gas: 1257339)\n[PASS] testUnauthorizedAndReplayedCallbackRejected() (gas: 1266171)\n[PASS] testUnwindWithoutFlashLoanUsesOwnerBridgeFunds() (gas: 1131102)\n[PASS] testWarmupOrCoolerBorrowFailureRollsBack() (gas: 950168)\nSuite result: ok. 38 passed; 0 failed; 0 skipped; finished in 124.10ms (235.09ms CPU time)\n\nRan 4 test suites in 126.43ms (249.47ms CPU time): 51 tests passed, 0 failed, 0 skipped (51 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"d0f9ecdc070f47056abcc6da64f0ea3ba77e5ef9d51ca8a449cbe144eb9e2b7a","verifiedTreeHash":"5c8adcfc6db08f279971ac8047360af354f9cc3b","verifierVersion":"0.1.0+ff982c0f"},{"checks":[{"durationMs":20181,"exitCode":0,"name":"build","output":"Compiling 53 files with Solc 0.8.26\nSolc 0.8.26 finished in 20.11s\nCompiler run successful!\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/WbtcUsdFeed.sol:41:44\n   │\n41 │             answer <= 0 || updated == 0 || updated > block.timestamp || answeredRound < round\n   │                                            ━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/WbtcUsdFeed.sol:42:20\n   │\n42 │                 || block.timestamp - updated > maxAge\n   │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Adapters.t.sol:43:9\n   │\n43 │         IERC20(coins[uint128(i)]).transferFrom(msg.sender, address(this), dx);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n   ╭▸ src/WbtcUsdFeed.sol:35:20\n   │\n35 │         return (1, int256(value), timestamp, timestamp, 1);\n   │                    ━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'int256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n   ╭▸ src/WbtcUsdFeed.sol:44:17\n   │\n44 │         return (uint256(answer), updated);\n   │                 ━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint256' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n   ╭▸ test/Adapters.t.sol:43:22\n   │\n43 │         IERC20(coins[uint128(i)]).transferFrom(msg.sender, address(this), dx);\n   │                      ━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint128' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n   ╭▸ test/Adapters.t.sol:44:9\n   │\n44 │         IERC20(coins[uint128(j)]).transfer(recipient, dy);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n   ╭▸ test/Adapters.t.sol:44:22\n   │\n44 │         IERC20(coins[uint128(j)]).transfer(recipient, dy);\n   │                      ━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint128' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/LoopPosition.sol:122:46\n    │\n122 │             answer <= 0 || updatedAt == 0 || updatedAt > block.timestamp || answeredInRound < round\n    │                                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/LoopPosition.sol:123:20\n    │\n123 │                 || block.timestamp - updatedAt > config.maxPriceAge()\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/FxSwapRouter.sol:216:31\n    │\n216 │         if (msg.value != 0 || block.timestamp > deadline || recipient == address(0) || recipient == address(this)) {\n    │                               ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/LoopPosition.sol:436:13\n    │\n436 │         if (block.timestamp > deadline) revert Expired();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ test/mocks/Protocols.mock.sol:341:17\n    │\n341 │         require(block.timestamp <= p.deadline);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/Loop.t.sol:652:26\n    │\n652 │         d.coolerBorrow = uint128(uint256(d.coolerBorrow) * units);\n    │                          ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ test/mocks/Protocols.mock.sol:353:17\n    │\n353 │         require(block.timestamp <= p.deadline);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#block-timestamp\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LoopPosition.sol:125:16\n    │\n125 │         return uint256(answer) * 1e10;\n    │                ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/Loop.t.sol:695:9\n    │\n695 │         token.transfer(address(0xBEEF), 1e18);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:123:31\n    │\n123 │             collateral[id] += uint256(c) * 1e10;\n    │                               ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:125:74\n    │\n125 │             withdrawal = c == type(int256).min ? collateral[id] / 1e10 : uint256(-c);\n    │                                                                          ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:129:25\n    │\n129 │             debt[id] += uint256(d);\n    │                         ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:131:66\n    │\n131 │             repaid = d == type(int256).min ? debt[id] : Math.min(uint256(-d), debt[id]);\n    │                                                                  ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LoopPosition.sol:427:16\n    │\n427 │         return int256(amount);\n    │                ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ src/LoopPosition.sol:432:16\n    │\n432 │         return uint128(amount);\n    │                ━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:135:30\n    │\n135 │         if (withdrawal != 0) IERC20(collateralToken).transfer(caller, withdrawal);\n    │                              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:174:13\n    │\n174 │             IERC20(pool.collateralToken()).transferFrom(msg.sender, address(pool), uint256(c));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:174:84\n    │\n174 │             IERC20(pool.collateralToken()).transferFrom(msg.sender, address(pool), uint256(c));\n    │                                                                                    ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:175:18\n    │\n175 │             c -= int256(uint256(c) * supplyFeeBps / 10000);\n    │                  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:175:25\n    │\n175 │             c -= int256(uint256(c) * supplyFeeBps / 10000);\n    │                         ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:179:43\n    │\n179 │         if (d > 0) token.mint(msg.sender, uint256(d) - uint256(d) * borrowFeeBps / 10000);\n    │                                           ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:179:56\n    │\n179 │         if (d > 0) token.mint(msg.sender, uint256(d) - uint256(d) * borrowFeeBps / 10000);\n    │                                                        ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:201:9\n    │\n201 │         IERC20(OHM).transferFrom(msg.sender, address(this), amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:209:9\n    │\n209 │         IERC20(gOHM).transferFrom(msg.sender, address(this), amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:212:9\n    │\n212 │         IERC20(OHM).transfer(to, out);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:259:9\n    │\n259 │         IERC20(collateralToken).transferFrom(msg.sender, address(this), amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:267:9\n    │\n267 │         IERC20(debtToken).transfer(to, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:274:9\n    │\n274 │         IERC20(debtToken).transferFrom(msg.sender, address(this), paid);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[unsafe-typecast]: typecasts that can truncate values should be checked\n    ╭▸ test/mocks/Protocols.mock.sol:277:16\n    │\n277 │         return uint128(paid);\n    │                ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#unsafe-typecast\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:287:9\n    │\n287 │         IERC20(collateralToken).transfer(to, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:343:9\n    │\n343 │         IERC20(from).transferFrom(msg.sender, address(this), p.amountIn);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:349:19\n    │\n349 │         if (!lie) IERC20(to).transfer(p.recipient, out);\n    │                   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:359:9\n    │\n359 │         IERC20(from).transferFrom(msg.sender, address(this), used);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:361:19\n    │\n361 │         if (!lie) IERC20(to).transfer(p.recipient, p.amountOut);\n    │                   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:379:24\n    │\n379 │         if (mode != 4) IERC20(token).transfer(msg.sender, assets);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\nwarning[erc20-unchecked-transfer]: ERC20 'transfer' and 'transferFrom' calls should check the return value\n    ╭▸ test/mocks/Protocols.mock.sol:382:9\n    │\n382 │         IERC20(token).transferFrom(msg.sender, address(this), assets);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://book.getfoundry.sh/reference/forge/forge-lint#erc20-unchecked-transfer\n\n","passed":true},{"durationMs":206,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/Loop.t.sol:LaunchTokenTest\n[PASS] testSupplyTransferAndNoMint() (gas: 459866)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 341.62µs (119.26µs CPU time)\n\nRan 1 test for test/Adapters.t.sol:CompositeFeedTest\n[PASS] testCompositePriceIncludesWrappedBitcoinBasisAndFreshness() (gas: 1061088)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 965.80µs (745.46µs CPU time)\n\nRan 11 tests for test/Adapters.t.sol:AdapterTest\n[PASS] testAdapterDonationsCannotBeTakenBySwap() (gas: 160429)\n[PASS] testBoundedV3AndCurveExactOutputRefundsUnspentInput() (gas: 268292)\n[PASS] testCurveApproximateInverseIsVerifiedBeforeSwapping() (gas: 320970)\n[PASS] testCurveOnlyBothDirections() (gas: 265496)\n[PASS] testCurveThenV3ExactInput() (gas: 272719)\n[PASS] testFuzzExactOutputBounds(uint96) (runs: 256, μ: 267611, ~: 267657)\nLogs:\n  Bound result 99999999999000000002029\n\n[PASS] testMalformedRoutesAndWrongCurveEndpoints() (gas: 26369)\n[PASS] testPureV3Passthrough() (gas: 259990)\n[PASS] testRouterRuntimeWithinLaunchConstraints() (gas: 3030716)\n[PASS] testSlippageAndAllowanceRevocation() (gas: 226645)\n[PASS] testV3ThenCurveExactInput() (gas: 252119)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 24.49ms (30.95ms CPU time)\n\nRan 38 tests for test/Loop.t.sol:LoopTest\n[PASS] testAccruedDebtsAndRepaymentFeePaidFromCapital() (gas: 1268631)\n[PASS] testAnyRoutableErc20SixDecimalsAndFullExitToSameToken() (gas: 1389037)\n[PASS] testApprovedNftOperatorCannotSpendPositionFunds() (gas: 745922)\n[PASS] testAuthorizedOwnerCallbackHitsReentrancyGuard() (gas: 1243191)\n[PASS] testCoolerMinimumAndMaxBorrow() (gas: 1053608)\n[PASS] testDeadlineAndZeroAmount() (gas: 99993)\n[PASS] testDebtTokenMigrationCanExitAfterExternalFullRepayment() (gas: 1141904)\n[PASS] testDependencyChangesFailClosed() (gas: 119049)\n[PASS] testDeploymentRuntimeHasNoEscapeOpcodes() (gas: 33194834)\n[PASS] testDepositLoopAndReceipt() (gas: 740634)\n[PASS] testDirectFxBurnCannotExceedRepaymentBudget() (gas: 1181650)\n[PASS] testDonationsRecoverableBeforeAndAfterBurn() (gas: 1355948)\n[PASS] testExitSlippageAndUnderfundingAreAtomic() (gas: 1767443)\n[PASS] testFeeOnTransferDepositRejected() (gas: 148391)\n[PASS] testFullLoopAndUnwindThroughCurveBridge() (gas: 14032200)\n[PASS] testFullUnwindConservesCapitalAndFlashLiquidity() (gas: 1278145)\n[PASS] testFullyLiquidatedPositionCanCloseWithExplicitZeroReturn() (gas: 788276)\n[PASS] testFuzzRepeatedLoopsConserveCapital(uint96,uint8) (runs: 256, μ: 1749583, ~: 1667300)\nLogs:\n  Bound result 4\n  Bound result 2\n\n[PASS] testIndependentPositions() (gas: 5764830)\n[PASS] testInitialBorrowMustBeNearFiftyPercent() (gas: 575778)\n[PASS] testInsufficientReinvestmentRevertsEverything() (gas: 680568)\n[PASS] testInvalidAndStaleFeed() (gas: 122125)\n[PASS] testLenderCannotSkipCallbackOrLieAboutAmountOrFunding() (gas: 1551856)\n[PASS] testOtherUsersCannotBurnOrWithdraw() (gas: 716762)\n[PASS] testOwnerCanReduceRiskWithStaleOracle() (gas: 956610)\n[PASS] testPoolOracleAlsoEnforcesFinalLtv() (gas: 681370)\n[PASS] testReceiptTransferMovesAllRights() (gas: 1293588)\n[PASS] testRejectsWrongPathEndpointsAndMalformedPath() (gas: 584451)\n[PASS] testRepeatedDeposits() (gas: 1093585)\n[PASS] testSupplyAndBorrowFeesRequireAdjustedQuote() (gas: 994159)\n[PASS] testSwapCannotReenterUnwind() (gas: 1186151)\n[PASS] testSwapCannotTransferReceiptMidOperation() (gas: 845627)\n[PASS] testSwapFailureAndMisreportedOutputRollback() (gas: 694638)\n[PASS] testTaxedOutputCannotUndercutWalletMinimum() (gas: 1339156)\n[PASS] testTopUpCanCoverMarketLossOnExit() (gas: 1257339)\n[PASS] testUnauthorizedAndReplayedCallbackRejected() (gas: 1266171)\n[PASS] testUnwindWithoutFlashLoanUsesOwnerBridgeFunds() (gas: 1131102)\n[PASS] testWarmupOrCoolerBorrowFailureRollsBack() (gas: 950168)\nSuite result: ok. 38 passed; 0 failed; 0 skipped; finished in 126.95ms (214.96ms CPU time)\n\nRan 4 test suites in 127.96ms (152.75ms CPU time): 51 tests passed, 0 failed, 0 skipped (51 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"e598a3bed7f1e5b956b54b71cd9b0b5a7ac76bf4ce5c411a39b2853a07789a16","verifiedTreeHash":"86b22e428a531173d95dfb78e855fb21077efb1c","verifierVersion":"0.1.0+ff982c0f"}]}