{"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":"a895e1a2-58b3-4a43-8ba6-20de12c92414","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"9d54985cca138cfd5a84a536c1f18ce09ca520d6e4eb972ab4cbc90a8aac7a78","dependsOn":["audit_imported_code"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"81b7052da6cdca6819abb4b1fb4924e31086633863b272c8ed89d9b24523ab82","skillId":"adapt-contract-project","tools":[]},"key":"adapt_contract_project","kind":"code","role":"implement","skillHash":"81b7052da6cdca6819abb4b1fb4924e31086633863b272c8ed89d9b24523ab82","skillId":"adapt-contract-project","state":"accepted"},{"acceptedSubmissionHash":"355b3b774bb8f36a74a08996670a6436eb6a13012c2746f92eac23d119e50676","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_economics","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"bf95f95c262bbbad882e28cc2a7af3dcce7969e7091f4be672cc3fe0128d0db6","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_flow","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"38b25d0604cad56463b58e4866071abee36688cbca964608edcf0e58fa41732e","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"9897597976b0e72440db7ca402d225aea20f3d37205ba53e7df2400ff80f29cc","skillId":"audit-imported-code","tools":[]},"key":"audit_imported_code","kind":"code","role":"review","skillHash":"9897597976b0e72440db7ca402d225aea20f3d37205ba53e7df2400ff80f29cc","skillId":"audit-imported-code","state":"accepted"},{"acceptedSubmissionHash":"668a2fa678742284f2c8f381832392c4c64b906924311d8a1c9b49000ea781a7","dependsOn":["adapt_contract_project","write_foundry_tests","manifest","audit_math","audit_permissions","audit_economics","audit_flow"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"af3aa01159bbf354f621cafa5c0006f6169e0938a8b015be508b7377dbf165bc","skillId":"audit-judge","tools":[]},"key":"audit_judge","kind":"code","role":"review","skillHash":"af3aa01159bbf354f621cafa5c0006f6169e0938a8b015be508b7377dbf165bc","skillId":"audit-judge","state":"accepted"},{"acceptedSubmissionHash":"a207de480b285c4509afc8ec880bb9a0848a0e2013cd7dade6a0994d494bf956","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_math","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"75d63209089e46c0e4ee261a938085f7385fd957a30ab593af15077772dded36","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_permissions","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"08aac4fdf369cf01b9e264b4f60163bc2cd788ef0f5dbc8ff56e5ba6502d4d1d","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"5fd7e914a4ebb6bef97f84acff10bafe1ad6d8fe7181c5f251af57c7ad043542","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"73431852439ad3a343f3d2b7db1c43cd363b9f48f9bb51497374a0cf6d50b223","skillId":"write-foundry-tests","tools":[]},"key":"write_foundry_tests","kind":"code","role":"tests","skillHash":"73431852439ad3a343f3d2b7db1c43cd363b9f48f9bb51497374a0cf6d50b223","skillId":"write-foundry-tests","state":"accepted"}],"objective":"Deploy the Marginalia companion IMPLEMENTATIONS from this repository on Ethereum mainnet: src/MarginaliaRouter.sol, src/MarginaliaJudge.sol, src/MarginaliaTreasury.sol and src/MarginaliaPricer.sol, each with no constructor arguments. Router, Judge and Treasury are EIP-1167 implementation targets that lock themselves in their constructors (hook = address(1)) so only zero-storage clones can ever be initialised, once, by the cloning hook; MarginaliaPricer (score arithmetic, price reads and the settlement rule) is a stateless contract the hook calls by staticcall. No owner, no pause, no upgrade anywhere. A later univ4_hook launch (MarginaliaHook) clones them in its constructor and calls each clone's one-shot init. What each does: MarginaliaRouter posts notes by swapping IMD for MARG with hookData, optionally trading any ERC-20 on Uniswap v4, v3 or v2 in the same transaction (the note must be about the token traded); MarginaliaJudge is the IdentityMD oracle consumer (EIP-712 \"IdentityMD Oracle\" v2) that once a week buys the panel ranking of the week's long-form theses through the Intake 0x1397434cd35e8a9C8aC312A61D3A285EB31dea56 and tells the hook whom to pay; MarginaliaTreasury holds IMD and drips 2% a day into the hook's pools, no withdraw. Who can call what: anyone, except init (once, by the cloning hook). Numbers: 0.25% action fee is NOT in this version; judge threshold 2 IMD, oracle price 0.5 IMD, prize split 50/30/20; treasury drip 2%. Upgrades and pausing: none. Outside services: Uniswap v4 PoolManager 0x000000000004444c5dc75cb358380d2e3de08a90, IMD 0xD34a99Bc0f67aE1bbd63C660e6d0b0dd03E263B7, the IdentityMD Intake. No token is deployed by this launch. This commit incorporates the previous launches' audit findings (canonical Uniswap venue validation, sweep accounting, judge retry and thesis-pool sweep, locked implementations, full-fill sells with a slippage floor, fee-on-transfer pulls) and resolves the finding that parked launch 1217 (observe() read a single-block spot): settlement now lives in MarginaliaPricer — Uniswap v3 and v2 venues settle on the TWAP of their on-chain accumulators between the first and last observation, v4 venues and the ETH->IMD hub leg settle on the observation least favourable to the call (minimum for a BUY call, maximum for a SELL call), and observations must span at least one hour, so a pump must be held for the whole span and any honest observation pins the price; a two-block pump-observe-unwind moves neither rule. Do not change the contracts' logic: audit, adapt to the launcher, and deploy. Tests are in test/ (forge test --no-match-path test/fork/*).","parentJobId":null,"planHash":"c5febd2e140f0c1b162ae65554df3f931f0b2bcd65cb3006da6113342e3f6e0c","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"a895e1a2-58b3-4a43-8ba6-20de12c92414","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-1240-src-marginaliarouter-sol-src-marginaliaj"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"52191","feedbackHash":"814764cd62efa09cd522f177dfd3eb83cca7fbd4044280c03ef3f4d1f6c96990","nodeKey":"adapt_contract_project","submissionHash":"9d54985cca138cfd5a84a536c1f18ce09ca520d6e4eb972ab4cbc90a8aac7a78","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51064","feedbackHash":"9cc48c0ec8eb993537e8d45fb2cea6b1b219f0d07fe86ffa0fffb99facbb6a5d","nodeKey":"adapt_contract_project","submissionHash":"65027068ed4a04582788addea6f2097c3e16ed56d979b045d04a362957c04a90","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"50982","feedbackHash":"60dd3fc83f8005ab5353767d4075590bf24ef1d2307a3b1735c57649693320e4","nodeKey":"adapt_contract_project","submissionHash":"5b9289bab76acb6d84029fd7db2d47f82cc9a5569b8d74a5a9e2a3b6fd9f2cc0","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52262","feedbackHash":"4ebdd8566ebea74a4adf3339525bf2365c9b218d032ddb8c40af4381e56c9755","nodeKey":"audit_economics","submissionHash":"355b3b774bb8f36a74a08996670a6436eb6a13012c2746f92eac23d119e50676","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52254","feedbackHash":"32d9aa58ac5d3c37f6f807cde42ab25900bc22e97e0407d053c8d35aabe24e4f","nodeKey":"audit_flow","submissionHash":"bf95f95c262bbbad882e28cc2a7af3dcce7969e7091f4be672cc3fe0128d0db6","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52207","feedbackHash":"888aaba9c2c01f57ade45ac83c57a6b6dfcf802d86e992b95697fff06e2bfe3f","nodeKey":"audit_imported_code","submissionHash":"38b25d0604cad56463b58e4866071abee36688cbca964608edcf0e58fa41732e","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51081","feedbackHash":"3427cb694d82b6282329bfa5e5879b9693d8226723c3437ad63093ed60322138","nodeKey":"audit_judge","submissionHash":"668a2fa678742284f2c8f381832392c4c64b906924311d8a1c9b49000ea781a7","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52163","feedbackHash":"8c9fd8a2ba31d5b63d211e18248831dadb17faa23f39d0665f99c1ab1d6261d4","nodeKey":"audit_judge","submissionHash":"e2f16292c703852be0a0687d9dc9a64974605d3fd501ae3c517bc265f82e2f59","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51883","feedbackHash":"c1d438728ddafe151e0e4dbcec3b9ef8d4ee440f827ebacacc9f59faf9ba0117","nodeKey":"audit_judge","submissionHash":"0398b410aad11acf06bf7aec4bfd29210ef4858ffa039d7714f10b374c7e4d6d","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52193","feedbackHash":"1e284c61d94c38c2bcbeb36141d41eb571c4c46a19083ab2acd5d69aa32cf800","nodeKey":"audit_math","submissionHash":"a207de480b285c4509afc8ec880bb9a0848a0e2013cd7dade6a0994d494bf956","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51168","feedbackHash":"0c9080f659de58c75f9447b4b2c7f030b1b041201110c4f344ed064d7df72232","nodeKey":"audit_permissions","submissionHash":"75d63209089e46c0e4ee261a938085f7385fd957a30ab593af15077772dded36","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"50968","feedbackHash":"58318e92b51f8098ce63b7c93310f903c066ad369b69e12a963ea9305663a548","nodeKey":"manifest","submissionHash":"b403073f12774acd8e2f118e93c55d3f6da12ce10d2c9b375faad3784f9cb349","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52158","feedbackHash":"2df80438701b98950cd560b11ae84f61756a9a3d1a23b116a63f03347ef18c65","nodeKey":"manifest","submissionHash":"08aac4fdf369cf01b9e264b4f60163bc2cd788ef0f5dbc8ff56e5ba6502d4d1d","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"50961","feedbackHash":"8185ba6d770326cb1c24eedeee337dcf3bb859401bc6a4df28e14a5a7db8c03b","nodeKey":"manifest","submissionHash":"ad6f2e3202e7b8bb97969756fb5cecfcdc6a15460dd71d026278dabb9bd5ba1d","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52163","feedbackHash":"af97eb5a9cf62a093cecf80cd0b2ce59234ac8a25e5108dfa64bf98f5b1af745","nodeKey":"write_foundry_tests","submissionHash":"5fd7e914a4ebb6bef97f84acff10bafe1ad6d8fe7181c5f251af57c7ad043542","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52266","feedbackHash":"90c76529fb6f063b5cbedac9a99d61f0aa71807540caa260f8dccede943fb202","nodeKey":"write_foundry_tests","submissionHash":"ce115551bba054a361ea3a3beac7718db0c2443e4ff37553a6621b38474eb997","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"50974","feedbackHash":"3aec87a7baccf4a4ac354d33628816c376352543de5c9d2771b3d9db33a049d8","nodeKey":"write_foundry_tests","submissionHash":"9701a2d204b980cc241b83f0abfc2009d89276cf29393c7bf33e450306a36305","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"7888c8009b13f1552abcbb17360ff862cf72813ffaa2ccebc9c65f52b82a7e7a","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"707624586655cf74","findings":[{"citation":"resolved","description":"Merged from audit_flow, audit_permissions and audit_economics (same root cause). validateVenue accepts any hookless v4 pool whose key recomputes the id and whose liquidity is non-zero (and any factory v3 pool or v2 pair), with no depth, age or counterparty requirement. Pool creation on the PoolManager is permissionless, so an author can be the only LP and the only trader of the venue its note is priced on. Every manipulation defence in MarginaliaPricer (adverse extreme over an hour of observations, 'any honest observation pins the price') assumes someone else has an incentive to trade the pump back; on a venue nobody else holds the token of, holding the pump costs nothing: the IMD spent on the pump lands in the attacker's own position. MarginaliaHook._difficulty (line 626) then prices the win with mcap = postPrice x IERC20(n.x).totalSupply(), both attacker-chosen, so the call lands in tier 3 with any target: log2(100) x sqrt(30) x 3 = 1,088,592 score points against ~20,538 for an honest RIGHT +10% call on the launch pool. weekTotal is dominated by the attacker, every honest leaderboardShare collapses, and with ten wallets (LEADERBOARD_CAP_BPS = 10% each) the entire week's leaderboardPool (50% of every stamp, fee, forfeit and treasury drip) is paid out through claimLeaderboard for ten 0.1 IMD stamps; the deposits come back because the calls are RIGHT. The same self-controlled token also makes the Traded class and the hold check meaningless. SPEC.md section 10 still claims 'price resolution only returns or forfeits your own bond', which stopped being true when the leaderboard started paying IMD for score.","line":208,"path":"src/MarginaliaRouter.sol","reproduction":"State: launch pool at 1 MARG = 1 IMD, hook bound. Attacker (1,000 IMD): deploy ERC-20 X (supply 1e27 to self); manager.initialize(PoolKey(X/IMD, fee 3000, spacing 60, hooks 0), sqrtP 2^96); add 1e18 liquidity over the full range (~1 X and ~1 IMD). router.checkpointVenue(p, xKey) with p.x = X, p.venue = (UniV4, xKey.toId()), side Buy, targetBps 1_000_000, horizonDays 1; warp +1h, roll +300; router.note(p, xKey, 1 ether, 1, deadline) succeeds, postPrice = 1e18. At horizonEnd: swap 11 IMD into the X pool (price ~144x, no one else can sell X back); hook.observe(id) at end, end+20 blocks/+10 min, end+300 blocks/+70 min; warp end+6h+1; hook.settle(id). Then hook.fundPot(1000 ether) in the same week (a treasury drip or gift). Expected: a venue the author alone can price earns nothing from the pool. Actual (test/scratch/SelfVenueLeaderboard.t.sol): status Right, weekScore(attacker) = 1,088,592, leaderboardShare(week, attacker) = 50.005 IMD of a 500.05 IMD pool (the 10% cap), claimable with claimLeaderboard after the week. Ten wallets repeat it and take 100% of the pool for 1 IMD of stamps. The v3 branch (line 215) is weaker still: a canonical v3 pool at an unused fee tier needs no liquidity at all and its tick (hence the TWAP accumulator) moves for free.","severity":"high","snippet":"            if (manager.getLiquidity(PoolId.wrap(v.ref)) == 0) revert BadVenue();","title":"Any wallet can provision its own canonical v4 venue, price it for free and farm the leaderboard pool with guaranteed-RIGHT tier-3 calls"},{"citation":"resolved","description":"Merged from audit_flow, audit_permissions, audit_math and audit_economics (same root cause). MarginaliaHook.sellPotMarg accepts any amount up to potMarg but only the judge may call it (line 674), and the judge's only path passes hook.potMarg() in full (lines 85-87). The sale is one exact-input full-fill swap (unlockCallback ACT_SELL, line 839) that must return at least 97% of the router window's MAXIMUM MARG price for the whole amount (line 678: router.postPrice(venue, true) is the window max including the current spot) after the pool's 1.25% LP fee (line 842: if (imdOut < extra) revert InvalidUnlock()). At infinitesimal size the output is 98.75% of spot, so 1.75% is left for price impact: for a concentrated position of liquidity L the full fill drops under the floor once the pot exceeds about 1.8% of L/sqrtP. potMarg is monotone: every Wrong, VoidSold, retract and thesis forfeit adds to it (line 609) and only a successful full sale subtracts, nobody is paid to call convertForfeits promptly, and LPs can leave. So the condition is absorbing: from the moment it holds, no forfeited MARG ever reaches leaderboardPool, thesisPool or refundPool again; the project's prize funding from forfeits is permanently broken and the MARG sits as ERC-6909 claims in the hook. A tranche of a tenth of the pot clears the same floor, so the all-or-nothing rule, not the band, is what fails.","line":87,"path":"src/MarginaliaJudge.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {PoolManager} from \"v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"v4-core/src/interfaces/IPoolManager.sol\";\nimport {IHooks} from \"v4-core/src/interfaces/IHooks.sol\";\nimport {IUnlockCallback} from \"v4-core/src/interfaces/callback/IUnlockCallback.sol\";\nimport {PoolKey} from \"v4-core/src/types/PoolKey.sol\";\nimport {PoolId, PoolIdLibrary} from \"v4-core/src/types/PoolId.sol\";\nimport {Currency} from \"v4-core/src/types/Currency.sol\";\nimport {ModifyLiquidityParams} from \"v4-core/src/types/PoolOperation.sol\";\nimport {BalanceDelta} from \"v4-core/src/types/BalanceDelta.sol\";\nimport {Marginalia} from \"src/Marginalia.sol\";\nimport {MarginaliaHook} from \"src/MarginaliaHook.sol\";\nimport {MarginaliaRouter} from \"src/MarginaliaRouter.sol\";\nimport {MarginaliaJudge} from \"src/MarginaliaJudge.sol\";\nimport {MarginaliaTreasury} from \"src/MarginaliaTreasury.sol\";\nimport {MarginaliaPricer} from \"src/MarginaliaPricer.sol\";\nimport {MarginaliaImpls} from \"src/MarginaliaImpls.sol\";\nimport {MarginaliaTypes as T} from \"src/MarginaliaTypes.sol\";\nimport {HookFlags} from \"src/HookFlags.sol\";\n\ncontract PSToken is ERC20 {\n    constructor(string memory n, uint256 supply) ERC20(n, n) {\n        _mint(msg.sender, supply);\n    }\n}\n\ncontract PSLiquidity is IUnlockCallback {\n    IPoolManager public immutable manager;\n\n    constructor(IPoolManager m) {\n        manager = m;\n    }\n\n    function add(PoolKey memory key, int24 lower, int24 upper, int256 amount) external {\n        manager.unlock(abi.encode(key, ModifyLiquidityParams(lower, upper, amount, bytes32(0))));\n    }\n\n    function unlockCallback(bytes calldata data) external returns (bytes memory) {\n        require(msg.sender == address(manager));\n        (PoolKey memory key, ModifyLiquidityParams memory p) = abi.decode(data, (PoolKey, ModifyLiquidityParams));\n        (BalanceDelta d,) = manager.modifyLiquidity(key, p, \"\");\n        _pay(key.currency0, d.amount0());\n        _pay(key.currency1, d.amount1());\n        return \"\";\n    }\n\n    function _pay(Currency c, int128 d) private {\n        if (d < 0) {\n            manager.sync(c);\n            IERC20(Currency.unwrap(c)).transfer(address(manager), uint256(uint128(-d)));\n            manager.settle();\n        }\n    }\n}\n\n/// @title Forfeited MARG is stranded once the pot outgrows what the launch pool absorbs inside the 97% floor\n/// @notice MarginaliaJudge.convertForfeits is the only caller of the judge-only MarginaliaHook.sellPotMarg and\n/// always passes the entire potMarg. The sale is a single full-fill swap that must return at least 97% of the\n/// router window's MAXIMUM MARG price for the whole amount, after the pool's 1.25% LP fee. potMarg only grows\n/// (every forfeit adds to it; only a successful full sale subtracts), so once it exceeds roughly 1.8% of the\n/// pool's virtual MARG reserve every conversion reverts InvalidUnlock, forever, although a tranche would sell.\n/// Fails on the current code (InvalidUnlock); passes once the conversion can sell what the pool absorbs.\ncontract PotStrandedProof is Test {\n    using PoolIdLibrary for PoolKey;\n\n    IPoolManager manager;\n    Marginalia token;\n    PSToken imd;\n    MarginaliaHook hook;\n    MarginaliaRouter router;\n    MarginaliaJudge judge;\n    PoolKey key;\n    address alice = makeAddr(\"alice\");\n\n    function setUp() public {\n        vm.warp(1_800_000_000);\n        vm.roll(20_000_000);\n        manager = IPoolManager(address(new PoolManager(address(this))));\n        token = new Marginalia();\n        imd = new PSToken(\"IMD\", 1_000_000_000 ether);\n        vm.etch(MarginaliaImpls.ROUTER_IMPL, address(new MarginaliaRouter()).code);\n        vm.etch(MarginaliaImpls.JUDGE_IMPL, address(new MarginaliaJudge()).code);\n        vm.etch(MarginaliaImpls.TREASURY_IMPL, address(new MarginaliaTreasury()).code);\n        vm.etch(MarginaliaImpls.PRICER, address(new MarginaliaPricer()).code);\n        bytes memory code = abi.encodePacked(type(MarginaliaHook).creationCode, abi.encode(manager, address(token), address(this)));\n        bytes32 h = keccak256(code);\n        for (uint256 i = 0; i < 300_000; ++i) {\n            address predicted = address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), bytes32(i), h)))));\n            if (!HookFlags.matches(predicted, HookFlags.MARGINALIA)) continue;\n            bytes32 salt = bytes32(i);\n            address deployed;\n            assembly (\"memory-safe\") {\n                deployed := create2(0, add(code, 32), mload(code), salt)\n            }\n            require(deployed == predicted, \"deploy\");\n            hook = MarginaliaHook(deployed);\n            break;\n        }\n        router = hook.router();\n        judge = hook.judge();\n        bool margIs0 = address(token) < address(imd);\n        (address c0, address c1) = margIs0 ? (address(token), address(imd)) : (address(imd), address(token));\n        key = PoolKey(Currency.wrap(c0), Currency.wrap(c1), 12500, 60, IHooks(address(hook)));\n        manager.initialize(key, uint160(1 << 96));\n        PSLiquidity liq = new PSLiquidity(manager);\n        token.transfer(address(liq), 10_000 ether);\n        imd.transfer(address(liq), 10_000 ether);\n        // A modest launch pool: 1000e18 of liquidity on [-6000, 6000] at 1 MARG = 1 IMD (~260 MARG in range).\n        liq.add(key, -6000, 6000, 1000 ether);\n        imd.transfer(alice, 10_000 ether);\n        vm.prank(alice);\n        imd.approve(address(router), type(uint256).max);\n        router.checkpointVenue(_margNote(), key);\n        vm.warp(vm.getBlockTimestamp() + 1 hours);\n        vm.roll(vm.getBlockNumber() + 300);\n    }\n\n    function _margNote() internal view returns (T.NoteParams memory p) {\n        p.x = address(token);\n        p.venue = T.Venue(T.VenueKind.UniV4, PoolId.unwrap(key.toId()), address(0), false);\n        p.side = T.Side.Buy;\n        p.targetBps = 20_000;\n        p.horizonDays = 7;\n        p.class = uint8(T.Class.Declared);\n        p.text = \"2x\";\n    }\n\n    function testForfeitedPotCanStillBeConvertedOnceItOutgrowsOneSale() public {\n        // 80 posted-and-retracted calls: each forfeits its ~0.49 MARG deposit to the pot.\n        for (uint256 i = 0; i < 80; ++i) {\n            vm.prank(alice);\n            router.note(_margNote(), key, 1 ether, 1, vm.getBlockTimestamp() + 1);\n            bytes32 id = bytes32(hook.noteCount());\n            vm.prank(alice);\n            hook.retract(id, \"out\");\n        }\n        uint256 pot = hook.potMarg();\n        emit log_named_uint(\"potMarg\", pot);\n        assertGt(pot, 30 ether);\n\n        // A fresh, honest, mature price window (the old one expired), so the floor is 97% of the current price.\n        vm.warp(vm.getBlockTimestamp() + 7 hours);\n        vm.roll(vm.getBlockNumber() + 2100);\n        router.checkpointVenue(_margNote(), key);\n        vm.warp(vm.getBlockTimestamp() + 2 hours);\n        vm.roll(vm.getBlockNumber() + 600);\n\n        // Expected: at least part of the pot converts. Actual: the whole-pot sale reverts and the pot never shrinks.\n        try judge.convertForfeits() returns (uint256 imdOut) {\n            emit log_named_uint(\"imdOut\", imdOut);\n        } catch (bytes memory reason) {\n            emit log_named_bytes(\"convertForfeits reverted\", reason);\n        }\n        assertLt(hook.potMarg(), pot, \"forfeited MARG is stranded in the pot: nothing converts\");\n    }\n}","reproduction":"State: launch pool with 1000e18 liquidity on [-6000, 6000] at 1 MARG = 1 IMD (about 260 MARG in range; the threshold scales with depth, a 10M-liquidity pool strands at ~180k MARG). alice posts 80 calls via router.note(p, key, 1 ether, 1, deadline) and retracts each with hook.retract: potMarg = 36.88 MARG. Warp 7h and roll 2100 blocks (old window expired), router.checkpointVenue(...) a fresh honest window, warp 2h, roll 600. judge.convertForfeits(). Expected: the pot (or what the pool absorbs) converts and accrues. Actual (test/scratch/PotStranded.t.sol): revert InvalidUnlock() (0xaf2ed76d) from MarginaliaHook.unlockCallback, potMarg unchanged at 36.88 MARG, and every later call reverts too since the pot only grows. In the same state vm.prank(judge); hook.sellPotMarg(potMarg / 10) succeeds and returns IMD (test/scratch/Repro.t.sol testTrancheSellsWhereWholePotDoesNot: 2.02 IMD for 3.7 MARG on a thinned fixture pool), and from any other account it reverts Unauthorized(), so no smaller sale exists. Also any genuine fall of more than ~1.75% within the 6-hour window blocks conversion until the window expires, and anyone can pin the window maximum high for six hours with a brief pump followed by checkpointVenue.","severity":"high","snippet":"        imdOut = hook.sellPotMarg(marg);","title":"convertForfeits sells the whole pot or nothing against a 97%-of-window-maximum floor: once the pot outgrows what the pool absorbs, every forfeit is stranded forever"},{"citation":"resolved","description":"Merged from audit_permissions and audit_economics (same root cause). The hold rule reads IERC20(n.x).balanceOf(n.author) at every observation (line 497) and, for a SELL call, treats any observation whose balance is above postBalance as 'the author bought X back' and resolves VoidSold (line 523): _forfeit sends 2% of the deposit to the settling keeper and the rest to potMarg, records[author].broken += 1 and score -= difficulty. A BUY call's rule (balance < postBalance) can only be broken by the author, but an ERC-20 balance can be raised by anyone with a plain transfer, so a third party voids any SELL call in the system for one wei of X plus gas. The victim cannot defend: it cannot refuse an inbound transfer and cannot burn the dust without changing its balance again before the next observation. Who profits: the settling keeper (2% of the deposit), every competitor for the week's leaderboard pool (the victim's positive score is replaced by a negative one), anyone wanting to damage a wallet's public record. The SPEC's intent ('selling on any venue breaks it') is not what the code checks.","line":517,"path":"src/MarginaliaHook.sol","reproduction":"State: launch pool at 1 MARG = 1 IMD with a mature checkpoint; alice approved the router for MARG. alice: router.sellWithNote({x: MARG, venue: the launch pool, side Sell, targetBps 9000, horizonDays 1}, key, 2 ether, 1, deadline): postBalance = 98 MARG = her balance after the sale. bob sells 1,500,000 MARG through a plain v4 router: margPriceInImd() < 0.8e18, so the -10% call is right. carol: MARG.transfer(alice, 1). Anyone observes three times over an hour after horizonEnd; after end + 6h carol calls settle(id). Expected: status Right, deposit intact, score +20538 (the identical sequence without carol's transfer settles Right with that score). Actual (test/scratch/DustVoidsSell.t.sol): status VoidSold (3), alice's deposit 0 and forfeited to potMarg, records(alice).score = -20538, broken = 1, carol receives 0.0099 MARG as keeper.","severity":"high","snippet":"                if (n.side == T.Side.Buy ? obs[i].balance < n.postBalance : obs[i].balance > n.postBalance) {","title":"Anyone voids a correct SELL call by sending its author one wei of X: deposit forfeited to the pot, score negative, keeper paid"},{"citation":"resolved","description":"Merged from write_foundry_tests and audit_math (same root cause). fromSqrt truncates sqrtP^2 / 2^192 x 1e18 to an integer and, when X is token0, returns it even when it is 0 (line 288); when X is token1 it returns FullMath.mulDiv(1e18, 1e18, p) (line 290) which is 0 whenever p > 1e36, with no check on the result either. The v2 branch of _spotInQuote (line 240) has the same gap. The zero flows through observe -> checkpoint -> postPrice unchanged (mulDiv(0, q, 1e18) = 0), MarginaliaHook._postNote stores n.postPrice = 0 with no check (line 447), and settle (line 525) resolves a BUY call with settlePrice * 10_000 >= 0 * targetBps, which is always true (a SELL call with settlePrice * 10_000 <= 0 is also RIGHT because the settlement reads 0 too). _difficulty computes mcap = 0 (tier 1) and still returns a positive score (log2(target) x sqrt(30/h)), so the call books leaderboard score and gets its deposit back whatever the market does. The edge is reachable through the router's canonical-venue check: any hookless v4 pool with non-zero liquidity can be initialised by anyone at any tick in [MIN_TICK, MAX_TICK]; the price rounds to zero past tick -414,500 (X token0) or +414,500 (X token1), far inside the legal range. This is distinct from the self-venue finding: it is an arithmetic defect that survives any depth rule, since a genuinely priced pool for a token with a huge supply reads the same zero.","line":288,"path":"src/MarginaliaPricer.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {PoolManager} from \"v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"v4-core/src/interfaces/IPoolManager.sol\";\nimport {IHooks} from \"v4-core/src/interfaces/IHooks.sol\";\nimport {IUnlockCallback} from \"v4-core/src/interfaces/callback/IUnlockCallback.sol\";\nimport {PoolKey} from \"v4-core/src/types/PoolKey.sol\";\nimport {PoolId, PoolIdLibrary} from \"v4-core/src/types/PoolId.sol\";\nimport {Currency} from \"v4-core/src/types/Currency.sol\";\nimport {ModifyLiquidityParams} from \"v4-core/src/types/PoolOperation.sol\";\nimport {BalanceDelta} from \"v4-core/src/types/BalanceDelta.sol\";\nimport {TickMath} from \"v4-core/src/libraries/TickMath.sol\";\nimport {StateLibrary} from \"v4-core/src/libraries/StateLibrary.sol\";\nimport {MarginaliaPricer} from \"src/MarginaliaPricer.sol\";\nimport {MarginaliaTypes as T} from \"src/MarginaliaTypes.sol\";\n\ncontract BigSupplyToken is ERC20 {\n    constructor() ERC20(\"Dust\", \"DUST\") {\n        _mint(msg.sender, 1e40);\n    }\n}\n\n/// @dev A hookless, liquid Uniswap v4 pool whose token0 is worth less than 1e-18 of its quote: the price\n/// MarginaliaPricer reads for it is exactly zero, and it never refuses the reading. The hook then stores\n/// postPrice = 0 for a BUY call and settles it with `settlePrice * 10_000 >= 0 * targetBps`, which is\n/// always true. Anyone can create such a pool (a token with a large supply, any tiny liquidity) and farm\n/// leaderboard score with guaranteed-RIGHT calls at the cost of the 0.1 IMD stamp each.\ncontract ZeroPriceProofTest is Test, IUnlockCallback {\n    using PoolIdLibrary for PoolKey;\n    using StateLibrary for IPoolManager;\n\n    PoolManager private manager;\n    MarginaliaPricer private pricer;\n    address private dust;\n    address private imd;\n    PoolKey private key;\n    T.Venue private venue;\n    int24 private constant TICK = -500_000;\n\n    function setUp() public {\n        vm.chainId(1);\n        vm.warp(1_800_000_000);\n        vm.roll(20_000_000);\n        manager = new PoolManager(address(this));\n        pricer = new MarginaliaPricer();\n        address a = address(new BigSupplyToken());\n        address b = address(new BigSupplyToken());\n        (dust, imd) = a < b ? (a, b) : (b, a);\n        key = PoolKey(Currency.wrap(dust), Currency.wrap(imd), 3000, 60, IHooks(address(0)));\n        manager.initialize(key, TickMath.getSqrtPriceAtTick(TICK));\n        manager.unlock(abi.encode(ModifyLiquidityParams(-887_220, -400_020, 1e12, bytes32(0))));\n        assertGt(IPoolManager(address(manager)).getLiquidity(key.toId()), 0, \"the venue is liquid: the router accepts it as canonical\");\n        venue = T.Venue(T.VenueKind.UniV4, PoolId.unwrap(key.toId()), imd, true);\n    }\n\n    function unlockCallback(bytes calldata data) external returns (bytes memory) {\n        require(msg.sender == address(manager));\n        ModifyLiquidityParams memory p = abi.decode(data, (ModifyLiquidityParams));\n        (BalanceDelta d,) = manager.modifyLiquidity(key, p, \"\");\n        _settle(key.currency0, d.amount0());\n        _settle(key.currency1, d.amount1());\n        return \"\";\n    }\n\n    function _settle(Currency c, int128 d) private {\n        if (d < 0) {\n            manager.sync(c);\n            ERC20(Currency.unwrap(c)).transfer(address(manager), uint256(uint128(-d)));\n            manager.settle();\n        }\n    }\n\n    /// @dev Fails today: the baseline and the settlement price are both zero and nothing refused them.\n    /// Passes once the pricer refuses a reading that rounds to zero (as it already does for the inverted\n    /// orientation, with EmptyPool) anywhere along checkpoint / postPrice / settlePrice.\n    function testAPricedCallNeverGetsAZeroBaselineOrSettlement() public {\n        T.PriceWindow memory empty;\n        T.PriceWindow memory w;\n        try pricer.checkpoint(IPoolManager(address(manager)), venue, imd, empty) returns (T.PriceWindow memory r) {\n            w = r;\n        } catch {\n            return; // refused at the checkpoint: fixed\n        }\n        vm.warp(vm.getBlockTimestamp() + 1 hours);\n        vm.roll(vm.getBlockNumber() + 300);\n        uint256 post;\n        try pricer.postPrice(IPoolManager(address(manager)), venue, imd, true, w) returns (uint256 p) {\n            post = p;\n        } catch {\n            return; // refused at posting: fixed\n        }\n        assertGt(post, 0, \"BUY baseline is zero: settle * 10_000 >= 0 * targetBps holds for any settlement\");\n\n        T.Observation[] memory obs = new T.Observation[](3);\n        for (uint256 i; i < 3; ++i) {\n            (uint256 x, uint256 q) = pricer.observe(IPoolManager(address(manager)), venue, imd);\n            obs[i] = T.Observation(uint64(vm.getBlockTimestamp()), uint64(vm.getBlockNumber()), x, q, 1);\n            vm.warp(vm.getBlockTimestamp() + 30 minutes);\n            vm.roll(vm.getBlockNumber() + 150);\n        }\n        uint256 settled;\n        try pricer.settlePrice(venue, true, obs) returns (uint256 s) {\n            settled = s;\n        } catch {\n            return;\n        }\n        assertGt(settled, 0, \"settlement price is zero for a liquid pool\");\n    }\n}","reproduction":"Pricer alone (test/scratch/ZeroPrice.t.sol, the independent tester's proof): PoolManager and MarginaliaPricer; two 18-decimal tokens with 1e40 supply, the lower address as token0 and the other as IMD; hookless key (fee 3000, spacing 60) initialised at getSqrtPriceAtTick(-500000); liquidity 1e12 over [-887220, -400020] so getLiquidity > 0. venue = (UniV4, id, imd, xIsToken0 = true). pricer.checkpoint(...) returns xStart = xMin = xMax = 0; after 1h/300 blocks pricer.postPrice(..., buy=true, w) returns 0 (expected: revert EmptyPool or a positive price); three observe() readings 30 minutes apart return xRead = 0 and settlePrice returns 0 (expected: revert). End to end through the hook (test/scratch/Repro.t.sol testZeroPostPriceMakesTheCallVacuouslyRight): ERC-20 DUST (1e40 supply); hookless DUST/IMD pool initialised at tick -420000 if DUST < IMD else +420000 with 1e18 liquidity on [tick-6000, tick+6000]; router.checkpointVenue, wait 1h; router.postPrice(router.validateVenue(p, k), true) == 0; router.note(p, k, 1 ether, 1, deadline) with side Buy, targetBps 50_000, horizon 1 day: noteOf(id).postPrice == 0; three observations with the pool untouched; settle(id). Expected: a 5x call on a flat price is WRONG or the post is refused. Actual: status Right, records(alice).score = 126,660, deposit refundable.","severity":"high","snippet":"        if (xIsToken0) return p;","title":"fromSqrt returns 0 instead of refusing a sub-1e-18 price; a zero baseline makes every BUY call on that venue vacuously RIGHT and scores it"},{"citation":"resolved","description":"From audit_flow. The settlement guarantee for v4 venues and the hub leg is that 'any honest observation pins the price'. The series is capped at 16 observations and each new one is refused for 20 blocks after the last (lines 492-495), so 16 observations taken at the earliest allowed block fill the series in exactly 15 x 20 x 12 s = 3600 s, which is not < OBS_MIN_SPAN (line 512) and so settles. An author who is first in each of those 16 blocks (a builder bundle, or front-running the public observe at the known block last+20) does pump -> observe -> unwind inside one block each time; between those blocks the price is honest, yet every honest observe reverts ObservationTooSoon, and after the sixteenth the window is closed with TooLate. settlePrice then sees only pumped readings. On the launch pool each sandwich costs the 3% quiet sell fee plus two 1.25% LP fees on the pump size; on any thin or self-owned v4 venue it costs nothing. For adverse-extreme venues extra observations can only hurt the author, so capping their count and spacing them per note (not per observer) only serves the squatter.","line":492,"path":"src/MarginaliaHook.sol","reproduction":"test/scratch/Repro.t.sol testObservationSquatting: alice posts BUY +10% / 1 day on MARG via router.note (10 IMD). At horizonEnd, for i in 0..15: roll end+20i, warp end+240i; buy 600,000 IMD of MARG (price > 1.1e18), hook.observe(id), sell it back (price < 1.1e18), all in that block. bob calls hook.observe(id) in the same block and in each of the next 19 blocks: 320 attempts, all refused (ObservationTooSoon, then TooLate after the sixteenth), 0 accepted. After SETTLE_WINDOW settle(id) -> Status.Right although the price was +12% only inside alice's 16 blocks. Expected: at least one honest reading lands and settles the call Wrong (as test/Lifecycle.t.sol testTwoBlockPumpObserveUnwindSettlesWrong shows when the series is not squatted).","severity":"medium","snippet":"        if (obs.length >= OBS_MAX) revert TooLate();","title":"OBS_MAX x OBS_GAP_BLOCKS lets one actor own every observation slot: honest observers are refused in every block and never pin the price"},{"citation":"resolved","description":"From audit_math. For v4 venues and the hub leg settlePrice is the extreme over the observation series least favourable to the call (lines 181-194). The brief's 'a two-block pump-observe-unwind moves neither rule' holds only in the direction that favours the author. In the adverse direction one observation taken in the same transaction as a swap is enough: observe (hook lines 485-500) has no caller restriction and reads the venue's spot at that instant, so a contract can swap, call observe and swap back atomically. A competitor for the week's pro-rata leaderboard pool, or anyone who wants a deposit forfeited to the pot (and the 2% keeper reward), turns a BUY call Wrong with one dump of X (or of ETH in the hub pool for WETH/native-quoted venues) and a SELL call Wrong with one pump; the author forfeits the whole deposit and the difficulty score, the attacker pays only the round-trip fees scaled by the size needed to cross the target, with no holding period and no exposure to arbitrage. The 1-hour span and 20-block gap do not help because the manipulated observation can be any one of the series. Severity medium rather than high because on the launch pool the round trip is expensive relative to the 0.5 IMD deposit (below), though on thin venues it is not.","line":184,"path":"src/MarginaliaPricer.sol","reproduction":"test/scratch/Repro.t.sol testThirdPartyDumpObserveUnwindMakesRightCallWrong. Fixture pool 10,000,000e18 liquidity on [-6000, 6000] at 1:1, mature checkpoint. alice: router.note(BUY 11_000, 1 day) on MARG (postPrice ~1.0e18). bob buys 1.5M IMD of MARG: spot > 1.3e18 and stays there for the horizon. At horizonEnd hook.observe(id) (xRead ~1.32e18). Roll +25, warp +30 min. carol, in one block: sell 1.5M MARG (spot < 1.0e18), hook.observe(id), buy back with the IMD received (spot > 1.19e18). Roll +50, warp +60 min: hook.observe(id) honest again. After end + 6h + 1: settle(id). Expected: a +32% move held for the whole horizon and both honest observations settles RIGHT. Actual: settlePrice = min of the series < 1.1 x postPrice, status Wrong, alice's deposit forfeited to potMarg (2% to the keeper), score negative; carol's IMD balance is unchanged and she lost 72,407 MARG of the 1.5M she cycled (3% quiet fee plus two 1.25% LP fees).","severity":"medium","snippet":"                x = _adverse(x, obs[i].xRead, buy);","title":"The adverse-extreme rule is movable against the author by any third party in one transaction: dump, observe, unwind makes a right call WRONG"},{"citation":"resolved","description":"From audit_flow, extended. Every observation reads IERC20(n.x).balanceOf(n.author) with a plain external call to a token the author chose. If the read reverts during the settlement window nobody can observe, settle() finds fewer than OBS_MIN observations and resolves VoidNoData (line 513), which books no score and leaves the deposit claimable (claimDeposit accepts VoidNoData, line 585). A reentrant balanceOf does the same without reverting: the call happens before obs.push (line 498), so a balanceOf that calls observe(id) again sees obs.length still 0, passes the gap and cap checks, and sixteen nested calls fill the whole series in one block with one timestamp; honest observers then get TooLate and the span check (line 512) voids the call. The author of a call on a token it controls (or any token whose owner can gate balanceOf) watches the outcome at the horizon: if RIGHT it lets observers in and banks the score; if WRONG it switches the read off for six hours and gets the deposit back with no penalty. The forfeit, the keeper reward and the negative score all disappear; the asymmetric payoff makes posting such calls strictly profitable in score.","line":497,"path":"src/MarginaliaHook.sol","reproduction":"test/scratch/Repro.t.sol testRevertingBalanceOfIsAFreeOption. Token SW whose balanceOf reverts 'paused' while a flag is set; hookless v4 pool SW/IMD with 1e18 full-range liquidity; router.checkpointVenue, wait 1h, router.note(BUY 2x, 1 day, 1 IMD). At horizonEnd the price is unchanged (the call is wrong); alice sets the flag. hook.observe(id) reverts 'paused' for every caller through the whole window. After SETTLE_WINDOW settle(id) -> Status.VoidNoData, records(alice).score == 0, then claimDeposit(id, false) returns the full deposit to alice. Expected: a wrong call whose position cannot be verified does not come back as a refundable void (treat a failed read as not held, or as a forfeit).","severity":"medium","snippet":"        uint256 balance = IERC20(n.x).balanceOf(n.author);","title":"observe() has no fallback for a reverting or reentrant balanceOf: a call on an author-controlled token is a free option (block the series, VoidNoData, deposit refunded, no score)"},{"citation":"resolved","description":"From audit_economics. A call needs three observations spanning an hour inside a six-hour window or it resolves VoidNoData (lines 512-513), which books no score and returns the deposit. observe() pays nothing; the only keeper reward is 2% of a forfeited deposit (0.01 IMD) paid on settle and only for Wrong / VoidSold outcomes, below the gas of three observations and a settlement on mainnet. So in practice the party with an incentive to observe a call is its author, who observes only the calls the market confirmed. The downside of a call (forfeit, negative score) is optional while the upside (positive score, leaderboard share) is kept: post a BUY and a SELL call on the same token every day and observe whichever one came true. The leaderboard pool pays IMD pro-rata by score, so this has positive expected value for two stamps regardless of skill, and the public record never shows a wrong call. settle() has no deadline either, so the author also chooses the week its positive score is booked into (_bookWeekScore uses the week of settlement, line 654). Leaderboard competitors do have a diffuse incentive to observe rivals' wrong calls, which bounds this below a guarantee, but the asymmetry is in the code: a void returns the deposit and costs nothing.","line":513,"path":"src/MarginaliaHook.sol","reproduction":"State: launch pool at 1 MARG = 1 IMD, mature checkpoint. alice posts two 1-day calls on MARG through router.note: BUY targetBps 11000 and SELL targetBps 9000 (two stamps, two ~0.5 IMD deposits). bob sells 1,000,000 MARG so the price falls ~15%. At the horizon alice observes only the SELL call three times (end, +10 min / +20 blocks, +70 min / +300 blocks) and never observes the BUY call; nobody else does. After end + 6h she settles both. Expected under the stated design: the wrong BUY call forfeits and scores negative. Actual: the SELL call settles Right (score +20538, deposit back via claimDeposit), the BUY call settles VoidNoData (deposit back via claimDeposit, score 0, nothing in the record): test/Lifecycle.t.sol testNoDataRefunds already shows the VoidNoData branch refunding with score 0. Net +20538 week score for 0.2 IMD of stamps, every day, independent of market direction; the same sequence with both calls observed books +20538 and -20538 and forfeits one deposit.","severity":"medium","snippet":"            outcome = T.Status.VoidNoData;","title":"Nobody is paid to observe and VoidNoData refunds without score, so an author chooses which of its calls get observed: every call is a free option on the leaderboard pool"},{"citation":"resolved","description":"From audit_economics. A thesis is only judged if it is in weekTheses[week], and that array silently stops growing at MAX_DAY_NOTES = 256: a later thesis is still posted (stamp taken, ~0.5 IMD deposit locked, status ThesisOpen, children allowed) but thesesOfWeek never returns it, so MarginaliaJudge.eligibleTheses, questionBody and judgedOf can never include it. The judge additionally truncates eligible theses to the first MAX_JUDGED = 120 by posting order (MarginaliaJudge.sol line 96). Neither limit is checked at posting, so an honest author pays for an entry that cannot win, with no revert or event saying so. Because a thesis's deposit is released by any child resolution, including VoidNoData with no observations, filling the judged set costs only stamps: 120 theses plus one child call each = 240 stamps = 24 IMD, after which every honest thesis that week is outside the 120 the panel sees and the 30% thesis prize (plus rolled-forward leftovers) is ranked among the attacker's entries only.","line":445,"path":"src/MarginaliaHook.sol","reproduction":"test/scratch/Repro.t.sol testTwoHundredFiftySeventhThesisPaysButIsNeverJudged: bob posts 256 theses in week w via router.note with targetBps 0 (1 IMD each); thesesOfWeek(w).length == 256. alice posts a thesis in the same week: router.note({targetBps: 0, text: ...}, key, 1 ether, 1, deadline). Expected: alice's thesis is in thesesOfWeek(w) or the call reverts before taking her stamp and deposit. Actual: her note exists (noteOf(id).status == ThesisOpen, deposit > 0, thesisPool(w) grew by her stamp's 30%), but thesesOfWeek(w).length is still 256 and does not contain her id, so judge.eligibleTheses(w) and judgedOf(w) can never pay her. Cheaper variant: 120 theses each with one child call fill eligibleTheses(w) (test/CompanionFailures.t.sol testEligibleThesesAreCappedAtTheJudgedMaximum shows the 120 cut) so every later honest thesis is cut by MAX_JUDGED.","severity":"medium","snippet":"            if (weekTheses[_week()].length < MAX_DAY_NOTES) weekTheses[_week()].push(id);","title":"The 257th thesis of a week (and any eligible thesis after the 120th) pays stamp and deposit but can never be judged; 24 IMD of stamps fills the judged set and takes the thesis prize uncontested"},{"citation":"resolved","description":"Merged from write_foundry_tests, audit_flow and audit_permissions (same root cause). The callback keys the week on the Intake's requestId argument (pendingDay, line 207) but verifies and consumes a.requestId from the signed attestation (line 216), and never compares the two, nor a.questionHash with any hash of questionBody(day), nor a.chainId with block.chainid. Any attestation signed for this clone (the domain pins the consumer, not the question) can therefore be delivered against any pending week. The judge's own retry path makes two signed answers for the same week possible and two weeks may be pending at once. A week judged with another week's ranking has judgedSet = true forever; judgedOf filters the foreign ids out (noteWeek != day) and payJudged rolls the whole prize forward with no winners, and the genuine delivery for the other week then reverts AlreadyConsumed, so that week can only be re-requested after ANSWER_DEADLINE at the cost of another 0.5 IMD draw. Only the Intake can call the function, so this needs a faulty or compromised Intake: a trust assumption rather than an open attack, but SPEC.md ('verifies ... that questionHash equals its own recomputation') claims a check the code does not make, and a.requestId cannot be pinned exactly either since the Intake's id and the oracle's UUID differ by design; at minimum the ranked ids' week and a.chainId can be checked and the README should state the trust.","line":216,"path":"src/MarginaliaJudge.sol","reproduction":"test/scratch/Repro.t.sol testAttestationForAnotherWeekAcceptedUnderThisWeeksId: theses with child calls and fundPot(20 ether) in weeks A and B; requestJudging(A) -> rA, requestJudging(B) -> rB. Attestation att with att.requestId = 0xB, answer = [week B's thesis id], panel 7/5/6, valid window, signature accepted by the signer. From the Intake: onOracleResult(rA, att, sig). Expected: revert (attestation not for rA). Actual: success, judgedSet[A] = true, judgedOf(A) = [0,0,0] (the id is filtered as another week's), consumed[0xB] = true. Then onOracleResult(rB, att, sig) reverts AlreadyConsumed(0xB); payJudged(A) pays nobody and rolls thesisPool[A] forward. test/JudgeOracle.t.sol already delivers attestations whose requestId (keccak256('signed judge request')) differs from the callback id and they are accepted.","severity":"low","snippet":"        _consume(a.requestId);","title":"onOracleResult does not bind the attestation to the request it is delivered for: no a.requestId == requestId, questionHash or chainId check"},{"citation":"resolved","description":"From audit_flow. MarginaliaJudge.weekClosed (lines 163-170) returns true once an unanswered request is older than ANSWER_DEADLINE and the week is 28 days past, but pendingDay[requestId] is only deleted on a retry (line 184). If nobody retries, the first request stays deliverable: after sweep(2, epoch) moves thesisPool[epoch] into the current leaderboard pool (lines 780-784), a late onOracleResult still succeeds (judgedSet = true) and payJudged pays shares of a zero pool while recording judgedWins. No funds are lost (they went to the leaderboard), but the ranked authors the oracle was paid 0.5 IMD to find get nothing and the week can never be judged again.","line":779,"path":"src/MarginaliaHook.sol","reproduction":"test/scratch/Repro.t.sol testSweepThenLateDeliveryPaysZero: week w with a thesis + child and fundPot(20 ether); at (w+1)*7d+1 judge.requestJudging(w) -> r; no answer. At (w+1)*7d + 28d + 1: judge.weekClosed(w) == true, hook.sweep(2, w) moves thesisPool[w] (> 0) to leaderboardPool[current], thesisPool[w] == 0. The Intake then delivers a valid answer for r: pendingDay still set, onOracleResult succeeds, judgedSet[w] = true. judge.payJudged(w) -> hook.payJudged(w, top) with pool = 0: alice's IMD balance unchanged, records(alice).judgedWins == 1, JudgedPaid(w, [0,0,0]). Expected: either the sweep invalidates the pending request (delete pendingDay as the retry does) or weekClosed stays false while a request is deliverable.","severity":"low","snippet":"            if (!judge.weekClosed(epoch)) revert NotOpen();","title":"sweep(2) can empty a thesis pool whose original Intake request is still deliverable, so a late ranking pays its winners zero"},{"citation":"resolved","description":"Own finding; it concerns the later univ4_hook launch, not this evm_contracts manifest, which deploys the four implementations with empty constructors and passes the contracts floor (verified: test/Implementations.t.sol and a run of the pinned Contracts.protected.t.sol per ADAPTATION.md). The hook's constructor (lines 190-210) reverts InvalidUnlock unless token_ and the four MarginaliaImpls addresses already hold code, then clones and initialises them. The pinned Hook.protected.t.sol deploys the hook's creation code on a fresh chain where only the PoolManager (and the token probe, when IMD_TOKEN_PROBE is set) exist; the companion implementations are never placed there, so the hook constructor reverts and the floor fails with 'hook deployment reverted' whatever addresses MarginaliaImpls carries. MarginaliaImpls.sol also still holds the rehearsal placeholders (0x...a0001-a0004) that tests etch code at, and the hook launch cannot deploy until they are replaced with the confirmed mainnet addresses, which is documented but is a hard dependency the author should plan for (take the four addresses as constructor arguments and verify them on first use, as the launch reference advises for exactly this constructor pattern).","line":199,"path":"src/MarginaliaHook.sol","reproduction":"On a chain where 0x00000000000000000000000000000000000a0001..a0004 (or the real implementation addresses) hold no code, deploy abi.encodePacked(type(MarginaliaHook).creationCode, abi.encode(poolManager, token, factory)) at a salt whose address carries flags 0x20cc: the constructor reverts InvalidUnlock() at line 198-201 (src/MarginaliaHook.sol) and the creation returns address(0); the fixture only succeeds because test/helpers/Fixture.sol _etchImpls etches the implementations first. The protected hook test never etches them, so the hook launch is parked at its floor.","severity":"low","snippet":"            MarginaliaImpls.TREASURY_IMPL.code.length == 0 || MarginaliaImpls.ROUTER_IMPL.code.length == 0","title":"The hook in this tree cannot pass the hook launch's empty-chain floor: its constructor requires code at the four companion addresses (and at the token), which no rehearsal chain has"},{"citation":"resolved","description":"From write_foundry_tests; confirmed by reading, no impact in the deployed configuration. (1) lastDripDay starts at 0, so on a chain whose timestamp is below 86400 the first drip reverts AlreadyDripped (irrelevant on mainnet). (2) MarginaliaPricer.sqrt (line 101, (x + 1) / 2) reverts with an arithmetic overflow for x = type(uint256).max; difficulty() only passes values up to 3e9. (3) MarginaliaPricer.difficulty(0, false, h, mcap) and difficulty(t, buy, 0, mcap) panic with division by zero (lines 73 and 75); the hook validates targetBps and horizonDays before calling it. Noted so the pricer's public surface is understood as hook-only.","line":44,"path":"src/MarginaliaTreasury.sol","reproduction":"vm.warp(1000); treasury.drip() -> AlreadyDripped. pricer.sqrt(type(uint256).max) -> panic 0x11. pricer.difficulty(0, false, 30, 0) -> panic 0x12; pricer.difficulty(20000, true, 0, 0) -> panic 0x12.","severity":"info","snippet":"        if (day == lastDripDay) revert AlreadyDripped();","title":"Unreachable edge behaviours: Treasury.drip refuses UTC day 0, Pricer.sqrt(type(uint256).max) overflows, difficulty() divides by zero on inputs the hook never sends"}],"hash":"0398b410aad11acf06bf7aec4bfd29210ef4858ffa039d7714f10b374c7e4d6d","nodeId":"d50b90ec-2bb8-4e57-b169-0042f10e9a18","outcome":"completed","summary":"The review is complete. No tracked file changed; the findings file and scratch proofs are excluded from git by the harness.\n\n**Outcome: 13 findings written to `.imd-findings.json`, 4 high with failing Foundry proofs, plus a 35-row coverage record answering all 32 entry points.**\n\n**Merging and recalibration of the 21 specialist findings**\n\n- **Self-owned canonical venue farms the leaderboard** (three specialists, one root cause) kept at high. My proof shows one 0.1 IMD stamp earning the 10% cap of the week's pool at score 1,088,592.\n- **Whole-pot forfeit conversion strands MARG** (four specialists) kept at high. Proof: 80 retractions on a modest pool, then every conversion reverts InvalidUnlock while a tenth of the pot sells fine.\n- **One wei voids a SELL call** (two specialists) kept at high. Proof: a stranger's transfer turns a correct call into VoidSold, forfeits the deposit and pays the stranger as keeper.\n- **Zero price reading** (two specialists) raised to high. The tester's proof fails on the pricer; my scratch run confirms it end to end through the hook, where a 5x call on a flat price settles RIGHT.\n- Five mediums kept with reproductions: observation squatting (320 honest attempts refused), third-party dump-observe-unwind, author-controlled balanceOf as a free option (extended with a reentrancy variant that fills all 16 slots in one block), VoidNoData as a free refund, and the 256/120 thesis caps.\n- Three specialist reports on attestation binding merged into one low. The sweep-then-late-delivery lead kept as low.\n- Three unreachable edge panics kept as one info entry.\n\n**Own addition:** the hook in this tree cannot pass the hook launch's empty-chain floor, because its constructor demands code at the four companion addresses and the token. This does not affect the current implementations manifest, which I verified deploys cleanly, so it is filed low as a dependency for the next launch.\n\n**Not substantiated and dropped:** nothing. Every specialist lead reproduced. The static-analysis lines (weak PRNG, reentrancy, strict equality) traced to benign code and are not reported.","treeHash":null,"usage":{"cachedInputTokens":6000437,"inputTokens":930,"model":"claude-fable-5-1","outputTokens":85298,"runtime":"claude","turns":49,"wallClockMs":1618141}},{"artifacts":[],"attempt":1,"bundleHash":"02a304dbe16c60b03862c41453251366d41c9442c2854cd9d9630824224812da","device":"4dd67dae195771b6","findings":[],"hash":"08aac4fdf369cf01b9e264b4f60163bc2cd788ef0f5dbc8ff56e5ba6502d4d1d","nodeId":"491da7ce-b563-4ce9-9d1f-cce0bb54ad24","outcome":"completed","summary":"The manifest is updated and verified. The only changed file is launch.json.\n\n**Why the last attempt failed**\nIt confirmed the manifest was correct and then submitted nothing, which the harness recorded as a runtime error. This revision keeps the verified contract list unchanged and makes one real edit to the notes.\n\n**What changed in launch.json**\n- **Contracts and arguments are untouched.** MarginaliaRouter, MarginaliaJudge, MarginaliaTreasury and MarginaliaPricer, each with an empty constructor argument list. The compiled ABIs show zero constructor inputs for all four, and MarginaliaPricer has only the implicit constructor.\n- **Notes now record the handoff step** that the brief and README require but the old notes omitted. The later hook launch reads the four implementation addresses from constants in src/MarginaliaImpls.sol, whose current values are rehearsal placeholders. The confirmed deployed addresses must be written there before the hook launch is built.\n- **Notes name the constants as declared** so a reviewer can match them to source: panel size, quorum, answer deadline, max oracle price, drip basis points, hub pool id, and the one-hour minimum and six-hour maximum checkpoint age. The 50/30/20 prize split is attributed to the hook, where it lives, with the judge supplying the ranking.\n- The notes are a single string of 3,451 characters, under the 4,000 cap. The file has exactly the keys kind, contracts and notes.\n\n**Verification**\n- A scratch script checked the manifest shape, unique identifiers under 32 characters, and empty argument lists.\n- `forge build` succeeds.\n- `forge test --no-match-path 'test/fork/*'` passes 81 of 81 tests, including the Implementations suite that deploys all four with no arguments and rejects init on the locked implementations.\n\n**Working tree** shows only launch.json modified. Nothing under foundry.toml, remappings, lib or .github was touched, and no scratch file remains.","treeHash":"7c2589728dc41752a66356c904f177a1e893eea2","usage":{"cachedInputTokens":364527,"inputTokens":226,"model":"claude-fable-5-1","outputTokens":5495,"runtime":"claude","turns":8,"wallClockMs":303957}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"28e346843ec15530","findings":[{"citation":"resolved","description":"The canonical-venue check accepts any hookless v4 pool (or any factory v3 pool / v2 pair) with non-zero liquidity that contains X and is quoted in IMD, WETH or ETH. Creating such a pool is permissionless, so an attacker deploys a token X it alone holds, opens X/IMD with dust liquidity (L = 1e18, under one IMD of depth) and is the only LP and the only trader. Every manipulation-resistance rule in MarginaliaPricer (TWAP span, adverse extreme, honest observers, 'a pump must be held for the whole span against every arbitrageur') assumes someone else has an incentive to trade the pool back; on a self-provisioned venue nobody does, so holding the pumped price for the whole settlement span costs nothing: the IMD the pump spends lands in the attacker's own position and comes back when it removes liquidity. The attacker self-observes three times, settles RIGHT, gets its 0.5 IMD deposit back and books a score of log2(target) x sqrt(30/horizon) x tier, where it also controls the mcap tier (postPrice x totalSupply of its own token) and the target (any uint32 >= 11000: 100x in 1 day scores 1,088,592 against 10,000 for an honest 2x-in-30-days tier-1 call). The leaderboard pool is 50% of every IMD accrual (quiet-sell fees, stamps, forfeits, treasury drips) and pays pro-rata by score with a 10% per-wallet cap, so one such note per wallet across ten wallets takes the entire weekly pool for ten stamps (1 IMD) and gas, every week. SPEC section 10 still claims 'price resolution only returns or forfeits your own bond' and 'capped bond makes manipulation unprofitable'; since v0.4 the leaderboard pays IMD for score, and the previous round's 'self-priced venue' fix (canonical factories) does not close this because canonical pools of worthless tokens are free to create. The same holds for a v3 pool or v2 pair the attacker creates through the canonical factory: the accumulator TWAP of a pool only it trades is whatever it sets.","line":205,"path":"src/MarginaliaRouter.sol","reproduction":"State: launch pool at 1 MARG = 1 IMD. Attacker deploys ERC20 X (1e27 supply), initializes hookless v4 pool X/IMD (fee 3000, spacing 60) at 1:1, adds liquidity 1e18 over ticks [-60000, 60000] (~0.95 X and ~0.95 IMD). Step 1: router.checkpointVenue(note{x: X, venue: UniV4 / xKey.toId(), side Buy, targetBps 1_000_000, horizonDays 1}, xKey); warp +1h, roll +300. Step 2: router.note(same params, xKey, imdIn 1 ether, minMargOut 1, deadline): note id 1, stamp 0.1 IMD, deposit ~0.5 IMD of MARG; postPrice = 1e18, mcap = 1e27 IMD so tier 3. Step 3: at horizonEnd, swap 11 IMD -> X on xKey (price ~143x); hook.observe(1); roll +20 / warp end+10min; observe; roll +300 / warp end+70min; observe. Step 4: warp end+6h+1; hook.settle(1). Expected (the protocol's stated guarantee): a call the author alone can price must not earn pool money. Actual: status = Right, records(attacker).score = 1,088,592, leaderboardShare(week, attacker) = 50.005 IMD out of a 500.05 IMD pool (the 10% cap) after one fundPot(1000 IMD) accrual in that week; claimLeaderboard pays it. Ten wallets repeat it and take 100% of the pool for 1 IMD of stamps. Proof test test/scratch/SelfVenueLeaderboard.t.sol fails on the current code with 'self-priced venue pays the capped leaderboard share for one 0.1 IMD stamp: 50005000000000000000 != 0'.","severity":"high","snippet":"        if (v.kind == T.VenueKind.UniV4) {\n            if (PoolId.unwrap(key.toId()) != v.ref) revert BadVenue();\n            if (address(key.hooks) != address(0) && address(key.hooks) != address(hook)) revert BadVenue();\n            if (manager.getLiquidity(PoolId.wrap(v.ref)) == 0) revert BadVenue();","title":"Any wallet can provision its own canonical v4 venue, price it for free and farm the leaderboard pool with guaranteed Right calls at the top difficulty tier"},{"citation":"resolved","description":"The hold rule for a SELL call treats any observation where the author's X balance is above its post-trade balance as 'the author bought X', and settles VoidSold: the deposit is forfeited (2% to the keeper, 98% to potMarg), the author's record gets broken += 1 and score -= difficulty, and the week score drops. An ERC-20 balance can be raised by anyone with a plain transfer, so a third party voids any SELL call for one wei of X plus gas. Who profits: the settling keeper (2% of the deposit, paid in MARG), every competitor for that week's leaderboard pool (the victim's positive score is reduced or erased, so their pro-rata share grows), and anyone wanting to damage a wallet's public record. The victim cannot defend: it cannot refuse an incoming transfer and cannot burn the dust without changing its balance again before the next observation. BUY calls are not exposed the same way (a balance cannot be lowered by a third party), so SELL calls are strictly worse to post, which also biases the whole ledger. The SPEC's hold-rule intent ('selling on any venue breaks it') is not what the code checks: it checks for any increase.","line":517,"path":"src/MarginaliaHook.sol","reproduction":"State: launch pool at 1 MARG = 1 IMD with a mature checkpoint. Step 1: alice calls router.note({x: MARG, venue: the launch pool, side Sell, targetBps 9000, horizonDays 1}, key, 2 ether, 1, deadline): postBalance = alice's MARG balance after the swap. Step 2: bob (any wallet) sells 1,000,000 MARG through a plain router so the price falls ~15%: the call is right. Step 3: bob calls MARG.transfer(alice, 1). Step 4: at the horizon anyone records three observations (end, end+10min / +20 blocks, end+70min / +300 blocks); after end+6h bob calls settle(id). Expected: status Right, deposit returned, score +20538 (verified: the identical sequence without step 3 settles Right with score +20538). Actual: status VoidSold (3), alice's deposit = 0 (forfeited), records(alice).score = -20538, broken = 1, bob receives 0.00987 MARG as keeper. Proof test test/scratch/DustVoidsSell.t.sol fails on the current code with 'one wei of dust from a third party voided the call'.","severity":"high","snippet":"                if (n.side == T.Side.Buy ? obs[i].balance < n.postBalance : obs[i].balance > n.postBalance) {","title":"Sending one wei of X to a SELL-call author voids a RIGHT call: deposit forfeited to the pot, score negative, keeper paid"},{"citation":"resolved","description":"Forfeited deposits accumulate in potMarg (retract, Wrong, VoidSold, settleThesis). The only path that spends potMarg is MarginaliaHook.sellPotMarg, which only the judge may call, and the judge's convertForfeits always passes the entire pot. sellPotMarg swaps that amount in one full-fill swap and requires imdOut >= 97% of the window-maximum price x amount (MarginaliaHook.sol:678-679, unlockCallback ACT_SELL at 839-842). The sale itself pays the 1.25% LP fee and moves the price, so once the pot is larger than roughly 1.7% of average price impact on the launch pool, the floor fails for the whole pot even though a fraction would sell. Nothing reduces potMarg other than a successful full sale, and forfeits keep arriving, so the condition is absorbing: from that point the pot's forfeited MARG (the part of the pot that funds the leaderboard, thesis prize and refunds) can never be converted. Nobody is paid to call convertForfeits, so the pot naturally grows between calls; a pool that thins out (LPs leave) or a quiet month is enough to cross the threshold. The hook's sellPotMarg accepts any amount <= potMarg, so the capability exists but is unreachable: the judge never asks for less.","line":84,"path":"src/MarginaliaJudge.sol","reproduction":"State: launch pool with L = 2000e18 at 1 MARG = 1 IMD (about 520 MARG and 520 IMD in range), a modest but realistic depth. Step 1: alice posts and immediately retracts 80 calls (router.note(..., 1 ether) then hook.retract(id, ...)): potMarg = 38.14 MARG (about 7% of the in-range depth). Step 2: after the 6-hour window expires, checkpointVenue again and wait one hour, so the floor is 97% of the current honest price. Step 3: judge.convertForfeits(). Expected: the pot (or at least what the pool can absorb) converts to IMD and accrues to the pools. Actual: the whole-pot sale reverts (InvalidUnlock at the floor check) and potMarg stays 38.14 MARG; it will revert on every later call because the pot only grows. In the same state, vm.prank(judge); hook.sellPotMarg(potMarg / 10) succeeds and returns 4.03 IMD, showing that a tranche sale is possible and only the judge's all-or-nothing call blocks it. Proof test test/scratch/PotStranded.t.sol fails on the current code with 'forfeited MARG is stranded in the pot: 38143981459127999555 != 0'.","severity":"high","snippet":"    function convertForfeits() external nonReentrant returns (uint256 imdOut) {\n        uint256 marg = hook.potMarg();\n        if (marg == 0) return 0;\n        imdOut = hook.sellPotMarg(marg);\n    }","title":"convertForfeits sells the whole pot or nothing: once forfeited MARG exceeds what the launch pool absorbs inside the 97% floor, every conversion reverts and the pot is stranded forever"},{"citation":"resolved","description":"A call needs three observations spanning an hour inside a six-hour window or it resolves VoidNoData, which returns the deposit and books no score. observe() pays nothing; the only keeper reward is 2% of a forfeited deposit (0.01 IMD, about one cent at IMD ~ 9 USD) paid on settle, and only for Wrong / VoidSold outcomes, which is far below the gas of three observations and a settlement on Ethereum mainnet. So in practice the only party with an incentive to observe a call is its author, who observes only the calls that turned out right. The downside of a call (forfeit, negative score) is therefore optional while the upside (positive score, leaderboard share) is kept: post a BUY and a SELL call on the same token every day and observe whichever one the market confirmed. Score is pro-rata money from the week's leaderboard pool (50% of all accruals), so this is a guaranteed positive expected value for the price of two stamps, regardless of any skill, and the public record never shows a wrong call. settle() has no deadline either, so the author also chooses the week its positive score is booked into (weekScore uses the week of settlement), while nobody has a reason to settle its wrong calls at all. The design's mitigation ('anyone may observe') has no economic actor behind it. Severity medium: no direct theft, but the leaderboard pool pays for coin flips and the published records are unfalsifiable.","line":512,"path":"src/MarginaliaHook.sol","reproduction":"State: launch pool at 1 MARG = 1 IMD, mature checkpoint. Step 1: alice posts two 1-day calls on MARG through router.note: BUY targetBps 11000 and SELL targetBps 9000 (two stamps, two 0.5 IMD deposits). Step 2: bob sells 1,000,000 MARG so the price falls 15%. Step 3: at the horizon alice observes only the SELL call three times (end, +10min/+20 blocks, +70min/+300 blocks) and never observes the BUY call; nobody else observes (no reward). Step 4: after end+6h alice settles both. Expected under the stated design: the wrong BUY call forfeits and scores negative. Actual: the SELL call settles Right (score +20538, deposit back via claimDeposit), the BUY call settles VoidNoData (deposit back via claimDeposit, score 0, nothing in the record). Net: +20538 week score for 0.2 IMD of stamps, every day, independent of the market direction. The same sequence with both calls observed books +20538 and -20538 (net zero) and forfeits one deposit.","severity":"medium","snippet":"        if (count < OBS_MIN || obs[count - 1].timestamp - obs[0].timestamp < OBS_MIN_SPAN) {\n            outcome = T.Status.VoidNoData;","title":"Nobody is paid to observe, so an author chooses which of its calls get observed: wrong calls go VoidNoData (deposit back, no score) and every call is a free option on the leaderboard pool"},{"citation":"resolved","description":"A thesis is only judged if it is in weekTheses[week], and that array silently stops growing at MAX_DAY_NOTES = 256: a later thesis is still posted (stamp taken, 0.5 IMD deposit locked, status ThesisOpen, children allowed) but thesesOfWeek never returns it, so MarginaliaJudge.eligibleTheses, questionBody and judgedOf can never include it. The judge additionally truncates eligible theses to the first MAX_JUDGED = 120 by posting order (MarginaliaJudge.sol:96). Neither limit is checked at posting, so an honest author pays for an entry that cannot win, and there is no event or revert telling it so. Because a thesis's deposit is released by any child resolution (including VoidNoData with no observations, see finding 4), filling the judged set costs only stamps: 120 theses plus one child call each = 240 stamps = 24 IMD, after which every honest thesis that week is outside the 120 the panel sees, and the 30% thesis prize (plus rolled-forward leftovers) is ranked among the attacker's entries only. The sweep path cannot recover the pool for honest writers either: thesisPool[w] is paid to whichever of the attacker's ids the panel ranks.","line":445,"path":"src/MarginaliaHook.sol","reproduction":"State: any week. Step 1: an attacker (or 257 writers) calls router.note with targetBps 0 (thesis) 256 times in week w: each call takes a stamp and a deposit and increments noteCount. Step 2: alice posts a thesis in the same week: router.note({targetBps: 0, text: '...'}, key, 1 ether, 1, deadline). Expected: alice's thesis is in thesesOfWeek(w) or the call reverts before taking her stamp and deposit. Actual: her note exists (noteOf(id).status == ThesisOpen, deposit > 0, stamp accrued) but thesesOfWeek(w).length == 256 and does not contain her id; judge.eligibleTheses(w) can never return it, so judgedOf(w) can never pay her. Cheaper variant: 120 theses each with one child call (240 stamps, 24 IMD; all deposits recoverable after the children resolve VoidNoData) fill eligibleTheses(w) so that every later honest thesis is cut by MAX_JUDGED and the panel ranks only the attacker's ids.","severity":"medium","snippet":"            if (weekTheses[_week()].length < MAX_DAY_NOTES) weekTheses[_week()].push(id);","title":"The 257th thesis of a week (and any eligible thesis after the 120th) pays stamp and deposit but can never be judged; an attacker fills the judged set for 24 IMD and takes the thesis prize uncontested"}],"hash":"355b3b774bb8f36a74a08996670a6436eb6a13012c2746f92eac23d119e50676","nodeId":"4d1501f6-847c-4e4f-a43a-7b990aa61320","outcome":"completed","summary":"The review is complete. `.imd-findings.json` holds 5 findings and a 34-row coverage record (all 32 listed entry points plus two invariants). No source files were changed; the only new files are the findings file and the scratch proofs under `test/scratch/`.\n\n**Findings (economics: Economic Security, Invariant, Flow Gap guides)**\n\n1. **High, with proof.** Anyone can create a canonical hookless v4 pool (or factory v3/v2 pool) for a token only they hold, price it for free, post a BUY call at the maximum difficulty tier, pump and self-observe at settlement, and settle Right. The proof shows one 0.1 IMD stamp earning the full 10% per-wallet cap of the week's leaderboard pool, which pays 50% of every IMD accrual. Ten wallets take the whole pool. The spec's \"price resolution only returns or forfeits your own bond\" no longer holds since the leaderboard pays for score.\n2. **High, with proof.** The SELL hold rule voids a call if the author's balance ever rises. One wei of X sent by any third party turns a Right sell call into VoidSold: deposit forfeited, score negated, keeper paid. The identical sequence without the dust settles Right.\n3. **High, with proof.** The judge's convertForfeits always sells the entire pot with a whole-fill swap floored at 97% of the window maximum. Once the pot exceeds roughly 1.7% average price impact on the launch pool, every conversion reverts forever while forfeits keep accumulating. The hook can sell a tranche, but the judge never asks for one.\n4. **Medium.** Nobody is paid to observe, so authors observe only their winning calls. Losing calls resolve VoidNoData with the deposit returned and no score, making every call a free option on the leaderboard pool.\n5. **Medium.** A week's 257th thesis, and any eligible thesis beyond the judge's first 120, pays stamp and deposit but can never be judged. Filling the judged set costs about 24 IMD in stamps.\n\n**Verification.** The existing suite passes on the tree as given. Each of the three proof tests fails on the current code for the stated reason and is written so a fix that blocks the sequence makes it pass.\n\n**Not reached in depth.** The oracle signature and quorum path in the judge, and the v3/v2 fork venues, were traced only as far as my area touches them. The convertForfeits sandwich and checkpoint-window griefing were examined and judged bounded by the design's own 97% floor and 6-hour expiry, so they were not reported.","treeHash":null,"usage":{"cachedInputTokens":4240918,"inputTokens":802,"model":"claude-fable-5-1","outputTokens":71662,"runtime":"claude","turns":41,"wallClockMs":1210330}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"f009de0ce52c7b3a","findings":[{"citation":"resolved","description":"Settlement (settlePrice) was hardened against a single-block price, but the baseline it is compared with was not. MarginaliaHook._postNote stores n.postPrice = MarginaliaPricer.postPrice(...), which is _spotInQuote (slot0 of a v4 pool, slot0 of a v3 pool, or the v2 reserves ratio) times the hub spot, all read in the posting block. The author controls that block: a contract (class Agent is still accepted) sells X on the venue, posts the note through MarginaliaRouter.note, and buys X back, atomically. The recorded post price is the depressed one; targetBps is applied to it; the honest TWAP / adverse-extreme settlement price of an unchanged market then clears the target. The deposit comes back, records[author].right and weekScore grow by difficulty(), and the author draws on the week's leaderboard pool (50% of every accrual, up to 10% per wallet, so ten wallets drain it). On a venue the author created (any hookless v4 pool, any v3/v2 factory pair) or on a thin pool the round trip costs only fees; on a deep pool a flash loan does the same. The mirror image for SELL calls is pump, post, unwind. The balance-hold rule does not help: postBalance is read in the same block and a BUY call with postBalance 0 is always held. The fix belongs to the same contract as the settlement rule: a post price that is not a single-block spot (the venue accumulator's TWAP over a trailing window for v3/v2; for v4 and the hub leg, for example, a post-time observation series or the adverse extreme of the posting block's price and a prior reading), or refusing the post when the spot moved in the same block.","line":101,"path":"src/MarginaliaPricer.sol","reproduction":"Fixture: PoolManager, MARG/IMD pool with this hook at 1 MARG = 1 IMD, 10,000,000 liquidity over ticks -6000..6000 (the repository's own test fixture). Author contract holds 2,000,000 MARG and 100 IMD. In one transaction: (1) plain exact-input sell of 2,000,000 MARG -> hook.margPriceInImd() falls from 1.0e18 to 0.697e18; (2) router.note(BUY MARG, targetBps 11000, horizonDays 1, venue = the pool) -> noteOf(id).postPrice == 0.6973e18; (3) plain buy of MARG with the IMD received -> spot 0.986e18. Nobody trades for a day. After horizonEnd, three observe(id) calls 25 blocks and 31 minutes apart, then settle(id) after the window. Expected: a '+10%' call on a market that ended at 0.986 (below its 1.0 start) is Wrong (or the post is refused). Actual: status == Right (settle price 0.986e18 >= 0.6973e18 * 1.1), the deposit is returned and the author's score rises. Run test/scratch/PostPriceSameBlock.t.sol: it fails on this code with 'a +10% call settled RIGHT on a market that fell'.","severity":"high","snippet":"        return FullMath.mulDiv(_spotInQuote(manager, v), _quoteSpot(manager, v.quote, imd), 1e18);","title":"postPrice is the venue's same-block spot: dump, post, unwind in one transaction makes a BUY call settle RIGHT on a market that fell"},{"citation":"resolved","description":"onOracleResult accepts any signed, in-quorum bytes32[] and sets judgedSet[day] = true before the ranking is filtered. The filter runs later in judgedOf, which drops ids that are not this week's theses with a child. If nothing survives, payJudged reverts BadAnswer on every call, requestJudging reverts AlreadyRequested (judgedSet is true), and weekClosed returns false at line 149 for the same reason, so MarginaliaHook.sweep(2, week) reverts NotOpen forever. The IMD left in thesisPool[week] (the pool minus the 0.5 IMD price already drawn) is unreachable by anyone, and the hook has no other path out of thesisPool. The same lock follows from the panel ranking only theses whose author posted no child, ids from another week, or short-form call ids. A judged week with an empty top should be payable as 'no winner' (roll the pool forward, as payJudged already does for unranked slots) or weekClosed should treat it as closed so it can be swept.","line":218,"path":"src/MarginaliaJudge.sol","reproduction":"State: week w has one thesis a1 (with a child call) and thesisPool[w] = 5.56 IMD after fundPot(20 IMD) plus stamps. After the week ends, requestJudging(w) draws 0.5 IMD and records the request. The Intake delivers onOracleResult(reqId, attestation{answerType 5, answer = abi.encode([bytes32(999)]), panelSize 7, quorum 5, agreed 6}, sig). Then: judgedSet(w) == true; payJudged(w) reverts BadAnswer; requestJudging(w) reverts AlreadyRequested; after 365 days weekClosed(w) == false and hook.sweep(2, w) reverts; hook.thesisPool(w) is still 5.06 IMD. Expected: the pool rolls forward or becomes sweepable. Actual: 5.06 IMD locked permanently. (Reproduced in a scratch test on the repository fixture: thesis pool stuck: 5560000000000000000 before the draw.)","severity":"medium","snippet":"        if (top[0] == bytes32(0)) revert BadAnswer();","title":"A judged week whose ranking contains no payable id locks its thesis pool forever (payJudged reverts, weekClosed stays false, sweep and retry impossible)"},{"citation":"resolved","description":"The repository ships a launch.json for the MarginaliaHook launch: kind univ4_hook, a hook entry with $poolManager/$token/$factory, a token block and a pool block. This launch is evm_contracts with four contracts (MarginaliaRouter, MarginaliaJudge, MarginaliaTreasury, MarginaliaPricer), each with an empty constructorArgs list and no token or pool. A launch.json present in the tree is checked as this launch's manifest, so the current file rejects the adapted work: wrong kind, unknown keys (hook, token, pool) and no contracts array. The adapter must replace it with {kind: 'evm_contracts', contracts: [four entries with constructorArgs: []], notes} or remove it so the manifest step writes it. Note also that notes in the current file describe the previous version ('median of at least three on-chain price observations', 'one IdentityMD oracle ranking per day'), which no longer matches the code (adverse-extreme / TWAP settlement, weekly judging).","line":2,"path":"launch.json","reproduction":"Read launch.json: line 2 is \"kind\": \"univ4_hook\" and there is no \"contracts\" key. Expected for this launch: kind evm_contracts, contracts = [MarginaliaRouter, MarginaliaJudge, MarginaliaTreasury, MarginaliaPricer] each with constructorArgs [], notes <= 4000 characters. Actual: a univ4_hook manifest with hook/token/pool keys, which the evm_contracts schema refuses.","severity":"medium","snippet":"  \"kind\": \"univ4_hook\",","title":"launch.json in the tree is the hook launch's manifest (kind univ4_hook, $token/$poolManager), not a contracts-only manifest for the four implementations"},{"citation":"resolved","description":"The Intake calls the callback with exactly 200,000 gas and records a revert or out-of-gas as not delivered, without retry (oracle-consumer skill). onOracleResult copies the full bytes32[] answer into storage (about 22,100 gas per element on top of the signature check, consume, judgedSet and the event). Measured on an EIP-1167 clone with an EOA signer: 3 ids succeed, 4 ids use about 182,000 gas in the implementation frame, 5 ids run out of gas (the repository fixture's ERC-1271 signer gives the same boundary). The question asks for head 3, so the normal answer fits, but any answer the panel pads (the full ranking rather than the head, duplicates, 'head' ignored) is lost together with the 0.5 IMD drawn from the thesis pool, and the week can only be bought again after ANSWER_DEADLINE, draining 0.5 IMD per retry while the thesis pool lasts. Storing only the first three surviving ids (judgedOf's filter, moved into the callback is too expensive; cap the copy at 3 elements instead) or storing keccak256(answer) and replaying the attestation in payJudged keeps the callback flat.","line":192,"path":"src/MarginaliaJudge.sol","reproduction":"Clone MarginaliaJudge, init(hookStub, intakeStub, action, vm.addr(key)); the hook stub reports week 100 and four eligible theses for week 99. requestJudging(99) returns reqId. From the intake address: judge.onOracleResult{gas: 200000}(reqId, attestation with answer = abi.encode(bytes32[5] of the week's thesis ids plus one), valid EOA signature). Expected: judgedSet(99) == true (a correctly signed, in-quorum ranking is accepted). Actual: the call reverts out of gas, judgedSet(99) == false, pendingDay[reqId] is still set, and requestJudging(99) reverts AlreadyRequested until requestedAt + 3 days. With 4 ids the call succeeds; with 3 ids it succeeds with roughly 40,000 gas to spare.","severity":"low","snippet":"        rawRanked[day] = ranked; // filtered in payJudged: the Intake gives this callback 200k gas","title":"onOracleResult stores the whole ranking inside the Intake's 200,000-gas stipend: an answer of five or more ids runs out of gas and the paid week is lost"},{"citation":"resolved","description":"MarginaliaRouter.validateVenue requires getLiquidity(v.ref) > 0 only at posting time, and the v2 read refuses empty reserves, but the v4 read used by observe() (and postPrice) takes slot0 regardless of liquidity. In a v4 pool with no liquidity in range an exact-input swap of 1 wei moves sqrtPriceX96 to the caller's price limit at no cost (computeSwapStep with liquidity 0 jumps to the target). The author of a note on a self-made hookless X/IMD or X/ETH pool, who is its only LP, removes the liquidity after the horizon, sets the price to the target with a 1-wei swap, and records the three observations an hour apart; nobody else has a reason to touch a dead pool, and the adverse-extreme rule then returns the author's price. Conversely anyone can set a dead pool's price to zero for free and make every BUY call on it Wrong (deposit forfeited to the pot, 2% to the keeper). Settlement should treat a v4 venue with zero liquidity like an empty v2 pair (revert EmptyPool so the observation is skipped and the call voids as no-data).","line":169,"path":"src/MarginaliaPricer.sol","reproduction":"Author deploys token X, initialises a hookless X/IMD v4 pool, adds minimal liquidity, posts a BUY note (targetBps 20000, horizon 1 day) through router.note; validateVenue passes (liquidity > 0). After the horizon the author removes all liquidity and swaps 1 wei of IMD with sqrtPriceLimitX96 at 3x the post price: the swap costs nothing and slot0 reads 3x. Three observe(id) calls 25 blocks and 31 minutes apart all read 3x; settle(id) returns Right. Expected: an observation of a venue with no liquidity is refused (EmptyPool, as for v2), leaving the call VoidNoData. Actual: the author's chosen price settles the call.","severity":"low","snippet":"            (uint160 sqrtP,,,) = manager.getSlot0(PoolId.wrap(v.ref));","title":"observe/_spotInQuote accept a v4 venue with zero liquidity, where one wei of swap sets the spot anywhere for free"},{"citation":"resolved","description":"MarginaliaHook.sellPotMarg is judge-only 'so the timing is predictable', but MarginaliaJudge.convertForfeits is callable by anyone at any time and always sells the entire potMarg. The hook's slippage floor is _minImdOut = 97% of margPriceInImd() read in the same transaction, after any swap the caller made first. A caller therefore sells MARG into the pool, calls convertForfeits so the pot sells at the depressed price, and buys back: the pot's IMD proceeds fall by the depression (not bounded by the 3%), and the difference is the caller's sandwich profit on the pot's size. The caller pays the quiet 3% and two LP fees on their own push, so this only pays when potMarg is large relative to the pool's depth, but nothing in the contracts prevents it and the judge's amount is never the caller's choice to bound. A floor that is independent of the posting block (for example the adverse extreme the pricer already computes, or a caller-supplied minimum checked against a prior reading) or a bounded per-call amount would close it.","line":80,"path":"src/MarginaliaJudge.sol","reproduction":"Repository fixture (pool at 1 MARG = 1 IMD, 10,000,000 liquidity). alice's wrong call forfeits 0.4839 MARG to potMarg. Honest: judge.convertForfeits() returns 0.4778 IMD. Instead: bob sells 2,000,000 MARG through a plain v4 router (spot 0.697), then calls judge.convertForfeits(): it returns 0.3332 IMD, 30% less, and does not revert because the 97% floor is 97% of 0.697. bob buys back afterwards. Expected: a sale the floor protects against a same-block push, or a sale the caller cannot time. Actual: the pot receives the pushed price.","severity":"low","snippet":"        imdOut = hook.sellPotMarg(marg);","title":"convertForfeits lets anyone sell the whole MARG pot at a moment of their choosing; the 97% floor is taken from the spot the caller has just pushed"}],"hash":"38b25d0604cad56463b58e4866071abee36688cbca964608edcf0e58fa41732e","nodeId":"2b828479-2392-48bf-93c2-6ae5d1c6b044","outcome":"completed","summary":"Review complete. The findings are in `.imd-findings.json` at the repository root, six entries, one with a proof.\n\n**What I read in full:** the four launch contracts (`src/MarginaliaRouter.sol`, `src/MarginaliaJudge.sol`, `src/MarginaliaTreasury.sol`, `src/MarginaliaPricer.sol`), plus the code they depend on or serve: `src/MarginaliaHook.sol`, `src/MarginaliaTypes.sol`, `src/OracleAttestation.sol`, `src/MarginaliaImpls.sol`, `src/interfaces/IIntake.sol`, the launch token, `HookFlags`, the test fixture and lifecycle suite, and the current `launch.json`. The hook is out of this launch's scope but it is the only caller of the companions, so I traced every call path through it.\n\n**What I could not reach:** the live Intake and the oracle signer's nature (EOA or registry) have no network here, so the callback gas figures use stubs. The fork rehearsal in `test/fork/` was not run. The vendored libraries in `lib/` were used, not re-audited. I ran no Slither or Mythril, only Foundry.\n\n**Findings, most severe first:**\n\n- **High. The post price is the author's own same-block spot.** Settlement was hardened, but `postPrice` in the pricer still reads slot0 or reserves in the posting block. A contract that dumps X, posts a BUY call through the router and buys back atomically records a depressed baseline, and the honest, unchanged market then settles it Right. The deposit returns and the score draws on the week's leaderboard pool. The proof under `test/scratch/PostPriceSameBlock.t.sol` fails on this code: post price 0.697 against a market of 1.0 before and 0.986 after, status Right.\n- **Medium. A judged week with no payable id locks its thesis pool forever.** `judgedSet` is set before filtering, so `payJudged` reverts `BadAnswer` on every call, `requestJudging` reverts, and `weekClosed` stays false so the hook can never sweep it. Reproduced with a one-id garbage ranking: about 5 IMD unreachable.\n- **Medium. The tree's `launch.json` is the hook launch's manifest** (kind `univ4_hook`, token and pool blocks). This contracts-only launch needs kind `evm_contracts` with four zero-argument entries, and its notes describe a superseded version.\n- **Low. The oracle callback stores the whole ranking under the 200,000-gas stipend.** Three ids fit, four fit with little margin, five or more run out of gas and the paid week is lost until a retry three days later.\n- **Low. The pricer reads v4 spot from a venue with zero liquidity**, where a one-wei swap sets the price for free. Liquidity is checked only at posting.\n- **Low. Anyone can time `convertForfeits`**, and the 97% floor is taken from the spot the caller just pushed. Measured: 0.333 IMD out instead of 0.478 after a push.\n\n**Verified clean:** the hub pool id constant matches the ETH/IMD 1% pool key, the canonical factory and WETH addresses are correct, all four runtimes are under the size limit and contain no DELEGATECALL, CALLCODE or SELFDESTRUCT, constructors take no arguments and make no external calls, each implementation locks itself, and the EIP-712 domain is rebuilt per clone so clone signatures verify. The repository's own 33 tests pass.","treeHash":null,"usage":{"cachedInputTokens":3332761,"inputTokens":706,"model":"claude-fable-5-1","outputTokens":63120,"runtime":"claude","turns":39,"wallClockMs":1375658}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"fa2b0b9c7ebc1547","findings":[],"hash":"4fb1b21388dbc5386f3c82769b3b75b34b4cb52a93677c05a69309064abe8f4f","nodeId":"491da7ce-b563-4ce9-9d1f-cce0bb54ad24","outcome":"failed","summary":"the task produced no changes; the agent's last message was: The existing launch.json is correct and needs no change. It was verified rather than rewritten.\n\n**What was checked**\n\n- **Manifest shape** has exactly the keys kind, contracts and notes, with kind set to evm_contracts. The four contract names are unique Solidity identifiers under 32 characters, every constructorArgs list is empty, and notes is a single string of 1,835 characters.\n- **Constructors match the source.** MarginaliaRouter, MarginaliaJudge and MarginaliaTreasury each declare a parameterless constructor that locks hook to address(1). MarginaliaPricer has no constructor at all. The compiled ABI confirms zero constructor inputs for all four, so the manifest's empty argument lists are exact.\n- **Protected probe rehearsal.** The four deployed runtimes are 17,803, 11,585, 1,449 and 7,770 bytes, all under the EIP-170 cap. A scratch scan that mirrors the probe's PUSH-aware loop found no DELEGATECALL, CALLCODE or SELFDESTRUCT in any of them. No constructor touches another contract, so they deploy on an empty chain.\n- **Notes claims match the code.** The Treasury's drip is 200 basis points keyed on the UTC day, and the Pricer's one-hour post span, 18-decimal scaling and aged-history requirement are all present in source.\n- **Build and tests.** `forge build` succeeds and `forge test --no-match-path 'test/fork/*'` passes 71 of 71 tests, including the Implementations suite that deploys all four through a factory with no arguments and rejects initialisation of the locked implementations.\n\n**Working tree** is clean. No file other than launch.json exists as my deliverable, and the only scratch file lives in test/scratch, which is discarded before submission.","treeHash":null,"usage":{"cachedInputTokens":315994,"inputTokens":194,"model":"claude-fable-5-1","outputTokens":5290,"runtime":"claude","turns":13,"wallClockMs":143941}},{"artifacts":[],"attempt":1,"bundleHash":"59c729263338a2362ec99dd74c94966155451d7b1d9f4032b255773a79277519","device":"fd744d20ac30e31f","findings":[],"hash":"5b9289bab76acb6d84029fd7db2d47f82cc9a5569b8d74a5a9e2a3b6fd9f2cc0","nodeId":"ff35a1e2-2305-4b17-bf5a-134a2541c161","outcome":"completed","summary":"Prepared the four implementations and fixed all six reproduced findings. Changes are documented in [ADAPTATION.md](/root/.identitymd/work/a895e1a2-58b3-4a43-8ba6-20de12c92414/ff35a1e2-2305-4b17-bf5a-134a2541c161/ADAPTATION.md).\n\n- `forge build`: passed.\n- `forge test`: 59 passed; fork suite skipped without RPC.\n- Protected deployment checks: passed.\n\nPosting and pot conversion now require mature price checkpoints. Mainnet deployment remains the launcher’s next step; no transaction was broadcast.","treeHash":"6b5673f9e1b548615ba5ddace73a210cf48f4ffa","usage":{"cachedInputTokens":5161600,"inputTokens":199541,"model":"gpt-6-astra","outputTokens":39954,"runtime":"codex","turns":9,"wallClockMs":1144419}},{"artifacts":[],"attempt":1,"bundleHash":"8af003a23bb9df634e6284eb39f7baebd57563ae9b801356bd7db037baebde69","device":"52c98c0dc01791cd","findings":[],"hash":"5fd7e914a4ebb6bef97f84acff10bafe1ad6d8fe7181c5f251af57c7ad043542","nodeId":"4fd3ac49-e4be-4f9b-a90d-838d3ef3c15d","outcome":"completed","summary":"The suite builds and passes again. Nothing else is needed; I'll leave the tree uncommitted for the harness as in previous rounds.\n\n**Outcome:** `forge build` passes and `forge test --no-match-path 'test/fork/*'` passes 177 of 177 tests, with the fork suite still skipping cleanly offline.\n\n**What was wrong.** The previous attempt's runtime error was a broken build, not a contract defect. The other node's third-round commit removed the SELL hold rule and its `SELL_HOLD_TOLERANCE_BPS` constant, scored only launch-pool calls, and fixed `sqrt` for inputs 1 to 3. My accepted `HoldRule.t.sol` still read the removed constant, so every test in the repository failed to compile.\n\n**What I changed, limited to my own two files:**\n\n- `test/HoldRule.t.sol`: the four tests that encoded the old tolerance rule are replaced by six that pin the new rule's edges and failure paths. A SELL author's own buy-back past the old 10% line is still Right. A SELL author dumping their entire balance is still Right. A wrong SELL call forfeits regardless of a gift. A SELL call with a reverting balance read still settles on price, with the sentinel checked on the emitted observation. The same reverting read voids a BUY call. A SELL call's balance jump is never a more adverse reading inside the block gap, while a higher price is. The BUY, replacement and series-cap tests are unchanged.\n- `test/PricerProperties.t.sol`: the fuzz floor property now covers the whole domain including 2, the pins assert `sqrt(2) == 1` plus a few neighbours, and the comments that described the open finding now describe it as fixed.\n\n**Findings.** None to report this round. The sqrt defect I reported previously is fixed in the tree, and the two new hook rules behave as documented under the inputs above, including the sentinel and in-gap replacement paths. No `.imd-findings.json` was written.\n\n**Not done, by design.** `ADAPTATION.md` and `README.md` still describe the old tolerance tests in their history sections; they are outside my allowed paths.","treeHash":"78ab7e39c0c0b97cae2754b3204d3160c85b579e","usage":{"cachedInputTokens":1168699,"inputTokens":450,"model":"claude-fable-5-1","outputTokens":20161,"runtime":"claude","turns":34,"wallClockMs":704804}},{"artifacts":[],"attempt":1,"bundleHash":"babd5b51602b540fd5d26ed266d5cee5d2e708d2b258d066af8952d5b2aba4b5","device":"63274cc86a9400de","findings":[],"hash":"65027068ed4a04582788addea6f2097c3e16ed56d979b045d04a362957c04a90","nodeId":"ff35a1e2-2305-4b17-bf5a-134a2541c161","outcome":"completed","summary":"The revision is complete. All 73 tests pass, including both reviewer proofs, and the responses file answers all 13 findings.\n\n**Outcome**\n\n- **Both held proofs now pass.** The pot-stranding proof and the zero-price proof failed on the starting tree and pass on the result.\n- **Eight reopening findings:** six fixed, two disputed as design decisions the brief fixes (any canonical Uniswap pool is a venue; the adverse-extreme settlement rule the launch specifies).\n- **Five advisory findings:** three fixed, one partially fixed (chain-id binding added, question-hash binding deliberately not), one disputed as belonging to the later hook launch.\n\n**What changed, by file**\n\n- `src/MarginaliaPricer.sol`: a price that rounds to zero is refused in every path (spot, TWAP, baseline, settlement); `sqrt` no longer overflows at the top of the range.\n- `src/MarginaliaJudge.sol`: `convertForfeits` sells the largest halving of the pot the pool absorbs, re-raising the hook's reason only when nothing sells; new permissionless `abandonRequest` so a thesis pool cannot be swept while a stale request is still deliverable; attestations must be about this chain.\n- `src/MarginaliaHook.sol`: a SELL call is voided only by a buy-back above 10% of the post balance and the deposit's worth, so dust cannot void it; an observation slot is never owned, since a more adverse reading replaces the latest entry; the author's balance is read by bounded staticcall and a failed read counts as not held; an unobserved call scores negative but keeps its refundable deposit; a week holds at most 120 theses and refuses the 121st before taking payment.\n- `src/MarginaliaRouter.sol`: a canonical v3 pool with zero liquidity is refused as a venue.\n- Tests: `test/RevisionFindings.t.sol` covers each change, `test/PotTranche.t.sol` keeps the reviewer's proof as a regression, and one existing no-data test was updated for the intended score change.\n- `ADAPTATION.md` and `README.md` record every change, the disputed items, and the remaining design limits.\n\n**Things to know**\n\n- The four implementation constructors are unchanged: empty, self-locking, no external calls.\n- Hook runtime bytecode is 24,442 bytes, under the limit by 134 bytes. Any further hook additions will need to trim elsewhere.\n- The self-venue finding is the one real exposure left open. Closing it needs a venue admission policy the brief does not give and no owner could tune, so it is documented rather than changed.","treeHash":"b920980a8199ae3becb7c7c30b7758464481260f","usage":{"cachedInputTokens":3731821,"inputTokens":802,"model":"claude-fable-5-1","outputTokens":53410,"runtime":"claude","turns":44,"wallClockMs":869963}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"2c968e88904ec22b","findings":[],"hash":"668a2fa678742284f2c8f381832392c4c64b906924311d8a1c9b49000ea781a7","nodeId":"d50b90ec-2bb8-4e57-b169-0042f10e9a18","outcome":"completed","summary":"All three earlier findings are fixed, and I found no new defect. The review is written to `.imd-findings.json` with an empty findings list and a coverage row for every entry point.\n\n**Settlement of my earlier findings**\n\n- **c7331916, self-provisioned venue farms the leaderboard (high): fixed.** The hook's difficulty function now returns zero for any venue that is not the launch pool, so settle and retract book no score there. I re-ran my exact recipe through the author's regression test. The 100x call on the attacker-only pool settles Right with score 0, week total 0, leaderboard share 0, and claiming reverts. A +10% launch-pool call still scores 20,538 and pays the leaderboard.\n- **80c42ce7, gift voids a correct SELL call (medium): fixed.** SELL calls have no hold rule now, so no balance growth can produce VoidSold. My recipe (no-MARG author, falling market, 0.5 MARG plus one wei gift, gifter settles) ends Right with the deposit intact and no keeper reward. A million-MARG gift behaves the same, and a BUY call still breaks when its author sells.\n- **4e3977e5, sqrt(2) returned 2 (low): fixed.** Inputs 1 to 3 return 1 before the loop. Exhaustive and fuzz floor checks pass.\n\n**Other checks on the revised tree**\n\n- The full suite passes, 177 tests. The changed lines I read as new code: slot replacement in observe, VoidNoData scored as wrong, the judge's halving conversion, abandonRequest and weekClosed, the thesis cap refusal, and the chainId check. None introduced a reproducible defect.\n- The cloned judge's EIP-712 domain rebuilds with the clone's own address, and the reentrancy guard works from zero storage.\n- The manifest lists the four implementations with empty constructor arguments, all far under the size limits.\n- One doc nit, not a defect: SPEC line 67 still calls VoidNoData \"no score\" while the code books a negative score for it, as its comment intends. It is recorded in a coverage row only.\n\nThe specialists' other leads were from before the fix and were either addressed by this round (pot stranding, observation squatting, reverting balanceOf, thesis cap, sweep race) or were design trust assumptions I did not keep earlier, so nothing new is reopened.","treeHash":null,"usage":{"cachedInputTokens":1421382,"inputTokens":418,"model":"claude-fable-5-1","outputTokens":23186,"runtime":"claude","turns":24,"wallClockMs":657149}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"40b27a75f026cec9","findings":[],"hash":"67a6b7dda4c48d38ed50ea797308ff7c8b550efc76811fe099da87128933746f","nodeId":"4fd3ac49-e4be-4f9b-a90d-838d3ef3c15d","outcome":"failed","summary":"This content was flagged for possible cybersecurity risk. If this seems wrong, try rephrasing your request. If you’re doing authorized security work that requires more cyber permissive safeguards, apply for Daybreak access via https://platform.openai.com/settings/organization/status-and-access before retrying.","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":"gpt-6-astra","outputTokens":0,"runtime":"codex","turns":7,"wallClockMs":1022630}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"6208734cdf5317a1","findings":[{"citation":"resolved","description":"Trust gap (access x economics). validateVenue accepts any hookless Uniswap v4 pool (or any factory-canonical v3 pool at any fee tier, or a v2 pair) that contains X and is quoted in IMD/WETH/ETH, with the only depth requirement being getLiquidity != 0. Pool creation on the PoolManager is permissionless, so the author can be the sole liquidity provider of the venue the note is priced on. The TWAP / adverse-extreme settlement in MarginaliaPricer and the permissionless observe() only defend against pumps that other traders would arbitrage; in a pool nobody else trades, every honest observation reads the author's price. The author therefore sets the window baseline (checkpointVenue + 1h), posts a BUY call with any targetBps, moves the dust pool with a few wei of IMD after the horizon, observes three times over an hour, and settles RIGHT. The difficulty score uses postPrice * totalSupply() of the author's own token, so the mcap tier is 3. The positive score becomes a claim on the week's leaderboard pool (50% of every stamp, fee, forfeit and treasury drip), capped at 10% per wallet, which Sybil wallets lift. The same works for real tokens: a fresh v4 pool for USDC/WETH at an unused fee/tickSpacing, or a fresh v3 pool at an unused fee tier, is canonical and author-owned. Cost: the 0.1 IMD stamp and gas; the 0.5 IMD deposit comes back. Victims: honest writers whose leaderboard share is diluted, and the treasury's drips which are paid out to the attacker.","line":208,"path":"src/MarginaliaRouter.sol","reproduction":"State: hook bound, leaderboard pool of week w funded (fundPot(100 ether) by anyone). Attacker: deploy ERC-20 X (supply 1e30); manager.initialize(PoolKey(X/IMD, fee 3000, spacing 60, hooks 0), sqrtP 2^96); add liquidity 1e6 over the full range (a few wei of each token). router.checkpointVenue(p, xKey) with p.x = X, p.venue = {UniV4, xKey.toId()}; warp +1h, roll +300; router.note(p, xKey, 10 ether, 1, deadline) with side Buy, targetBps 100000 (10x), horizonDays 1 -> succeeds. Warp to horizonEnd; swap 1e9 wei of IMD into the dust pool (price of X rises far past 10x); observe(id) three times 25 blocks / 30 min apart; warp past SETTLE_WINDOW; settle(id). Expected: a venue nobody but the author trades cannot post or cannot settle RIGHT. Actual: status == Right, records[attacker].score > 0, leaderboardShare(w, attacker) == 10% of the week's pool, claimable after the week. Proof test test/scratch/VenueDust.t.sol fails on this code with 'self-priced dust venue settled RIGHT' and passes once the router refuses such a venue or the call cannot settle RIGHT on it.","severity":"high","snippet":"            if (manager.getLiquidity(PoolId.wrap(v.ref)) == 0) revert BadVenue();","title":"Caller-chosen price venue only needs liquidity > 0: an author who owns all of a canonical pool's dust liquidity dictates baseline and settlement and farms the leaderboard pool"},{"citation":"resolved","description":"Asymmetry between the Buy and Sell branches of the hold rule. For a BUY call, 'held' means balance >= postBalance, which only the author can break (nobody can take tokens from them). For a SELL call, 'held' means balance <= postBalance, which any third party breaks by transferring 1 wei of X to the author, since balances are read with IERC20(n.x).balanceOf(n.author) at each observation. The author never traded, the call is correct, yet settle() returns VoidSold: the deposit (0.5 IMD-equivalent of MARG) goes to the pot, the author is booked as broken with a negative score, and the settle caller (who can be the griefer) receives 2% of the deposit. Cost to the attacker is dust plus gas; every SELL call in the system is exposed, including ones whose author's score the attacker competes with on the leaderboard.","line":517,"path":"src/MarginaliaHook.sol","reproduction":"State: matured MARG/IMD checkpoint. alice: router.note(_margNote(Side.Sell, 7000, 1), key, 10 ether, 1, deadline) -> postBalance == alice's MARG balance. bob sells 2,000,000 MARG through any v4 router so margPriceInImd() < 0.7e18 (the -30% call is correct). carol: token.transfer(alice, 1). Anyone observes 3 times over 1h+ after horizonEnd; carol calls settle(id) after the window. Expected: status Right, deposit intact. Actual: status VoidSold (3), deposit 0 and forfeited to potMarg, carol's MARG balance +2% of the deposit, records[alice].broken == 1. Proof test test/scratch/SellCallAirdrop.t.sol fails here with '3 != 1' and passes when the hold rule tolerates inbound transfers (for example compare against the author's X balance reduced only by outflows, or use postBalance <= balance < postBalance + tolerance / track via the author's own sells).","severity":"medium","snippet":"                if (n.side == T.Side.Buy ? obs[i].balance < n.postBalance : obs[i].balance > n.postBalance) {","title":"Anyone can void a correct SELL call by sending its author 1 wei of X: the deposit is forfeited and the sender collects the keeper reward"},{"citation":"resolved","description":"Asymmetry between the two MARG->IMD exits: claimDeposit(asImd) sells one note's deposit, while the judge's only conversion path sells hook.potMarg() in full (no amount argument) and sellPotMarg is restricted to the judge, so nobody can sell a partial amount. The floor at MarginaliaHook.sol:678 is 97% of the router window's maximum MARG price (>= current spot). The swap runs with DATA_EXEMPT, so no hook fee, but the pool's LP fee of 1.25% still comes off the input: at infinitesimal size the output is 98.75% of spot, leaving 1.75% for price impact. For a concentrated position of liquidity L at sqrtP=1, the full fill yields 0.9875/(1+0.9875*A/L) of spot value, which drops below 0.97 once A > ~1.83% of L. potMarg only grows (forfeits from settle/retract/settleThesis) until a conversion succeeds, there is no incentive to call convertForfeits promptly, and once potMarg crosses the threshold every call reverts InvalidUnlock until outside liquidity is added. The forfeited MARG then never reaches the IMD pools that pay writers.","line":87,"path":"src/MarginaliaJudge.sol","reproduction":"State: fixture pool (L = 1e7 ether, 1 MARG = 1 IMD, LP fee 12500), potMarg = 200,000 MARG accumulated from forfeited deposits (400,000 x 0.5 IMD-equivalent) with no conversion in between, window max == spot. judge.convertForfeits(): hook.sellPotMarg(200000e18) computes minimum = 200000e18 * 0.97 = 194,000 IMD; the exact-input swap of 200,000 MARG returns 0.9875*200000/(1+0.01975) = 193,675 IMD < minimum, so unlockCallback reverts InvalidUnlock and potMarg stays 200,000 forever (a later, larger pot fails harder). Expected: a conversion path that sells what the pool can absorb (an amount parameter on convertForfeits / sellPotMarg, with the floor applied to that amount). On the fixture the same state can be built by forfeiting deposits; the threshold scales with pool depth, so on a thinner mainnet launch pool the stuck size is proportionally smaller.","severity":"low","snippet":"        imdOut = hook.sellPotMarg(marg);","title":"convertForfeits always sells the entire pot against a 97%-of-window-max floor that must also absorb the 1.25% LP fee, so a pot above ~1.8% of pool depth can never be converted"},{"citation":"resolved","description":"Access/trust boundary. SPEC.md (section 'POT AND JUDGING') states the callback 'verifies the signature and that questionHash equals its own recomputation'. onOracleResult verifies only the signer, window, quorum/panel counts and consumes a.requestId; it does not compare a.questionHash with any hash of questionBody(day), nor a.chainId with block.chainid, nor bind a.requestId to the intake requestId it deletes from pendingDay. Per the oracle-consumer reference the questionHash cannot be recomputed exactly for a relative window, so full pinning is not possible as written; but as a result the pairing of a signed answer to the week it pays rests entirely on the Intake. A signed attestation for this consumer (any week, any question, any chain) presented by the Intake under a pending week's intake id is accepted and pays that week's 50/30/20 to whoever its ids name. This is a documented-guarantee mismatch rather than an unprivileged exploit; report it as a trust assumption the README/SPEC should state, or store keccak256(questionBody) at request time and at least check a.chainId == block.chainid and that the ranked ids belong to that week (judgedOf already filters by week, which bounds the damage to the wrong ranking within the same week).","line":211,"path":"src/MarginaliaJudge.sol","reproduction":"State: week 5 requested (intake id R5, pendingDay[R5] = 6). The Intake delivers onOracleResult(R5, A, sig) where A is a validly signed attestation for this judge whose questionHash is that of some other question (e.g. a week-4 ranking that was never delivered, or any other body naming this consumer), chainId 10, answerType bytes32[] with three ids of week-5 theses. Expected per SPEC: BadAnswer because questionHash does not match the judge's own body. Actual: accepted; judgedSet[5] = true; payJudged(5) pays the pool to the attestation's ids.","severity":"low","snippet":"        _verifyAttestation(a, signature);","title":"Judge trusts the Intake for request/answer pairing: questionHash and chainId of the signed attestation are never compared with the question it paid for"}],"hash":"75d63209089e46c0e4ee261a938085f7385fd957a30ab593af15077772dded36","nodeId":"fea98e47-f220-46d0-b83a-a1526c8fbaae","outcome":"completed","summary":"The sanity run confirms the full chain: the dust-venue call settles RIGHT, the attacker's week score is positive, and their leaderboard share is exactly the 10% per-wallet cap of the week's pool (5.005 of 50.05 IMD; the pool includes their own stamp's accrual). The sanity file was removed; only the two proof files remain in test/scratch/.\n\n## Recap\n\nThe review is complete. Findings are in `.imd-findings.json` with 4 findings and a coverage row for every listed entry point (none unreached), plus three invariant rows.\n\n**Findings, most severe first:**\n\n1. **High, Router line 208.** The note's price venue is caller-chosen and only needs liquidity > 0. An author who provides all of a canonical pool's dust liquidity (a fresh hookless v4 pool, or a v3 pool at an unused fee tier, for any token including their own) dictates both the checkpoint baseline and every settlement observation. The honest-observer defence has nothing to observe but the author's price. Proof `test/scratch/VenueDust.t.sol` fails on this code: a 10x call settles RIGHT and the author takes the capped 10% of the week's leaderboard pool, Sybil-liftable.\n\n2. **Medium, Hook line 517.** The SELL hold rule is `balance > postBalance → VoidSold`, so anyone can void a correct SELL call by transferring 1 wei of X to the author. The deposit is forfeited, the author is scored as broken, and the griefer collects the 2% keeper reward. The BUY branch has no such third-party trigger. Proof `test/scratch/SellCallAirdrop.t.sol` fails here (status 3 instead of 1) and passes without the airdrop.\n\n3. **Low, Judge line 87.** The judge's only conversion path sells the whole pot against a 97%-of-window-max floor that must also absorb the 1.25% LP fee. Above roughly 1.8% of pool depth the conversion reverts forever, stranding forfeited MARG. No proof test, concrete arithmetic given.\n\n4. **Low, Judge line 211.** SPEC says the callback checks questionHash against its own recomputation. It does not, nor chainId; answer-to-week pairing rests entirely on the Intake. Reported as a documentation versus implementation trust gap.\n\n**Covered in depth:** the init locks on all three implementations and clone semantics under OZ v5 (ReentrancyGuard from zero storage, EIP-712 domain rebuilt per clone), every judge-only and manager-only guard, both unlock callbacks, the v3 callback, treasury drip, and the Buy/Sell, checkpoint/postPrice, and claimDeposit/convertForfeits pairs. **Not reached:** the economic incentive to observe wrong calls at all (keeper reward vs gas), which belongs to the economics specialist, and no fork run against mainnet venues.","treeHash":null,"usage":{"cachedInputTokens":2247935,"inputTokens":454,"model":"claude-fable-5-1","outputTokens":46721,"runtime":"claude","turns":31,"wallClockMs":875255}},{"artifacts":[],"attempt":1,"bundleHash":"a0be08290ca14faf89db4c99e0438bda850f559d51626af950eee88a32132537","device":"98b4506bef931d13","findings":[{"description":"Revision round 2 (finding 272fbe0d) changed the Babylonian seed from `(x + 1) / 2` to `x / 2 + 1` so that `sqrt(type(uint256).max)` no longer overflows. The new seed equals x itself when x == 2 (2 / 2 + 1 == 2), so the `while (z < y)` guard (y starts at x) is false on entry, the loop never runs, and the function returns y == 2. The integer floor of sqrt(2) is 1. Every other input in [0, 2^256 - 1] is rooted correctly (verified by fuzzing in test/PricerProperties.t.sol with x == 2 excluded, and by exhaustive check of 0..1023 in the proof). Reachability: `difficulty` is the only in-repo caller and passes `30e8 / horizonDays` with horizonDays in 1..90, so the smallest argument is 33,333,333 and no score is affected; the defect is only observable through the public `sqrt` itself. Fix: seed with `x / 2 + 1` only when that is below x, e.g. `uint256 z = x / 2 + 1; if (z > x) z = x;` is not enough (z == x is the failing case); use `y = x; z = x / 2 + 1; if (z >= y) z = y - 1 + 1 ...` — simplest correct form: `if (x < 4) return x == 0 ? 0 : 1;` before the loop, keeping the overflow-safe seed for the rest.","line":101,"path":"src/MarginaliaPricer.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {MarginaliaPricer} from \"src/MarginaliaPricer.sol\";\n\n/// @dev Proof for the finding \"sqrt(2) returns 2\": the reseeded Babylonian start `x / 2 + 1` equals x when\n/// x == 2, so the `while (z < y)` loop never runs and the function returns y == x == 2. The integer floor\n/// of sqrt(2) is 1. Every other input in [0, type(uint256).max] is rooted correctly.\ncontract SqrtOfTwoTest is Test {\n    MarginaliaPricer private pricer;\n\n    function setUp() public {\n        pricer = new MarginaliaPricer();\n    }\n\n    function testSqrtOfTwoIsOne() public view {\n        assertEq(pricer.sqrt(2), 1, \"sqrt(2) must floor to 1\");\n    }\n\n    function testSqrtIsTheIntegerFloorOnEverySmallInput() public view {\n        for (uint256 x = 0; x < 1024; ++x) {\n            uint256 y = pricer.sqrt(x);\n            assertLe(y * y, x, \"sqrt above the root\");\n            assertGt((y + 1) * (y + 1), x, \"sqrt below the floor\");\n        }\n    }\n}","reproduction":"Deploy MarginaliaPricer and call sqrt(2). Expected: 1 (floor of 1.414...). Actual: 2. Also sqrt(2) * sqrt(2) == 4 > 2, which violates the integer-floor property every other input satisfies. The accepted suite's fuzz test testFuzzSqrtIsTheIntegerFloor failed on this tree with counterexample args=[2] before x == 2 was excluded.","severity":"low","title":"MarginaliaPricer.sqrt(2) returns 2: the revision's reseed skips the Babylonian loop at x == 2"}],"hash":"9701a2d204b980cc241b83f0abfc2009d89276cf29393c7bf33e450306a36305","nodeId":"4fd3ac49-e4be-4f9b-a90d-838d3ef3c15d","outcome":"completed","summary":"Done. The suite is green from a clean, network-free build and the work is committed.\n\n**What was wrong.** The tree held my accepted tests merged under a later contract commit (revision round 2). That commit made the Pricer refuse prices that round to zero, changed `weekClosed` to stay open while a request is deliverable, added `abandonRequest`, and reseeded `sqrt`. Six of my accepted tests failed against it, which is the most likely cause of the rejected attempt.\n\n**What I changed, all under `test/`:**\n- `PricerProperties.t.sol`: the four fuzz tests now expect `EmptyPool` where the adverse extreme or TWAP rounds to zero instead of asserting a zero price. Added sharp-threshold bisection tests for `fromSqrt` in both orientations, a dust v4 series, v2 dust ratio via a frozen pair mock, a post price whose two legs price but whose product does not, and a pin that every argument `difficulty` can pass to `sqrt` is rooted exactly.\n- `CompanionFailures.t.sol`: `testWeekClosedStates` rewritten around the new rule (28 days alone no longer closes a week with a live request; abandoning does; a retry reopens; a judged week never closes). New tests for `abandonRequest` refusals (unrequested, before deadline, exactly at deadline, twice, judged week), that abandoning moves no IMD, and the nine-tranche bound of `convertForfeits` using a slippage-capped hook mock.\n- `HoldRule.t.sol` (new): SELL tolerance held at exactly the bound and broken one wei past it, the deposit's-worth bound for a small holder, no downward tolerance on BUY, breach never replaced by a non-breach inside the gap, breach replacing a non-breach, equal reading refused, and the series cap admitting only a more adverse reading.\n\n**Finding reported, not tested around.** `sqrt(2)` returns 2 because the overflow-safe seed `x / 2 + 1` equals x there and the loop never runs. It is unreachable through `difficulty` (smallest argument is 30e8 / 90), so severity is low. It is in `.imd-findings.json` with a self-contained proof that fails on this tree; the fuzz excludes that single input with a comment pointing at the finding.\n\nResults from `forge clean` then `env -i … forge test --offline --no-match-path 'test/fork/*'`:\n\n| Suites | Tests passed | Failed |\n|---|---|---|\n| 16 | 165 | 2 (both in `test/scratch/`, the intended proof) |\n\nGit status is clean apart from paths the harness excludes (`test/scratch/`, `.imd-findings.json`). Commit `4727d53` touches only the three test files.","treeHash":"48d5776e0670ddeb085f5dc191b6c82120c9f879","usage":{"cachedInputTokens":2323885,"inputTokens":578,"model":"claude-fable-5-1","outputTokens":44404,"runtime":"claude","turns":41,"wallClockMs":1224171}},{"artifacts":[],"attempt":1,"bundleHash":"806c5a296f1089b823b6725e7c0adc5f428cb9738a5856164857846a3a66adfc","device":"1f9cb1750ebf47ed","findings":[],"hash":"9d54985cca138cfd5a84a536c1f18ce09ca520d6e4eb972ab4cbc90a8aac7a78","nodeId":"ff35a1e2-2305-4b17-bf5a-134a2541c161","outcome":"completed","summary":"All three findings reproduced on the unchanged tree and are now fixed, tested, and answered in `.imd-responses.json` (the harness's own exclude rule keeps it out of git status, which is expected).\n\n**What changed**\n\n- **Self-priced venue (high, c7331916):** `_difficulty` in `src/MarginaliaHook.sol` returns zero for any call not priced on the launch pool. Such calls still return or forfeit their own deposit on price and count in the right/wrong tallies, but book no score and no leaderboard share. The reviewer's scenario now settles Right with share zero and a reverting claim. I chose this over a multiple cap or depth-derived tier because those leave a free \"right\" on a self-provisioned pool, and free rights still dilute honest wallets pro-rata.\n- **Gifted SELL call (medium, 80c42ce7):** the SELL hold rule is removed entirely. Any balance-growth rule is a stranger's transfer away from voiding a correct call, so SELL calls settle on price alone. The BUY hold rule and its failed-read sentinel are unchanged. The one test that encoded the old rule was renamed and inverted with the reason in its comment.\n- **sqrt(2) (low, 4e3977e5):** inputs 1 to 3 return 1 before the loop in `src/MarginaliaPricer.sol`. The pricer is one of the four deployed contracts, so it is worth fixing here.\n- **Docs:** SPEC section 4.3, 4.4 and section 10, README, and a round-3 section in ADAPTATION.md now describe both rules as implemented.\n\n**Verification**\n\n- `forge build --sizes` passes. Hook runtime is 24,411 bytes, down 31 bytes, under the EIP-170 cap.\n- `forge test` with an empty environment: 85 tests pass, the fork suite skips. New regressions live in `test/Round3Findings.t.sol` (10 tests including an exhaustive and a fuzzed sqrt floor check).\n- The unchanged supplied protected deployment test passed from scratch against the four rebuilt creation bytecodes with empty constructor arguments on chain id 1.\n\n**Scope note:** the implementation constructors are untouched. The launch-pool-only scoring rule is a product-level change the finding required. A venue policy that lets other canonical pools score again would be the requester's decision, and ADAPTATION.md says so.","treeHash":"93f02176ce99dcb30cfb5b6062e6f1f5ba35e80d","usage":{"cachedInputTokens":3222478,"inputTokens":706,"model":"claude-fable-5-1","outputTokens":42450,"runtime":"claude","turns":56,"wallClockMs":1274249}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"5d667e4b0751bcb5","findings":[{"citation":"resolved","description":"sellPotMarg (MarginaliaHook.sol:673-682) is judge-only and MarginaliaJudge.convertForfeits (MarginaliaJudge.sol:84-88, `imdOut = hook.sellPotMarg(marg);` with marg = the entire potMarg) is the only caller, so the pot can only ever be sold all at once. The slippage floor is 97% of router.postPrice(venue, true), which for a v4 venue is the MAXIMUM of the window's readings and the current spot (MarginaliaPricer.postPrice: _adverse(w.xMax, x, false)). The exact-input sale pays the 1.25% LP fee (LP_FEE = 12_500), so its own price impact may not exceed about 1.8% of the pool's virtual MARG reserve (L / sqrtP for a concentrated position). Seam boundary x invariant: the floor is a fixed band against a pre-trade maximum, the quantity is forced to the full pot, and potMarg is monotone (every Wrong/VoidSold/retract/thesis forfeit adds to it, MarginaliaHook.sol:609). Once potMarg > ~1.8% of virtual reserve, unlockCallback's `if (imdOut < extra) revert InvalidUnlock();` (MarginaliaHook.sol:842) fires on every call, with an honest fresh window as much as with a manipulated one, and nothing can ever shrink the pot. Forfeits never reach thesisPool / leaderboardPool / refundPool again (the _accrue(imdOut) at line 680 is never reached): the project's prize funding from forfeits is permanently broken, and the MARG sits as ERC-6909 claims in the hook forever. Aggravating: because the floor is the window MAXIMUM, any genuine fall of more than ~1.75% in MARG within the 6-hour window also blocks conversion until the window expires, and anyone can pin the maximum high for 6 hours with a brief pump followed by checkpointVenue. Half the pot would clear the same floor (shown in the reproduction), so the all-or-nothing rule, not the band, is what fails. Fix preserving the design: let the judge (or anyone) convert a caller-chosen slice bounded by the pot (e.g. convertForfeits(uint256 amount) forwarding to sellPotMarg(amount)), or have sellPotMarg cap the slice so the quoted impact stays inside the band, and base the floor on the window's spot/TWAP rather than its maximum.","line":678,"path":"src/MarginaliaHook.sol","reproduction":"Fixture: MARG/IMD hook pool, 800e18 liquidity on [-6000, 6000] at 1:1 (~207 MARG in range, ~800 virtual). alice posts 40 notes via router.note(p, key, 1 ether, 1, deadline) and retracts each (hook.retract): potMarg ~= 19.6e18 MARG (40 x ~0.49). Warp 7 h and roll 2100 blocks so the old window expires; router.checkpointVenue(...) a fresh honest window; warp 2 h, roll 600. Call judge.convertForfeits(). Expected: the pot is converted (at least in part). Actual: revert InvalidUnlock() from MarginaliaHook.unlockCallback; potMarg unchanged. Numbers: spot 1.1025 (sqrtP 1.05 after 40 x 1 IMD buys), floor = 19.6 x 1.1025 x 0.97 = 20.96 IMD; sale: 19.6 x 0.9875 = 19.36 MARG after fee, 1/sqrtP moves 0.9524 -> 0.9766, sqrtP 1.05 -> 1.0240, IMD out = 800 x (1.05 - 1.0240) = 20.8 IMD < 20.96. hook.sellPotMarg(1 ether) from any other account reverts Unauthorized(), so no smaller sale exists. The pot keeps growing with every later forfeit. Also run: test/scratch/MathAudit.t.sol testForfeitPotBecomesPermanentlyUnconvertible (passes on this code = defect present); the proof file fails here with InvalidUnlock().","severity":"high","snippet":"        uint256 minimum = FullMath.mulDiv(amount, router.postPrice(venue, true), 1e18) * 97 / 100;","title":"Forfeited MARG becomes permanently unconvertible: convertForfeits sells the whole pot against a 97%-of-maximum floor, and the pot only grows"},{"citation":"resolved","description":"fromSqrt truncates sqrtP^2 / 2^192 x 1e18 to an integer and, when X is token0, returns it even when it is 0 (line 288); when X is token1 it returns FullMath.mulDiv(1e18, 1e18, p) which is also 0 whenever p > 1e36 (line 290, no check on the result). The zero flows through _spotInQuote -> observe -> checkpoint/postPrice unchanged (FullMath.mulDiv(0, q, 1e18) = 0), and _postNote stores n.postPrice = 0 with no check (MarginaliaHook.sol:447). At settlement (MarginaliaHook.sol:525) `settlePrice * 10_000 >= n.postPrice * n.targetBps` is 0 >= 0 for a BUY call and `settlePrice * 10_000 <= 0` holds for a SELL call too, so the call is RIGHT whatever the market does, the deposit is returned, and _difficulty is computed with mcap = 0 (tier 1) giving a positive score that counts toward the week's leaderboard pool. Seam boundary x precision x invariant: the invariant 'a call is falsifiable against its baseline' is only enforced when the baseline is non-zero, and the price math produces exactly 0 at a reachable edge. The edge is reachable through the router's canonical-venue check: validateVenue accepts any hookless v4 pool with non-zero liquidity whose other asset is IMD/WETH/native, and the PoolManager lets anyone initialise such a pool at any tick in [MIN_TICK, MAX_TICK]; a price below 1e-18 quote per 1e18 X is reached just past tick -414,500 (X token0; fromSqrt(getSqrtPriceAtTick(-420000), true) == 0, while -414,486 still yields 1) or past +414,500 (X token1; fromSqrt(getSqrtPriceAtTick(414500), false) == 0), both legal ticks far inside [MIN_TICK, MAX_TICK]. Fix: revert EmptyPool() (or a dedicated error) when the computed price is 0 on either branch, and have _postNote reject postPrice == 0.","line":288,"path":"src/MarginaliaPricer.sol","reproduction":"Mainnet-equivalent state: ERC-20 X with code; hookless v4 pool X/IMD (fee 3000, spacing 60) initialised at tick -420000 if X < IMD else +420000, with 1e18 liquidity on [tick-6000, tick+6000]. Calls: router.checkpointVenue(p, xKey) with p.x = X, p.venue = (UniV4, xKey.toId(), -, -); wait 1 h; router.postPrice(router.validateVenue(p, xKey), true) == 0; router.note(p, xKey, 10 ether, 1, deadline) with side Buy, targetBps 50_000 (5x), horizon 1 day: noteOf(id).postPrice == 0. At horizonEnd: hook.observe(id) three times spaced 25 blocks / 30 min with the pool untouched (xRead = 0 each time). After horizonEnd + 6 h + 1: hook.settle(id). Expected: a 5x call on a flat price is WRONG (or the post is refused). Actual: status Right, deposit refundable, records(alice).score > 0. Run test/scratch/MathAudit.t.sol testZeroPostPriceMakesTheCallVacuouslyRight.","severity":"medium","snippet":"        if (xIsToken0) return p;","title":"fromSqrt returns 0 instead of reverting for a sub-1e-18 X price; a zero postPrice makes a call vacuously RIGHT and earns score"},{"citation":"resolved","description":"For v4 venues and the ETH->IMD hub leg, settlePrice is the extreme over the observation series that is least favourable to the call (minimum for BUY, maximum for SELL; lines 181-194). The brief states that 'any honest observation pins the price' and 'a two-block pump-observe-unwind moves neither rule'. That holds only in the direction that favours the author. In the adverse direction a single observation taken in the same transaction as a swap is enough: observe (MarginaliaHook.sol:485-500) has no caller restriction and reads the pool's spot at that instant (line 496), so a contract can swap, call observe, and swap back atomically. A competitor for the week's pro-rata leaderboard pool (or anyone who wants a deposit forfeited to the pot) can therefore turn every BUY call Wrong by one dump of X (or of ETH in the hub pool for WETH/native-quoted venues) and every SELL call Wrong by one pump. The author then forfeits the whole deposit (0.5 IMD-equivalent) to the pot and loses difficulty score; the attacker's cost is the round-trip fees on the venue (LP fee twice, plus the hook's 3% quiet sell fee when the venue is the MARG pool itself) scaled by the size needed to cross the target, with no holding period and no exposure to arbitrage. Seam boundary x invariant: the extreme operator makes the settlement a function of the single worst observation, so the one-hour span requirement constrains only the honest side. The 1-hour span and 20-block gap do not help because the manipulated observation can be any one of the series. Fix preserving the design: settle v4 and hub legs on a time-weighted or median value of the series (e.g. the median of observations, or the hook accumulating its own tick cumulative in afterSwap and using a TWAP as for v3/v2), or require an extreme to be confirmed by a second observation at least OBS_GAP_BLOCKS later before it can set the price.","line":184,"path":"src/MarginaliaPricer.sol","reproduction":"Fixture pool: 10_000_000e18 liquidity on [-6000, 6000] at 1:1, checkpoint matured. alice: router.note(_margNote(Buy, 11_000, 1 day), key, 10 ether) (postPrice ~1.0e18). bob buys 1.5M IMD of MARG: spot ~1.32e18 and stays there for the horizon. At horizonEnd: hook.observe(id) (xRead 1.32e18). Roll +25 blocks, warp +30 min. carol, in one block: sell 1.5M MARG (spot 0.96e18 < 1.0e18), hook.observe(id), buy back with the IMD received (spot back > 1.19e18). Roll +50, warp +60 min: hook.observe(id) honest again. After horizonEnd + 6 h + 1: hook.settle(id). Expected: a +32% move held for the whole horizon and both honest observations settles RIGHT. Actual: settlePrice = min series = 0.96e18 < 1.1 x postPrice, status Wrong, alice's deposit forfeited to potMarg (2% to the keeper), score negative; carol's MARG loss is under 6% of the 1.5M she cycled (3% quiet fee + two 1.25% LP fees) and her IMD balance is unchanged. Run test/scratch/MathAudit.t.sol testOneBlockDumpObserveUnwindMakesAnHonestRightCallWrong.","severity":"medium","snippet":"                x = _adverse(x, obs[i].xRead, buy);","title":"The adverse-extreme rule is movable by any third party in one transaction: dump, observe, unwind makes a genuinely right call WRONG"}],"hash":"a207de480b285c4509afc8ec880bb9a0848a0e2013cd7dade6a0994d494bf956","nodeId":"28757ca8-a14b-417f-9c6d-883230a60a93","outcome":"completed","summary":"The review is complete. `.imd-findings.json` holds three substantiated findings and a coverage row for all 33 listed entry points plus three invariant rows. No tracked file was changed; the scratch tests and the findings file are git-ignored by the harness.\n\n**Findings**\n\n1. **High. Forfeited MARG becomes permanently unconvertible.** `MarginaliaJudge.convertForfeits` always sells the entire pot, and `MarginaliaHook.sellPotMarg` demands at least 97% of the window's maximum MARG price. With the 1.25% LP fee, the sale's own impact may not exceed about 1.8% of the pool's virtual reserve. The pot only grows and no partial sale exists, so past that size every conversion reverts forever and forfeits never fund the thesis or leaderboard pools again. Reproduced on a thin pool with 40 retracted notes against a fresh, honest, mature window. The proof test in `test/scratch/ForfeitPotStuck.t.sol` fails on this tree with InvalidUnlock.\n\n2. **Medium. A zero post price makes a call vacuously Right.** `fromSqrt` returns 0 instead of reverting when the X price is below one wei of quote per 1e18 X, which a canonical hookless v4 pool parked past tick ±414,500 produces. The note stores postPrice 0, settlement compares 0 ≥ 0, and a 5x call on a flat price settles Right with a positive score. Reproduced end to end through the router.\n\n3. **Medium. The adverse extreme is movable by a third party in one transaction.** `observe` is permissionless and reads spot in the same block, so dump, observe, buy back atomically sets the settlement minimum. A BUY call that was genuinely up 32% for the whole horizon settles Wrong and forfeits its deposit. This inverts the brief's claim that a pump-observe-unwind moves neither rule: it holds only in the author's favour.\n\n**Verified as holding** in my area: stamp and deposit arithmetic in both swap paths, the exact-output fee gross-up, accrual split, leaderboard pro-rata and cap, refund division, sweep subtraction, treasury drip, the v3 floor-rounding TWAP (the Slither weak-PRNG line is a false positive), the v2 wrapping accumulator, and score bounds at every legal extreme. The baseline suite of 59 tests passes.\n\n**Not reached**: nothing in the listed entry points. The 1/16-step log2 precision and the 18-decimal assumption are documented limitations and are recorded as notes, not defects.","treeHash":null,"usage":{"cachedInputTokens":2388149,"inputTokens":546,"model":"claude-fable-5-1","outputTokens":58692,"runtime":"claude","turns":28,"wallClockMs":957186}},{"artifacts":[],"attempt":2,"bundleHash":"61fd4b84154e7633ef3163be91ef188aaba3ef2b86853f3f4adb6bee21f79853","device":"d68ba89c0b30801c","findings":[],"hash":"ad6f2e3202e7b8bb97969756fb5cecfcdc6a15460dd71d026278dabb9bd5ba1d","nodeId":"491da7ce-b563-4ce9-9d1f-cce0bb54ad24","outcome":"completed","summary":"launch.json is revised and verified. The only file changed is the manifest.\n\n**What changed**\n\nThe previous round was rejected because it produced no diff. This round keeps the contract list and empty constructor arguments, which were already correct, and rewrites the notes so every number the brief names is stated and traced to source. The notes now run 3,000 characters, under the 4,000 cap.\n\n**What was verified against the accepted source**\n\n- **Constructors.** Router, Judge and Treasury each declare a parameterless constructor that writes address(1) into the hook slot. Pricer has no constructor. The compiled ABIs show zero constructor inputs for all four, so the empty argument lists are exact.\n- **Lock and init.** Each init reverts when hook is already set and requires the caller to be the hook it names, so only zero-storage clones can ever be initialised, once, by the cloning hook.\n- **Brief numbers.** Judge threshold 2 IMD, oracle price 0.5 IMD with a 1 IMD ceiling, a 7-member panel with quorum 5, a 3-day retry deadline, the 50/30/20 split in payJudged, treasury drip of 200 basis points per UTC day, and the Pricer's one-hour minimum and six-hour maximum checkpoint age.\n- **Settlement rule.** v3 and v2 venues settle on the accumulator TWAP between first and last observation. v4 venues and the hub leg take the least favourable observation for the call.\n- **Protected probe.** Runtime sizes are 17,803, 11,585, 1,449 and 7,770 bytes, all under the EIP-170 limit. No constructor touches another contract, so deployment on an empty chain succeeds.\n- **Manifest shape.** Exactly the keys kind, contracts and notes. Four unique names, longest 18 characters, each entry with only contract and constructorArgs.\n\n**Check results**\n\n```\nforge build: ok\nforge test --no-match-path 'test/fork/*': 71 passed, 0 failed\ngit diff --stat: launch.json | 1 insertion, 1 deletion\n```\n\nNothing is left open. The manifest is ready for the manifest validation step.","treeHash":"857399856f49659569b57a37c064334396728c1f","usage":{"cachedInputTokens":471648,"inputTokens":258,"model":"claude-fable-5-1","outputTokens":7414,"runtime":"claude","turns":18,"wallClockMs":184000}},{"artifacts":[],"attempt":1,"bundleHash":"2e848d3a11c9de572ccf084ccea1c4071e72a184d5afd0d018c9db678eb2d73e","device":"228636b860e0212c","findings":[],"hash":"b403073f12774acd8e2f118e93c55d3f6da12ce10d2c9b375faad3784f9cb349","nodeId":"491da7ce-b563-4ce9-9d1f-cce0bb54ad24","outcome":"completed","summary":"Created [launch.json](/home/imd/.identitymd/work/a895e1a2-58b3-4a43-8ba6-20de12c92414/491da7ce-b563-4ce9-9d1f-cce0bb54ad24/launch.json) listing all four companion contracts with empty constructor arguments.\n\nManifest format and compiled ABIs checked. Offline build passed; all 59 non-fork tests passed. Only `launch.json` is changed for submission.","treeHash":"becc8828f8274d70b86cc1320e48cdb06a1efe9b","usage":{"cachedInputTokens":473216,"inputTokens":60848,"model":"gpt-6-astra","outputTokens":4133,"runtime":"codex","turns":4,"wallClockMs":102004}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"584bd638e7e022f0","findings":[{"citation":"resolved","description":"validateVenue accepts any hookless v4 pool whose key recomputes the id and that has non-zero liquidity (and any factory-created v3 pool / v2 pair). Anyone can create such a pool for a token they minted, be its only liquidity provider, and move its price for free: the IMD swapped in lands in their own position. The settlement rule (adverse extreme over observations spanning an hour, MarginaliaPricer.settlePrice) assumes holding a pumped price for an hour costs something; on a venue with no other market there is no arbitrage, so holding costs nothing. MarginaliaHook._difficulty then prices the win with mcap = postPrice * IERC20(n.x).totalSupply(), both attacker-chosen, so the call lands in tier 3 with a 100x target: log2(100)*sqrt(30)*3 ~ 1.09M score points against ~20k for an honest, correct +10% call on the launch pool. weekScore and weekTotal are dominated by the attacker, every honest leaderboardShare collapses, and with ten wallets (LEADERBOARD_CAP_BPS = 10% per wallet) the entire week's leaderboardPool (50% of every stamp, fee, forfeit and treasury drip) is paid to the attacker. Cost per wallet: one stamp (0.1 IMD), the 1.25% LP fee on a ~1 IMD buy, gas; the deposit comes back because the call is RIGHT. The same self-controlled token also lets the author fake Traded class and position checks, since postBalance and the held test read that token.","line":206,"path":"src/MarginaliaRouter.sol","reproduction":"1) attacker deploys FAKE (supply 1e30 to self), initialises hookless v4 pool FAKE/IMD at 1:1 (fee 3000, spacing 60) and adds ~1 IMD + 1 FAKE of full-range liquidity. 2) router.checkpointVenue(p{x: FAKE, venue: UniV4 that pool}, key); wait 1 hour. 3) router.note(p{side Buy, targetBps 1_000_000, horizonDays 1}, key, 1 ether, 1, deadline) succeeds with postPrice 1e18. 4) at horizon end the attacker swaps 20 IMD into their own pool (price x441), observes three times 30 minutes apart (no other market exists, so nothing pulls the price back), settle(id) -> Status.Right, hook.weekScore(week, attacker) = 1,088,592. 5) honest bob's RIGHT +10% call on the MARG/IMD launch pool the same week: weekScore = 20,538; leaderboardShare(attacker) = the 10% cap, leaderboardShare(bob) = 1.85% of the pool. Expected: a venue whose only liquidity and whose token are the author's cannot out-earn a real call; actual: 53x, and Sybil'd the whole pool. Proof: test/scratch/FakeVenueLeaderboard.t.sol fails with 'self-owned venue farms the leaderboard: 1088592 > 205380'.","severity":"high","snippet":"            if (PoolId.unwrap(key.toId()) != v.ref) revert BadVenue();\n            if (address(key.hooks) != address(0) && address(key.hooks) != address(hook)) revert BadVenue();\n            if (manager.getLiquidity(PoolId.wrap(v.ref)) == 0) revert BadVenue();","title":"A self-owned canonical v4 venue on a self-minted token farms the leaderboard pool at zero cost"},{"citation":"resolved","description":"The brief's guarantee for v4 venues and the hub leg is that a pump 'must be held for the whole span and any honest observation pins the price'. The series is capped at 16 observations and each new one is refused for 20 blocks after the last, so a sequence of 16 observations at the earliest allowed block fills the series in exactly 15 x 20 x 12 s = 3600 s, which satisfies OBS_MIN_SPAN. An author who is first in each of those 16 blocks (a builder bundle, or simply front-running a public observe) does pump -> observe -> unwind inside one block each time; between blocks the price is honest, yet every honest observe reverts ObservationTooSoon, and after the sixteenth the window is closed with TooLate. settlePrice then sees only pumped readings. On the launch pool the sandwiches are expensive (1.25% + 1.25% + 3% of the pump each), on any thin or self-owned v4 venue they are not; either way the pinning property the design relies on does not exist. For adverse-extreme venues extra observations can only hurt the author, so capping their count and spacing them per-note (instead of per-block or per-observer) only serves the squatter.","line":492,"path":"src/MarginaliaHook.sol","reproduction":"Author posts BUY +10% on MARG via router.note. At horizon end, for each of 16 slots at blocks end, end+20, ..., end+300: swap 600,000 IMD into MARG (+12%), hook.observe(id), sell the MARG back, all in that block. An honest wallet calling hook.observe(id) later in the same block and in each of the next 19 blocks gets ObservationTooSoon every time (321 attempts refused, 0 accepted in the proof), and TooLate after the series is full. After SETTLE_WINDOW, settle(id) -> Status.Right although the price was +12% only inside the attacker's 16 blocks. Expected: at least one honest reading lands and settles the call Wrong. Proof: test/scratch/ObservationSquatting.t.sol.","severity":"medium","snippet":"        if (obs.length >= OBS_MAX) revert TooLate();\n        if (obs.length > 0 && block.number < obs[obs.length - 1].blockNumber + OBS_GAP_BLOCKS) {\n            revert ObservationTooSoon();\n        }","title":"OBS_MAX x OBS_GAP_BLOCKS lets one actor own every observation slot; an honest observer is refused in every block and never pins the price"},{"citation":"resolved","description":"MarginaliaHook.sellPotMarg accepts any amount up to potMarg, but only the judge may call it and the judge's only path passes the entire potMarg. The sale must return at least 97% of the router window's maximum MARG price for the whole amount (unlockCallback ACT_SELL: imdOut < extra -> InvalidUnlock), so the moment selling the full pot at once would move the launch pool more than ~3% the conversion reverts. potMarg only grows (every forfeit adds, only sellPotMarg subtracts) and pool liquidity can shrink, so the condition is absorbing: from then on no forfeited MARG ever reaches leaderboardPool, thesisPool or refundPool. A chunked sale (an amount parameter on convertForfeits, or the judge selling at most the pool's 3% depth per call) clears the floor trivially.","line":85,"path":"src/MarginaliaJudge.sol","reproduction":"Launch pool at 1 MARG = 1 IMD. Three posted-and-retracted calls leave potMarg = 1.48 MARG. LP liquidity in the pool is 40e18 (so 1.48 MARG moves the price well past 3%; equivalently any pot above ~1.5% of the pool's token depth). judge.convertForfeits() -> hook.sellPotMarg(1.48e18) -> InvalidUnlock, and it keeps reverting on every later call since potMarg never shrinks. Expected: at least a bounded chunk converts. Proof: test/scratch/WholePotConversionLock.t.sol (fails with InvalidUnlock on the current code).","severity":"medium","snippet":"        uint256 marg = hook.potMarg();\n        if (marg == 0) return 0;\n        imdOut = hook.sellPotMarg(marg);","title":"convertForfeits sells the whole pot in one swap under a 3% floor, so forfeits lock permanently once the pot exceeds the pool's depth"},{"citation":"resolved","description":"Every observation reads IERC20(n.x).balanceOf(n.author) with a plain call. If that read reverts during the settlement window nobody can observe, settle() finds fewer than OBS_MIN observations and returns VoidNoData, which keeps the score at zero and makes the deposit claimable. The author of a call on a token they control (or any token whose owner can make balanceOf revert, e.g. a blocklist/pause that guards view functions) therefore watches the outcome at the horizon: if RIGHT they let observers in and bank the score; if WRONG they switch the read off for six hours and get the deposit back with no penalty. The forfeit the pot should have received, the keeper reward and the negative score all disappear; the asymmetric payoff makes posting such calls strictly profitable in score. Treating a failed balance read as 'not held' (try/catch, balance = 0) or as a forfeit removes the option.","line":497,"path":"src/MarginaliaHook.sol","reproduction":"Token SW whose balanceOf reverts while a flag is set; hookless v4 pool SW/IMD with 1 IMD of liquidity; checkpoint, wait 1 hour, router.note(BUY 2x, 1 day). At horizon end the price is unchanged (the call is wrong); the author sets the flag. hook.observe(id) reverts 'paused' for every caller through the whole window. After SETTLE_WINDOW settle(id) -> Status.VoidNoData, weekScore unchanged, then claimDeposit(id,false) returns the deposit to the author. Expected: a wrong call whose position cannot be verified does not come back as a refundable void. Proof: test/scratch/RevertingBalanceFreeOption.t.sol.","severity":"medium","snippet":"        uint256 balance = IERC20(n.x).balanceOf(n.author);","title":"observe() has no fallback for a reverting balanceOf: a call on a self-controlled token is a free option (block observations -> VoidNoData -> deposit refunded, no score)"},{"citation":"resolved","description":"pendingDay is looked up by the Intake's requestId argument, while replay protection consumes a.requestId and nothing compares the two or compares a.questionHash with keccak256 of questionBody(day). Any attestation signed for this clone (the domain pins the consumer, not the question) can be delivered against any pending week. The judge's own retry path makes two signed answers for the same week possible (the first request's answer may still be produced after the retry) and two weeks may be pending at once. A week judged with another week's ranking has judgedSet = true forever; judgedOf filters the foreign ids out (noteWeek != day) and payJudged rolls the whole prize forward with no winners. This needs the Intake to misroute or an operator mistake, so it is a trust assumption on the Intake rather than an open attack, but the consumer could enforce it for free.","line":211,"path":"src/MarginaliaJudge.sol","reproduction":"Weeks 10 and 11 both requested (requestOf[10] = R10, requestOf[11] = R11). Intake calls onOracleResult(R10, A11, sig) where A11 is the valid signed answer whose a.requestId = R11 and whose ranking lists week-11 theses. Checks pass (signature in this clone's domain, quorum/panel ok, judgedSet[10] false), consumed[R11] = true, rawRanked[10] = week-11 ids, judgedSet[10] = true. Later onOracleResult(R11, A11, sig) reverts AlreadyConsumed and week 11 can only be re-requested after ANSWER_DEADLINE; payJudged(10) pays nobody and rolls thesisPool[10] into the current week. Expected: the attestation for R10 is the only one accepted for R10.","severity":"low","snippet":"        _verifyAttestation(a, signature);\n        if (a.agreed < a.quorum || a.quorum < QUORUM || a.panelSize < PANEL_SIZE || judgedSet[day]) {\n            revert BadAnswer();\n        }\n        bytes32[] memory ranked = decodeBytes32List(a);\n        _consume(a.requestId);","title":"onOracleResult never binds the attestation to the request it is delivered for (no questionHash and no a.requestId == requestId check)"},{"citation":"resolved","description":"weekClosed(epoch) returns true once an unanswered request is older than ANSWER_DEADLINE and the week is 28 days past, but pendingDay[requestId] is only deleted on a retry. If nobody retries, the first request stays deliverable: after sweep(2, epoch) moves thesisPool[epoch] into the current leaderboard pool, a late onOracleResult still succeeds (judgedSet = true) and payJudged pays shares of a zero pool while recording judgedWins. No funds are lost (they went to the leaderboard), but the ranked authors the oracle was paid to find get nothing and the week can never be judged again.","line":779,"path":"src/MarginaliaHook.sol","reproduction":"Week w: requestJudging(w) at T; no answer. At (w+1)*7d + 28d anyone calls sweep(2, w): weekClosed true -> thesisPool[w] -> leaderboardPool[current]. Then the Intake delivers the valid answer for requestOf[w]: pendingDay still set, judgedSet[w] = true. judge.payJudged(w) -> hook.payJudged(w, top) with pool = 0: three _unlock(ACT_PAY, to, 0) calls, JudgedPaid(w, [0,0,0]). Expected: either the sweep invalidates the pending request (delete pendingDay as the retry does) or weekClosed stays false while a request is deliverable.","severity":"low","snippet":"            if (!judge.weekClosed(epoch)) revert NotOpen();\n            amount = thesisPool[epoch];\n            thesisPool[epoch] = 0;","title":"sweep(2) can empty a thesis pool whose original Intake request is still deliverable, so a late ranking pays its winners zero"}],"hash":"bf95f95c262bbbad882e28cc2a7af3dcce7969e7091f4be672cc3fe0128d0db6","nodeId":"8c02e5ab-5520-4798-a860-5a4bdcf4d48c","outcome":"completed","summary":"The review is complete. `.imd-findings.json` holds six findings and a coverage row for all 32 listed entry points plus four checked invariants, with no row left unreached. No source file was changed; the four proof tests live under `test/scratch/` and each fails on the current code for the stated reason. The existing suite of 59 tests still passes.\n\n**Findings, most severe first**\n\n- **High. Self-owned venue farms the leaderboard.** Venue validation in the router accepts any hookless v4 pool with liquidity, so an author mints a token, seeds their own pool with about 1 IMD, posts a 100x BUY call, moves the price for free at the horizon and settles RIGHT. Difficulty uses the attacker's own total supply for the market-cap tier. The proof shows a score of 1,088,592 against 20,538 for an honest, correct +10% call on the launch pool. Ten wallets take the whole weekly leaderboard pool.\n- **Medium. Observation slot squatting.** Sixteen observations spaced twenty blocks apart fill the series in exactly one hour. An author who is first in each of those blocks does pump, observe, unwind in one block each; an honest observer trying in every block of the window was refused 321 of 321 times and the call settled RIGHT. The brief's claim that any honest observation pins the price does not hold.\n- **Medium. Forfeit conversion locks.** The judge always sells the entire forfeited pot in one swap under a 97% floor. Once the pot exceeds what the pool absorbs within 3%, conversion reverts forever because the pot only grows.\n- **Medium. Free option via a reverting balance read.** The observe path reads the X token's balance with no fallback. The author of a call on a token they control blocks reads during the window of a wrong call, gets VoidNoData, zero score and the deposit back.\n- **Low. Attestation not bound to the delivered request.** The judge checks the signature and quorum but never compares the attestation's request id or question hash with the pending request, so a misrouted answer judges a week with another week's ranking.\n- **Low. Sweep before a late answer.** A thesis pool can be swept while the original Intake request is still deliverable; the late ranking then pays its winners zero.\n\n**Verified as holding:** the hardcoded hub pool id recomputes correctly from the mainnet IMD address, the factory and WETH constants are the mainnet ones, delta accounting nets to zero on every swap branch, both unlock callbacks are hash-bound and manager-only, the v3 callback is pinned to the pending pool, implementations lock themselves and clones initialise once from their hook, and EIP-712 domains rebuild correctly on clones.\n\n**Not reached in depth:** the Intake's real callback gas behaviour against a live signer, and economic sizing of the squatting attack on specific mainnet venues beyond the launch pool.","treeHash":null,"usage":{"cachedInputTokens":2349398,"inputTokens":482,"model":"claude-fable-5-1","outputTokens":68936,"runtime":"claude","turns":33,"wallClockMs":983659}},{"artifacts":[],"attempt":2,"bundleHash":"ff54ba19f2846ac5b47d229575ed75d8946113b8db68c63abf5cc5cb499b8f03","device":"644eb561f6d70a85","findings":[{"description":"fromSqrt() computes p = sqrtP^2 / 2^96 * 1e18 / 2^96 and, when X is token0, returns p unchanged even when it rounds to 0 (any pool whose token0 is worth less than 1e-18 of its quote, i.e. tick below about -414486). The inverted orientation already reverts EmptyPool for the same condition, so the two orientations are inconsistent. The v2 branch of _spotInQuote has the same gap (mulDiv(r1, 1e18, r0) == 0 is returned). observe(), checkpoint(), postPrice() and settlePrice() all pass the zero through. The hook (MarginaliaHook._postNote / settle) stores postPrice = 0 and resolves a BUY call with `settlePrice * 10_000 >= postPrice * targetBps`, which is `x >= 0` and always true; _difficulty() still returns a positive score (log2(target) * sqrt(30/h), tier 1). Anyone can create the venue: deploy an ERC-20 with a large supply, open a hookless v4 pool against IMD (or WETH) at a very low tick with any dust liquidity (the router only requires getLiquidity > 0 and a canonical key), checkpoint it, wait an hour, and post BUY calls with huge targetBps and short horizons through the router. Every call settles RIGHT, returns its deposit and books positive score into the week's leaderboard pool (capped 10% per wallet, so sybil wallets take the whole pool) for 0.1 IMD of stamp per note. Expected: a reading that rounds to zero is refused (EmptyPool / Unsupported) in both orientations and on both legs, as the inverted orientation already is, so no note can ever be posted or settled at price 0. Actual: observe returns (0, 1e18), postPrice returns 0, settlePrice returns 0.","line":286,"path":"src/MarginaliaPricer.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {PoolManager} from \"v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"v4-core/src/interfaces/IPoolManager.sol\";\nimport {IHooks} from \"v4-core/src/interfaces/IHooks.sol\";\nimport {IUnlockCallback} from \"v4-core/src/interfaces/callback/IUnlockCallback.sol\";\nimport {PoolKey} from \"v4-core/src/types/PoolKey.sol\";\nimport {PoolId, PoolIdLibrary} from \"v4-core/src/types/PoolId.sol\";\nimport {Currency} from \"v4-core/src/types/Currency.sol\";\nimport {ModifyLiquidityParams} from \"v4-core/src/types/PoolOperation.sol\";\nimport {BalanceDelta} from \"v4-core/src/types/BalanceDelta.sol\";\nimport {TickMath} from \"v4-core/src/libraries/TickMath.sol\";\nimport {StateLibrary} from \"v4-core/src/libraries/StateLibrary.sol\";\nimport {MarginaliaPricer} from \"src/MarginaliaPricer.sol\";\nimport {MarginaliaTypes as T} from \"src/MarginaliaTypes.sol\";\n\ncontract BigSupplyToken is ERC20 {\n    constructor() ERC20(\"Dust\", \"DUST\") {\n        _mint(msg.sender, 1e40);\n    }\n}\n\n/// @dev A hookless, liquid Uniswap v4 pool whose token0 is worth less than 1e-18 of its quote: the price\n/// MarginaliaPricer reads for it is exactly zero, and it never refuses the reading. The hook then stores\n/// postPrice = 0 for a BUY call and settles it with `settlePrice * 10_000 >= 0 * targetBps`, which is\n/// always true. Anyone can create such a pool (a token with a large supply, any tiny liquidity) and farm\n/// leaderboard score with guaranteed-RIGHT calls at the cost of the 0.1 IMD stamp each.\ncontract ZeroPriceProofTest is Test, IUnlockCallback {\n    using PoolIdLibrary for PoolKey;\n    using StateLibrary for IPoolManager;\n\n    PoolManager private manager;\n    MarginaliaPricer private pricer;\n    address private dust;\n    address private imd;\n    PoolKey private key;\n    T.Venue private venue;\n    int24 private constant TICK = -500_000;\n\n    function setUp() public {\n        vm.chainId(1);\n        vm.warp(1_800_000_000);\n        vm.roll(20_000_000);\n        manager = new PoolManager(address(this));\n        pricer = new MarginaliaPricer();\n        address a = address(new BigSupplyToken());\n        address b = address(new BigSupplyToken());\n        (dust, imd) = a < b ? (a, b) : (b, a);\n        key = PoolKey(Currency.wrap(dust), Currency.wrap(imd), 3000, 60, IHooks(address(0)));\n        manager.initialize(key, TickMath.getSqrtPriceAtTick(TICK));\n        manager.unlock(abi.encode(ModifyLiquidityParams(-887_220, -400_020, 1e12, bytes32(0))));\n        assertGt(IPoolManager(address(manager)).getLiquidity(key.toId()), 0, \"the venue is liquid: the router accepts it as canonical\");\n        venue = T.Venue(T.VenueKind.UniV4, PoolId.unwrap(key.toId()), imd, true);\n    }\n\n    function unlockCallback(bytes calldata data) external returns (bytes memory) {\n        require(msg.sender == address(manager));\n        ModifyLiquidityParams memory p = abi.decode(data, (ModifyLiquidityParams));\n        (BalanceDelta d,) = manager.modifyLiquidity(key, p, \"\");\n        _settle(key.currency0, d.amount0());\n        _settle(key.currency1, d.amount1());\n        return \"\";\n    }\n\n    function _settle(Currency c, int128 d) private {\n        if (d < 0) {\n            manager.sync(c);\n            ERC20(Currency.unwrap(c)).transfer(address(manager), uint256(uint128(-d)));\n            manager.settle();\n        }\n    }\n\n    /// @dev Fails today: the baseline and the settlement price are both zero and nothing refused them.\n    /// Passes once the pricer refuses a reading that rounds to zero (as it already does for the inverted\n    /// orientation, with EmptyPool) anywhere along checkpoint / postPrice / settlePrice.\n    function testAPricedCallNeverGetsAZeroBaselineOrSettlement() public {\n        T.PriceWindow memory empty;\n        T.PriceWindow memory w;\n        try pricer.checkpoint(IPoolManager(address(manager)), venue, imd, empty) returns (T.PriceWindow memory r) {\n            w = r;\n        } catch {\n            return; // refused at the checkpoint: fixed\n        }\n        vm.warp(vm.getBlockTimestamp() + 1 hours);\n        vm.roll(vm.getBlockNumber() + 300);\n        uint256 post;\n        try pricer.postPrice(IPoolManager(address(manager)), venue, imd, true, w) returns (uint256 p) {\n            post = p;\n        } catch {\n            return; // refused at posting: fixed\n        }\n        assertGt(post, 0, \"BUY baseline is zero: settle * 10_000 >= 0 * targetBps holds for any settlement\");\n\n        T.Observation[] memory obs = new T.Observation[](3);\n        for (uint256 i; i < 3; ++i) {\n            (uint256 x, uint256 q) = pricer.observe(IPoolManager(address(manager)), venue, imd);\n            obs[i] = T.Observation(uint64(vm.getBlockTimestamp()), uint64(vm.getBlockNumber()), x, q, 1);\n            vm.warp(vm.getBlockTimestamp() + 30 minutes);\n            vm.roll(vm.getBlockNumber() + 150);\n        }\n        uint256 settled;\n        try pricer.settlePrice(venue, true, obs) returns (uint256 s) {\n            settled = s;\n        } catch {\n            return;\n        }\n        assertGt(settled, 0, \"settlement price is zero for a liquid pool\");\n    }\n}","reproduction":"Deploy PoolManager and MarginaliaPricer; two 18-decimal tokens with 1e40 supply, the lower address as token0 ('dust'), the other as IMD; initialize the hookless key (fee 3000, spacing 60) at TickMath.getSqrtPriceAtTick(-500000); add liquidity 1e12 over [-887220, -400020] so getLiquidity(id) > 0. Venue = (UniV4, id, imd, xIsToken0 = true). pricer.checkpoint(manager, venue, imd, empty) succeeds with xStart = xMin = xMax = 0; warp +1h, roll +300; pricer.postPrice(manager, venue, imd, true, window) returns 0 (expected: revert EmptyPool or a positive price); three pricer.observe() readings 30 minutes apart all return xRead = 0 and pricer.settlePrice(venue, true, obs) returns 0 (expected: revert). In the hook this is postPrice = 0 and outcome Right for any BUY targetBps. The proof below fails on the current code at the first assertGt and passes after adding `if (p == 0) revert EmptyPool();` before `if (xIsToken0) return p;` in fromSqrt (verified locally), or any equivalent refusal of zero readings along checkpoint/postPrice/settlePrice.","severity":"high","title":"MarginaliaPricer reads a liquid pool as price zero instead of refusing it; a zero baseline makes every BUY call settle RIGHT"},{"description":"The callback keys the week on the Intake's `requestId` argument but verifies and consumes `a.requestId` from the signed attestation, and never compares the two, nor `a.questionHash` with keccak256 of the body it sent. A correctly signed attestation for week B's request, delivered under week A's callback id, is stored as week A's ranking (its ids are then filtered out by judgedOf because noteMeta reports another week, so the thesis pool rolls forward instead of paying), and `_consume(a.requestId)` then makes the genuine delivery for week B revert AlreadyConsumed; week B can only be retried after the 3-day deadline at the cost of another 0.5 IMD draw. Only the Intake can call the function, so this needs a faulty or compromised Intake; the consumer base contract leaves this check to the consumer by design, and it costs one comparison.","line":196,"path":"src/MarginaliaJudge.sol","reproduction":"Clone and init a judge against a stub hook with eligible theses in weeks 98 and 99 (week 100 current). requestJudging(99) -> R1, requestJudging(98) -> R2. Build a valid attestation `a` with a.requestId = R2 and a bytes32[] answer of week 98's ids, signed by the oracle signer for this consumer. Call onOracleResult(R1, a, sig) from the Intake: expected revert (attestation not for R1); actual success, judgedSet[99] = true, consumed[R2] = true. Then onOracleResult(R2, a, sig): actual revert AlreadyConsumed(R2). The existing test/JudgeOracle.t.sol already delivers attestations whose requestId (keccak256('signed judge request')) differs from the callback id and they are accepted.","severity":"low","title":"MarginaliaJudge.onOracleResult does not bind the attestation to the request it is delivered for"},{"description":"Three edge behaviours that are unreachable in the deployed configuration but worth knowing: (1) Treasury.lastDripDay starts at 0, so on a chain whose timestamp is below 86400 the first drip reverts AlreadyDripped (irrelevant on mainnet). (2) MarginaliaPricer.sqrt(type(uint256).max) reverts with an arithmetic overflow in `(x + 1) / 2`; difficulty() only passes it values up to 3e9. (3) MarginaliaPricer.difficulty(0, false, h, mcap) and difficulty(t, buy, 0, mcap) panic with division by zero; the hook validates targetBps and horizonDays before calling it. None of these is asserted in the submitted tests.","line":42,"path":"src/MarginaliaTreasury.sol","reproduction":"vm.warp(1000); treasury.drip() -> AlreadyDripped. pricer.sqrt(type(uint256).max) -> panic 0x11. pricer.difficulty(0, false, 30, 0) -> panic 0x12; pricer.difficulty(20000, true, 0, 0) -> panic 0x12.","severity":"info","title":"MarginaliaTreasury.drip can never run on UTC day 0 and MarginaliaPricer helpers panic on inputs the hook never sends"}],"hash":"ce115551bba054a361ea3a3beac7718db0c2443e4ff37553a6621b38474eb997","nodeId":"4fd3ac49-e4be-4f9b-a90d-838d3ef3c15d","outcome":"completed","summary":"Everything is in place: the harness itself excludes the findings file and the scratch directory from git, so their absence from `git status` is expected. No blocking file was needed.\n\n## Outcome\n\n**The submitted suite passes.** `forge test --no-match-path \"test/fork/*\"` runs the 59 pre-existing tests plus 73 new ones, all green. The only failing test on the machine is the deliberately failing proof under test/scratch, which the harness deletes before building.\n\n**One high-severity defect reported, not tested around.** MarginaliaPricer returns a price of exactly zero for a liquid Uniswap v4 pool whose token0 is worth less than 1e-18 of its quote, instead of refusing the reading the way the inverted orientation already does. The hook stores that zero as the post price, and its BUY rule `settle * 10_000 >= 0 * targetBps` is then always true. Anyone can create such a pool with a large-supply token and dust liquidity, then farm leaderboard score with guaranteed-RIGHT calls at 0.1 IMD per note. The finding in `.imd-findings.json` carries a self-contained proof that fails on the current code and that I verified passes under a one-line refusal of zero readings in `fromSqrt` (patched locally, then restored; src is untouched).\n\nTwo further findings are recorded without proof: a low one, where the judge's oracle callback never checks that the signed attestation's request id matches the request it was delivered for, and an info entry covering three unreachable edge panics.\n\n## New test files (all under test/)\n\n- **TreasuryInvariant.t.sol**: a handler drives a treasury clone with random gifts, clock moves, drips from random callers, re-init attempts and ETH. Six invariants hold over 256 runs: balance equals gifts minus drips, the hook received exactly every drip, no drip exceeded 2%, one drip per day, hook binding pinned, no ETH.\n- **RouterInvariant.t.sol**: over the full hook fixture, three actors post noted buys, noted sells, theses, checkpoints and plain swaps while time advances and strangers hit the callbacks. Invariants: the router never retains IMD, MARG, claims or ETH; every note on the hook came through a successful router call; bindings pinned; the manager always backs the hook's claims.\n- **PricerProperties.t.sol**: fuzzed monotonicity and tier steps of the difficulty score, log2 and sqrt floor properties, price orientation inversion within the representable range, v4 settlement equal to the adverse extreme over random series, appended observations never helping a call, v3 settlement ignoring middle readings, v2 TWAP of a flat ratio, exact posting-window boundaries, and the refusal paths for empty series, bad ticks, unknown venues, off-mainnet ETH quotes and empty pools.\n- **CompanionFailures.t.sol**: failure paths for all three companions. Treasury: dust rounding, same-day and day-boundary repeats, ETH, an admin-selector sweep, bad init, a hook that cannot take funds. Judge: every init field, current-week and thesis-less requests, zero and over-cap prices, deadline-exact retries, duplicate intake ids, wrong signer, wrong consumer domain, expiry boundary, malformed answers, head filtering, pay-before-answer, convert on an empty pot, and the full weekClosed state table. Router: expired deadline, zero and oversized amounts, slippage refund, unapproved payer, venue kind None, foreign-hook and empty v4 venues, caller-supplied venue fields overridden, stray callbacks, traded-note subject mismatch, foreign or empty X legs, init without a manager, and the expired-window recovery sequence.\n\n**Still owed**: the fork test in test/fork needs an RPC and did not run here. The previous attempt's failure mode was not visible to me; the main trap I found and avoided is that the optimizer caches `block.timestamp` within a test frame across `vm.warp`, so all new tests read the clock through the cheatcode.","treeHash":"8c20ac4b35027dcbca430d52362cb46985430cf9","usage":{"cachedInputTokens":5859426,"inputTokens":1314,"model":"claude-fable-5-1","outputTokens":81840,"runtime":"claude","turns":42,"wallClockMs":1341982}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"52c98c0dc01791cd","findings":[{"citation":"resolved","description":"Settled: NOT fixed; the author disputes it as design. Re-run against the revised tree: the v4 branch of validateVenue (line 209) still admits any hookless pool with non-zero liquidity, with no depth, age or counterparty requirement, and nothing between posting and payment distinguishes a venue that only the author ever trades. The brief's own settlement guarantee ('a pump must be held for the whole span and any honest observation pins the price') is what fails here, not a venue preference: on a pool whose token nobody else holds there is no honest observation to pin anything and holding the pump costs nothing, because the IMD spent on it lands in the attacker's own position. MarginaliaHook._difficulty (line 690, mcap = postPrice x IERC20(n.x).totalSupply()) then takes both the price and the supply from the attacker, so the win scores log2(100) x sqrt(30) x 3 = 1,088,592 against ~20,538 for an honest right +10% call on the launch pool, and leaderboardShare pays the 10% cap; ten wallets take 100% of every week's leaderboard pool (50% of all stamps, fees, forfeits and treasury drips) for 1 IMD of stamps. The author's partial closures (empty v3 pools refused, zero prices refused, failed balanceOf is not a refundable void, 10% cap) do not touch this path: the proof needs a liquid v4 pool, a positive price and a working ERC-20. The author is right that no fix fits inside 'do not change the contracts' logic' and that a depth floor only raises the attacker's cost (the pumped IMD comes back when it removes liquidity); the decision is the requester's, but until the requester either accepts the exposure in the brief or a change bounds what a self-priced call can draw (for example: score only calls priced on the launch pool or the hub leg, cap the claimed multiple, or derive the mcap tier from something the author does not choose), the loss path stands as reproduced. SPEC.md section 10 still says price resolution only returns or forfeits the author's own bond, which stopped being true when the leaderboard started paying IMD for score.","line":209,"path":"src/MarginaliaRouter.sol","reproduction":"State: launch pool MARG/IMD at 1:1 with 10,000,000e18 liquidity on [-6000, 6000], hook bound. Attacker (2,000 IMD): deploy ERC-20 X (1e27 to self); manager.initialize(PoolKey(X/IMD, fee 3000, spacing 60, hooks 0), sqrtP 2^96); add 1e18 liquidity on [-887220, 887220] (~1 X and ~1 IMD). router.checkpointVenue(p, xKey) with p.x = X, p.venue = (UniV4, xKey.toId()), side Buy, targetBps 1_000_000, horizonDays 1; warp +1h, roll +300; router.note(p, xKey, 1 ether, 1, deadline) succeeds, noteOf(id).postPrice == 1e18. At horizonEnd: swap 11 IMD into the X pool (price ~144x; nobody else holds X so nothing sells it back); hook.observe(id) at end, end+10min/+50 blocks, end+70min/+300 blocks; warp end+6h+1; hook.settle(id). Then hook.fundPot(1000 ether) in the same week. Expected: a venue the author alone can price earns nothing from the pool. Actual (test/scratch/SelfVenueLeaderboard.t.sol, run on this tree): status Right, records(attacker).score = 1,088,592, leaderboardPool(week) = 500.05 IMD, leaderboardShare(week, attacker) = 50.005 IMD (the 10% cap), claimable with claimLeaderboard after the week; the 0.5 IMD deposit comes back because the call is RIGHT. The test fails with 'self-priced venue pays the capped leaderboard share for one 0.1 IMD stamp: 50005000000000000000 != 0'.","severity":"high","snippet":"            if (manager.getLiquidity(PoolId.wrap(v.ref)) == 0) revert BadVenue();","title":"Self-provisioned canonical v4 venue still farms the leaderboard pool: a wallet that is the only LP and trader of a hookless X/IMD pool settles a 100x call RIGHT at tier 3 and takes the capped 10% of t"},{"citation":"resolved","description":"Settled: the dust variant (1 wei) is fixed and testAStrangersDustTransferDoesNotVoidASellCall confirms it. The fix does not fully hold: _broken (lines 530-537) still declares a SELL call void on any balance growth above max(10% of postBalance, DEPOSIT x 1e18 / postPrice), and an ERC-20 balance can be raised by anyone. For an author who holds little or none of X at posting (a SELL call posted through router.note needs no X at all; postBalance for a note on MARG is only the ~0.4 MARG the 1 IMD swap delivers), the tolerance is the deposit's worth, so a gift of 0.5 IMD worth of X plus one wei voids the call. The author's defence is that the gift compensates the deposit, and in money it does (gift in 0.5, deposit out 0.494), but it does not compensate the score: the call books -difficulty instead of +difficulty, records.broken is incremented, and the settling keeper (who can be the gifter) collects 2% of the deposit. In the leaderboard economy score is money: for 0.5 IMD a competitor erases a rival's +20,538 (or a tier-3 call's +1,000,000) and replaces it with the negative, raising every other wallet's pro-rata share of the week's pool; BUY calls cannot be attacked this way, so SELL calls remain strictly worse to post. SPEC.md line 70 still describes the SELL hold rule as 'balance <= post-trade balance', which the code no longer implements either. A rule a stranger cannot trigger would compare against outflows only (a SELL call is broken by the author buying X back, which cannot be told from a gift by balanceOf), or drop the SELL hold rule and rely on price alone as the brief's settlement does; either is a design decision, but the guarantee claimed in round 2 ('a stranger's dust transfer cannot void it') is only true for dust.","line":536,"path":"src/MarginaliaHook.sol","reproduction":"State: repository fixture (launch pool at 1 MARG = 1 IMD, mature checkpoint); dave holds 100 IMD and no MARG. dave: router.note({x: MARG, venue: launch pool, side Sell, targetBps 9000, horizonDays 1}, key, 1 ether, 1, deadline): noteOf(id).postBalance = 0.395 MARG, postPrice = 1e18, tolerance = max(0.0395, 0.5) = 0.5 MARG. bob sells 1,500,000 MARG through a plain v4 router: margPriceInImd() < 0.8e18, the -10% call is right. carol: MARG.transfer(dave, 0.5e18 + 1). Three observations at end, end+30min/+150 blocks, end+61min/+155 blocks; warp end+6h+1; carol calls settle(id). Expected: status Right and a positive score (the identical sequence without carol's transfer settles Right with score +20,538: test/scratch/SellGiftResidual.t.sol testBaselineWithoutGiftSettlesRight). Actual (testAGiftWorthTheDepositVoidsACorrectSellCall): status VoidSold, deposit 0 (0.494 MARG forfeited to potMarg), records(dave).score = -20,538, broken = 1, carol receives 0.00987 MARG as keeper; dave's MARG balance is up 0.006 MARG net, his week score is down 41,076 points.","severity":"medium","snippet":"        return balance > n.postBalance + tolerance;","title":"Residual of ce3d30ae: a stranger still voids a correct SELL call by gifting its author X worth just over the deposit (0.5 IMD); the deposit is forfeited, the score flips negative and the keeper is pai"},{"citation":"resolved","description":"Introduced by the fix for 272fbe0d. With the seed z = x / 2 + 1, x == 2 gives z == 2 == y, so `while (z < y)` is false on entry and the function returns 2; floor(sqrt(2)) is 1. Every other input is rooted correctly (the accepted fuzz test excludes x == 2 for this reason). Reachability: difficulty() is the only in-tree caller and passes 30e8 / horizonDays with horizonDays in 1..90, so the smallest argument is 33,333,333 and no score changes; the defect is only visible through the public sqrt. Fix: return 1 for x in [1, 3] before the loop (or seed with z = x / 2 + 1 only when x >= 4), keeping the overflow-safe seed for the rest.","line":101,"path":"src/MarginaliaPricer.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {MarginaliaPricer} from \"src/MarginaliaPricer.sol\";\n\n/// @dev Proof for the finding \"sqrt(2) returns 2\": the reseeded Babylonian start `x / 2 + 1` equals x when\n/// x == 2, so the `while (z < y)` loop never runs and the function returns y == x == 2. The integer floor\n/// of sqrt(2) is 1. Every other input in [0, type(uint256).max] is rooted correctly.\ncontract SqrtOfTwoTest is Test {\n    MarginaliaPricer private pricer;\n\n    function setUp() public {\n        pricer = new MarginaliaPricer();\n    }\n\n    function testSqrtOfTwoIsOne() public view {\n        assertEq(pricer.sqrt(2), 1, \"sqrt(2) must floor to 1\");\n    }\n\n    function testSqrtIsTheIntegerFloorOnEverySmallInput() public view {\n        for (uint256 x = 0; x < 1024; ++x) {\n            uint256 y = pricer.sqrt(x);\n            assertLe(y * y, x, \"sqrt above the root\");\n            assertGt((y + 1) * (y + 1), x, \"sqrt below the floor\");\n        }\n    }\n}","reproduction":"Deploy MarginaliaPricer; pricer.sqrt(2). Expected: 1. Actual: 2 (and 2 x 2 = 4 > 2 violates the integer-floor property). The tester's proof test/scratch/Proof_953f5fe661de.t.sol fails on this tree with 'sqrt(2) must floor to 1: 2 != 1' and 'sqrt above the root: 4 > 2'; the exhaustive check of 0..1023 passes for every other input.","severity":"low","snippet":"        uint256 z = x / 2 + 1; // (x + 1) / 2 overflows at type(uint256).max","title":"MarginaliaPricer.sqrt(2) returns 2: the overflow-safe reseed from round 2 equals x at x == 2 so the Babylonian loop never runs (tester finding 953f5fe6, confirmed)"}],"hash":"e2f16292c703852be0a0687d9dc9a64974605d3fd501ae3c517bc265f82e2f59","nodeId":"d50b90ec-2bb8-4e57-b169-0042f10e9a18","outcome":"completed","summary":"The review is complete and written to `.imd-findings.json` (3 findings, 33 entry points answered plus 4 invariant rows, none unreached). Only that file and my scratch tests under `test/scratch/` changed; no source was touched.\n\n**Settled from round 2**\n\n- **Fixed and confirmed** (proofs or the author's regression tests run on this tree): stranded forfeit pot (tranche conversion, my proof passes), zero-price baseline (my proof passes), dust voiding a SELL call (the 1 wei case), observation-slot squatting (a more adverse reading replaces the slot), reverting `balanceOf` free option (bounded staticcall, sentinel = not held), VoidNoData free option (now scores negative), thesis cap (121st refused before payment), sweep versus late delivery (`abandonRequest`), attestation chain id check.\n- **Dropped**: the adverse-extreme round-trip finding, because the brief specifies that rule, and the hook-constructor floor finding, because it concerns the later hook launch, not this manifest.\n- **Still open (high, proof attached)**: the self-provisioned v4 venue. The author's dispute is that admission is design, and nothing in the revision touches the path. I rebuilt the proof: one wallet opens a hookless X/IMD pool it alone supplies, posts a 100x call, pumps its own pool, observes three times, settles Right with score 1,088,592 and takes the 10% cap of the week's leaderboard pool for a 0.1 IMD stamp. I recorded that resolving it is a requester decision, with concrete options, but the loss path reproduces.\n\n**New this round**\n\n- **Medium**: the SELL hold fix only stops dust. A stranger gifting X worth just over the deposit (0.5 IMD) still voids a correct SELL call: deposit forfeited, score flipped from +20,538 to -20,538, keeper paid, author's money roughly neutral. Reproduced on the fixture with and without the gift.\n- **Low, proof attached**: the sqrt reseed from round 2 makes `sqrt(2)` return 2. Unreachable through `difficulty`, confirmed with the tester's proof.\n\nOne caution on the high finding: it cannot be fixed without a logic change the brief forbids, so it will stay outstanding until the requester either accepts the exposure explicitly or allows a bound on what a self-priced call can draw.","treeHash":null,"usage":{"cachedInputTokens":2574974,"inputTokens":482,"model":"claude-fable-5-1","outputTokens":42354,"runtime":"claude","turns":31,"wallClockMs":1025529}}],"verification":[{"checks":[{"durationMs":85211,"exitCode":0,"name":"build","output":"Compiling 109 files with Solc 0.8.26\nSolc 0.8.26 finished in 84.98s\nCompiler run successful with warnings:\nWarning (8760): This declaration has the same name as another declaration.\n   --> src/MarginaliaHook.sol:383:9:\n    |\n383 |         uint32 week = _week();\n    |         ^^^^^^^^^^^\nNote: The other declaration is here:\n   --> src/MarginaliaHook.sol:706:5:\n    |\n706 |     function week() external view returns (uint32) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:771:9:\n    |\n771 |         uint256 pool = thesisPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:90:5:\n   |\n90 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:792:9:\n    |\n792 |         uint256 pool = leaderboardPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:90:5:\n   |\n90 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2018): Function state mutability can be restricted to pure\n   --> test/helpers/Fixture.sol:114:5:\n    |\n114 |     function priceOf(bytes32, address) external view returns (uint256) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (2018): Function state mutability can be restricted to pure\n  --> test/fork/MainnetLaunch.t.sol:78:5:\n   |\n78 |     function _mine(bytes memory hookCode) internal view returns (bytes32 salt) {\n   |     ^ (Relevant source part starts here and spans across multiple lines).\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/MarginaliaTreasury.sol:51:9\n   │\n51 │         emit Dripped(day, amount);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n   ╭▸ src/MarginaliaJudge.sol:96:17\n   │\n96 │             try hook.sellPotMarg(marg) returns (uint256 out) {\n   │                 ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[missing-events-access-control]: `jobHash` is changed without an event but is used for access control\n    ╭▸ src/MarginaliaRouter.sol:303:16\n    │\n303 │         delete jobHash;\n    │                ━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/MarginaliaTreasury.sol:43:22\n   │\n43 │         uint32 day = uint32(block.timestamp / 1 days);\n   │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint32' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/MarginaliaHook.sol:75:38\n   │\n75 │     bytes32 public constant ACTION = bytes32(\"oracle.request@oracle-1\");\n   │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes32' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/MarginaliaPricer.sol:85:13\n   │\n85 │             n += 1;\n   │             ━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n   ╭▸ src/MarginaliaJudge.sol:96:17\n   │\n96 │             try hook.sellPotMarg(marg) returns (uint256 out) {\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/MarginaliaPricer.sol:120:33\n    │\n120 │         if (w.startedAt == 0 || block.timestamp > uint256(w.startedAt) + POST_MAX_AGE) {\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:114:47\n    │\n114 │         for (uint256 i = 0; i < all.length && n < MAX_JUDGED; ++i) {\n    │                                               ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/MarginaliaHook.sol:193:44\n    │\n193 │     constructor(IPoolManager poolManager_, address token_, address factory_) {\n    │                                            ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaJudge.sol:115:35\n    │\n115 │             (,,, bool hasChild) = hook.noteMeta(all[i]);\n    │                                   ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:121:34\n    │\n121 │             return T.PriceWindow(uint64(block.timestamp), uint64(block.number), x, x, x, q, q);\n    │                                  ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:121:59\n    │\n121 │             return T.PriceWindow(uint64(block.timestamp), uint64(block.number), x, x, x, q, q);\n    │                                                           ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaJudge.sol:115:35\n    │\n115 │             (,,, bool hasChild) = hook.noteMeta(all[i]);\n    │                                   ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaPricer.sol:142:20\n    │\n142 │                 || block.timestamp < uint256(w.startedAt) + POST_MIN_SPAN\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/MarginaliaPricer.sol:143:20\n    │\n143 │                 || block.timestamp > uint256(w.startedAt) + POST_MAX_AGE\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:149:69\n    │\n149 │             x = twap(v.kind, v.xIsToken0, w.xStart, w.startedAt, x, uint64(block.timestamp));\n    │                                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:170:15\n    │\n170 │             ++n;\n    │               ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaJudge.sol:174:33\n    │\n174 │             out[i - 1] = bytes1(uint8(48 + v % 10));\n    │                                 ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:168:55\n    │\n168 │         else if (v.kind == T.VenueKind.UniV3) xRead = uint256(_v3Cumulative(ref));\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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaJudge.sol:186:52\n    │\n186 │         return eligibleTheses(week).length == 0 || block.timestamp >= (uint256(week) + 1) * 7 days + 28 days;\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/MarginaliaJudge.sol:194:32\n    │\n194 │         if (judgedSet[week] || block.timestamp < requestedAt[week] + ANSWER_DEADLINE) {\n    │                                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:213:28\n    │\n213 │             int256 delta = int256(c2) - int256(c1);\n    │                            ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:213:41\n    │\n213 │             int256 delta = int256(c2) - int256(c1);\n    │                                         ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:214:35\n    │\n214 │             int256 mean = delta / int256(dt);\n    │                                   ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:215:38\n    │\n215 │             if (delta < 0 && delta % int256(dt) != 0) mean -= 1; // round toward negative infinity, as v3 does\n    │                                      ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:217:57\n    │\n217 │             return fromSqrt(TickMath.getSqrtPriceAtTick(int24(mean)), xIsToken0);\n    │                                                         ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int24' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaPricer.sol:241:37\n    │\n241 │             (uint160 sqrtP,,,,,,) = IUniswapV3PoolOracle(ref).slot0();\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/MarginaliaPricer.sol:245:41\n    │\n245 │             (uint112 r0, uint112 r1,) = IUniswapV2PairOracle(ref).getReserves();\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/MarginaliaPricer.sol:269:33\n    │\n269 │         (int56[] memory cum,) = IUniswapV3PoolOracle(pool).observe(ago);\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:279:24\n    │\n279 │         uint32 nowTs = uint32(block.timestamp);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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 `requestOf` is updated\n    ╭▸ src/MarginaliaJudge.sol:214:9\n    │\n214 │         hook.drawForJudging(day, price, retry);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `requestOf` is updated\n    ╭▸ src/MarginaliaJudge.sol:217:21\n    │\n217 │           requestId = intake.request(\n    │ ┏━━━━━━━━━━━━━━━━━━━━━┛\n218 │ ┃             action, body, IIntake.Callback(address(this), this.onOracleResult.selector), imd, price\n219 │ ┃         );\n    │ ┗━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaJudge.sol:206:41\n    │\n206 │         if (judgedSet[day] || (retry && block.timestamp < requestedAt[day] + ANSWER_DEADLINE)) {\n    │                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaJudge.sol:225:9\n    │\n225 │         emit Requested(day, requestId, price);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaJudge.sol:223:28\n    │\n223 │         requestedAt[day] = uint64(block.timestamp);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaJudge.sol:255:9\n    │\n255 │ ┏         emit Judged(\n256 │ ┃             day,\n257 │ ┃             [\n258 │ ┃                 count > 0 ? ranked[0] : bytes32(0),\n    ‡ ┃\n262 │ ┃         );\n    │ ┗━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:276:17\n    │\n276 │             if (dup) continue;\n    │                 ━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:269:50\n    │\n269 │         for (uint256 i = 0; i < ranked.length && kept < 3; ++i) {\n    │                                                  ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaJudge.sol:270:77\n    │\n270 │             (address author, uint32 noteWeek, bool thesis, bool hasChild) = hook.noteMeta(ranked[i]);\n    │                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/MarginaliaJudge.sol:288:9\n    │\n288 │         hook.payJudged(day, top);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaRouter.sol:251:13\n    │\n251 │         if (block.timestamp > deadline) revert Expired();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:252:41\n    │\n252 │         if (amountIn == 0 || amountIn > uint256(uint128(type(int128).max))) revert InvalidSwap();\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/MarginaliaRouter.sol:252:49\n    │\n252 │         if (amountIn == 0 || amountIn > uint256(uint128(type(int128).max))) revert InvalidSwap();\n    │                                                 ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:338:9\n    │\n338 │         emit Noted(job.payer, job.sellMarg, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:320:18\n    │\n320 │                 -int256(job.amountIn),\n    │                  ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:328:25\n    │\n328 │         uint256 spent = uint256(uint128(-inputDelta));\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/MarginaliaRouter.sol:328:33\n    │\n328 │         uint256 spent = uint256(uint128(-inputDelta));\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:329:28\n    │\n329 │         uint256 received = uint256(uint128(outputDelta));\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/MarginaliaRouter.sol:329:36\n    │\n329 │         uint256 received = uint256(uint128(outputDelta));\n    │                                    ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:373:9\n    │\n373 │         emit XTraded(payer, X_V4, xIn, xOut, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:355:18\n    │\n355 │                 -int256(x.amountIn),\n    │                  ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:363:25\n    │\n363 │         uint256 spent = uint256(uint128(-inputDelta));\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/MarginaliaRouter.sol:363:33\n    │\n363 │         uint256 spent = uint256(uint128(-inputDelta));\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:364:20\n    │\n364 │         received = uint256(uint128(outputDelta));\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/MarginaliaRouter.sol:364:28\n    │\n364 │         received = uint256(uint128(outputDelta));\n    │                            ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:403:9\n    │\n403 │         emit XTraded(payer, X_V3, xIn, xOut, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:394:13\n    │\n394 │             int256(x.amountIn),\n    │             ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:399:25\n    │\n399 │         uint256 spent = uint256(zeroForOne ? a0 : a1);\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/MarginaliaRouter.sol:409:78\n    │\n409 │         if (amount0Delta > 0) IERC20(pool.token0()).safeTransfer(msg.sender, uint256(amount0Delta));\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/MarginaliaRouter.sol:410:78\n    │\n410 │         if (amount1Delta > 0) IERC20(pool.token1()).safeTransfer(msg.sender, uint256(amount1Delta));\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:438:9\n    │\n438 │         emit XTraded(payer, X_V2, xIn, xOut, actualIn, received);\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/MarginaliaRouter.sol:426:37\n    │\n426 │         (uint112 r0, uint112 r1,) = pair.getReserves();\n    │                                     ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:295:21\n    │\n295 │                 if (uint256(-params.amountSpecified) <= STAMP * 2) revert NoteTooSmall();\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/MarginaliaHook.sol:303:17\n    │\n303 │             if (uint256(-params.amountSpecified) <= depositMarg * 2) revert NoteTooSmall();\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/MarginaliaHook.sol:309:30\n    │\n309 │             specifiedTake = (uint256(params.amountSpecified) * bps + (10_000 - bps) - 1) / (10_000 - bps);\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:389:9\n    │\n389 │         emit Accrued(day, 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/MarginaliaHook.sol:463:9\n    │\n463 │ ┏         emit NotePosted(\n464 │ ┃             id,\n465 │ ┃             author,\n466 │ ┃             p.x,\n    ‡ ┃\n475 │ ┃             p.text\n476 │ ┃         );\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/MarginaliaHook.sol:341:13\n    │\n341 │             emit SwapFee(true, author, poolImd, 0, STAMP);\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/MarginaliaHook.sol:357:13\n    │\n357 │             emit SwapFee(false, author, poolImd, fee - STAMP, STAMP);\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/MarginaliaHook.sol:376:9\n    │\n376 │         emit SwapFee(false, tx.origin, poolImd, quietFee, 0);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:326:33\n    │\n326 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\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/MarginaliaHook.sol:326:41\n    │\n326 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\n    │                                         ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:326:63\n    │\n326 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\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/MarginaliaHook.sol:326:71\n    │\n326 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\n    │                                                                       ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:331:29\n    │\n331 │             uint256 netIn = uint256(-params.amountSpecified) - STAMP;\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/MarginaliaHook.sol:333:31\n    │\n333 │             uint256 margOut = uint256(uint128(margDelta));\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/MarginaliaHook.sol:333:39\n    │\n333 │             uint256 margOut = uint256(uint128(margDelta));\n    │                                       ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:366:25\n    │\n366 │             quietFee = (uint256(params.amountSpecified) * bps + (10_000 - bps) - 1) / (10_000 - bps);\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/MarginaliaHook.sol:367:28\n    │\n367 │             if (poolImd != uint256(params.amountSpecified) + quietFee) revert PartialFill();\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:449:17\n    │\n449 │             if (weekTheses[_week()].length >= MAX_WEEK_THESES) revert InvalidNote();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:441:22\n    │\n441 │         n.postedAt = uint64(block.timestamp);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe 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/MarginaliaHook.sol:497:13\n    │\n497 │         if (block.timestamp < end) revert TooEarly();\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/MarginaliaHook.sol:498:13\n    │\n498 │         if (block.timestamp > end + SETTLE_WINDOW) revert TooLate();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:511:9\n    │\n511 │         emit Observed(id, uint64(block.timestamp), xRead, quoteRead, balance);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:503:27\n    │\n503 │             T.Observation(uint64(block.timestamp), uint64(block.number), xRead, quoteRead, balance);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:503:52\n    │\n503 │             T.Observation(uint64(block.timestamp), uint64(block.number), xRead, quoteRead, balance);\n    │                                                    ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:511:27\n    │\n511 │         emit Observed(id, uint64(block.timestamp), xRead, quoteRead, balance);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[return-bomb]: external call with a gas limit may copy unbounded return data\n    ╭▸ src/MarginaliaHook.sol:519:13\n    │\n519 │             x.staticcall{gas: BALANCE_READ_GAS}(abi.encodeWithSelector(IERC20.balanceOf.selector, who));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/return-bomb\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaHook.sol:606:35\n    │\n606 │         emit Settled(id, outcome, settlePrice, scoreDelta, msg.sender);\n    │                                   ━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:556:13\n    │\n556 │         if (block.timestamp <= end + SETTLE_WINDOW) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:676:13\n    │\n676 │             emit ThesisReleased(n.parentId);\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/MarginaliaHook.sol:606:9\n    │\n606 │         emit Settled(id, outcome, settlePrice, scoreDelta, msg.sender);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:588:26\n    │\n588 │             scoreDelta = int256(_difficulty(n));\n    │                          ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:593:27\n    │\n593 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:595:27\n    │\n595 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:599:27\n    │\n599 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:614:13\n    │\n614 │         if (block.timestamp >= horizonEnd(id)) revert TooLate();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:623:9\n    │\n623 │         emit Retracted(id, text);\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/MarginaliaHook.sol:624:9\n    │\n624 │         emit Settled(id, T.Status.Retracted, 0, scoreDelta, address(0));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:616:30\n    │\n616 │         int256 scoreDelta = -int256(_difficulty(n) / 2);\n    │                              ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/MarginaliaHook.sol:632:13\n    │\n632 │         if (block.timestamp <= uint256(n.postedAt) + THESIS_GRACE) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:635:9\n    │\n635 │         emit ThesisForfeited(id);\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/MarginaliaHook.sol:653:9\n    │\n653 │         emit DepositClaimed(id, n.author, asImd, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:695:16\n    │\n695 │         return uint32(block.timestamp / 1 days);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:699:16\n    │\n699 │         return uint32(block.timestamp / 7 days);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:720:38\n    │\n720 │         uint256 prevPos = prev > 0 ? uint256(prev) : 0;\n    │                                      ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:721:38\n    │\n721 │         uint256 nextPos = next > 0 ? uint256(next) : 0;\n    │                                      ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:731:9\n    │\n731 │         emit PotFunded(_today(), amount, msg.sender);\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/MarginaliaHook.sol:743:9\n    │\n743 │         emit PotMargSold(amount, imdOut, _today());\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:763:27\n    │\n763 │         return (n.author, uint32(uint256(n.postedAt) / 7 days), n.targetBps == 0, n.children > 0);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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 `thesisPool` is updated\n    ╭▸ src/MarginaliaHook.sol:862:28\n    │\n862 │         bytes memory out = poolManager.unlock(data);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaHook.sol:862:28\n    │\n862 │         bytes memory out = poolManager.unlock(data);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:785:9\n    │\n785 │         emit JudgedPaid(w, paidAmounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/MarginaliaHook.sol:863:39\n    │\n863 │         if (unlockHash != bytes32(0)) revert InvalidUnlock();\n    │                                       ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:793:47\n    │\n793 │         uint256 share = FullMath.mulDiv(pool, uint256(s), weekTotal[w]);\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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:799:13\n    │\n799 │         if (w >= _week()) revert TooEarly();\n    │             ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:806:9\n    │\n806 │         emit LeaderboardClaimed(w, msg.sender, amount);\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/MarginaliaHook.sol:813:13\n    │\n813 │         if (n.day >= _today()) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:823:9\n    │\n823 │         emit RefundClaimed(id, msg.sender, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:821:30\n    │\n821 │         notesPerDay[n.day] = uint32(count - 1);\n    │                              ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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/MarginaliaHook.sol:832:17\n    │\n832 │             if (block.timestamp < (uint256(epoch) + 1) * 1 days + SWEEP_AFTER) revert TooEarly();\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/MarginaliaHook.sol:836:17\n    │\n836 │             if (block.timestamp < (uint256(epoch) + 1) * 7 days + SWEEP_AFTER) revert TooEarly();\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/MarginaliaHook.sol:840:17\n    │\n840 │             if (block.timestamp < (uint256(epoch) + 1) * 7 days + SWEEP_AFTER) revert TooEarly();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:873:40\n    │\n873 │             address currency = address(uint160(extra));\n    │                                        ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint160' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaHook.sol:882:13\n    │\n882 │             poolManager.settle();\n    │             ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:892:22\n    │\n892 │                     -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/MarginaliaHook.sol:901:17\n    │\n901 │             if (uint256(uint128(-margDelta)) != amount) revert InvalidUnlock();\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/MarginaliaHook.sol:901:25\n    │\n901 │             if (uint256(uint128(-margDelta)) != amount) revert InvalidUnlock();\n    │                         ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:903:30\n    │\n903 │             uint256 imdOut = uint256(uint128(imdDelta));\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/MarginaliaHook.sol:903:38\n    │\n903 │             uint256 imdOut = uint256(uint128(imdDelta));\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[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n   ╭▸ test/AuditFindings.t.sol:19:30\n   │\n19 │         uint256 startBlock = block.number;\n   │                              ━━━━━━━━━━━━\n   ‡\n23 │             vm.roll(startBlock + 25 * (i + 1));\n   │             ────────────────────────────────── `vm.roll` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockNumber()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/AuditFindings.t.sol:20:27\n   │\n20 │         uint256 startTs = block.timestamp;\n   │                           ━━━━━━━━━━━━━━━\n   ‡\n24 │             vm.warp(startTs + 31 minutes * (i + 1));\n   │             ─────────────────────────────────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/AuditFindings.t.sol:18:9\n    │\n 18 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/AuditFindings.t.sol:65:9\n    │\n 65 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/AuditFindings.t.sol:65:17\n   │\n65 │         vm.warp(block.timestamp + 7 days);\n   │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:130:9\n    │\n130 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:131:30\n    │\n131 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n135 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:132:27\n    │\n132 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n136 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:158:9\n    │\n158 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:159:30\n    │\n159 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n163 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:160:27\n    │\n160 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n164 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:182:9\n    │\n182 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:183:30\n    │\n183 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n187 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:184:27\n    │\n184 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n188 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:278:9\n    │\n278 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:278:17\n    │\n278 │         vm.warp(block.timestamp + 7 days);\n    │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:328:9\n    │\n328 │         vm.warp(hook.horizonEnd(a));\n    │         ─────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:329:30\n    │\n329 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n334 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:330:27\n    │\n330 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n335 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:408:9\n    │\n408 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:408:17\n    │\n408 │         vm.warp(block.timestamp + 7 days);\n    │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:475:9\n    │\n475 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:476:30\n    │\n476 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n479 │         vm.roll(startBlock + 25);\n    │         ──────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:477:27\n    │\n477 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n480 │         vm.warp(startTs + 30 minutes);\n    │         ───────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:499:9\n    │\n499 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:500:30\n    │\n500 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n504 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:501:27\n    │\n501 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n505 │             vm.warp(startTs + 10 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/RevisionFindings.t.sol:199:17\n    │\n199 │         vm.warp(block.timestamp + 1 hours);\n    │         ────────━━━━━━━━━━━━━━━─────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/RevisionFindings.t.sol:262:9\n    │\n262 │         vm.warp((uint256(w) + 1) * 7 days + 1);\n    │         ────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/Round3Findings.t.sol:67:17\n   │\n67 │         vm.warp(block.timestamp + 1 hours);\n   │         ────────━━━━━━━━━━━━━━━─────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\n","passed":true},{"durationMs":231,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 7 tests for test/Pricer.t.sol:PricerTest\n[PASS] testQuoteLegIsAdverseEvenUnderAV3Twap() (gas: 28455)\n[PASS] testTwapRefusesZeroSpanAndV4() (gas: 17708)\n[PASS] testV2TwapFromWrappingCumulative() (gas: 9503)\n[PASS] testV3TwapOfAConstantTickIsThatTick() (gas: 15459)\n[PASS] testV3TwapRoundsNegativeMeansDown() (gas: 14848)\n[PASS] testV3TwapWeightsByTime() (gas: 14715)\n[PASS] testV4SettlesOnTheAdverseExtreme() (gas: 26636)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 578.02µs (626.15µs CPU time)\n\nRan 1 test for test/fork/MainnetLaunch.t.sol:MainnetLaunchTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 568.56µs (0.00ns CPU time)\n\nRan 7 tests for test/JudgeOracle.t.sol:JudgeOracleTest\n[PASS] testEmptySignedRankingIsAnExecutableNoWinnerResult() (gas: 248153)\n[PASS] testFiveIdsWithEoaSignatureFitStipend() (gas: 554052)\n[PASS] testFullRankingWithEoaSignatureFitsStipend() (gas: 633672)\n[PASS] testProtocolDigestSignatureAndSelectorConformanceOnClone() (gas: 3322442)\n[PASS] testRejectedAnswersDoNotConsumeThePendingRequest() (gas: 892875)\n[PASS] testRequestedHeadIsFilteredAndDeduplicatedWithoutPromotingTheTail() (gas: 250679)\n[PASS] testTimeoutRetryInvalidatesOldIntakeRequest() (gas: 523953)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 6.00ms (27.94ms CPU time)\n\nRan 8 tests for test/PriceHistory.t.sol:PriceHistoryTest\n[PASS] testBaselineRequiresMatureFreshHistory() (gas: 188472)\n[PASS] testEmptyVenueAndHubCannotBeCheckpointedObservedOrPriced() (gas: 284549)\n[PASS] testFuzzV4BaselineIsNeverFavourableToTheCall(int24,bool) (runs: 256, μ: 106081, ~: 106158)\nLogs:\n  Bound result 64359\n\n[PASS] testHubBaselineUsesOppositeExtremeFromSettlement() (gas: 180334)\n[PASS] testLiveCheckpointCannotEraseHonestExtremesOrRestartTheClock() (gas: 224282)\n[PASS] testV2BaselineIgnoresSameBlockReservesDumpAndPumpBothOrientations() (gas: 467543)\n[PASS] testV3BaselineIgnoresSameBlockTickChangesBothOrientations() (gas: 418025)\n[PASS] testV3BaselineWeightsElapsedTime() (gas: 371037)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 9.86ms (11.03ms CPU time)\n\nRan 3 tests for test/Implementations.t.sol:ImplementationsTest\n[PASS] testClonesInitializeOnceOnlyFromTheirHook() (gas: 4551335)\n[PASS] testFactoryDeploysAllFourWithoutArgumentsOrExternalDependencies() (gas: 34608585)\nLogs:\n  four implementation CREATE2 deployments (gas): 8829579\n\n[PASS] testImplementationsRejectInitialization() (gas: 81376)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 41.36ms (42.26ms CPU time)\n\nRan 8 tests for test/AuditFindings.t.sol:AuditFindingsTest\n[PASS] testConversionAfterARealPriceFallNeedsAFreshMatureWindow() (gas: 2244515)\n[PASS] testEmptyV4ObservationIsRefused() (gas: 1028673)\n[PASS] testExpiredBaselineRejectsPostWithoutTakingFunds() (gas: 643517)\n[PASS] testForfeitureConversionRejectsSameBlockDump() (gas: 2224133)\n[PASS] testLongRankingFitsIntakeStipend() (gas: 2192588)\n[PASS] testSameBlockDumpPostUnwindDoesNotWinBuy() (gas: 1916921)\n[PASS] testSameBlockPumpPostUnwindDoesNotWinSell() (gas: 1785783)\n[PASS] testUnpayableRankingRollsTheWholePoolForward() (gas: 2465804)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 71.68ms (9.89ms CPU time)\n\nRan 26 tests for test/Lifecycle.t.sol:LifecycleTest\n[PASS] testAttestedClassCannotBeSelfDeclared() (gas: 343124)\n[PASS] testCallbackSelectorPinned() (gas: 3361)\n[PASS] testFakeVenueIsRefused() (gas: 382714)\n[PASS] testFlagsAndBinding() (gas: 55923)\n[PASS] testForfeitsConvertToImdForThePot() (gas: 1118696)\n[PASS] testLeaderboardProRataWithCap() (gas: 3247485)\n[PASS] testNoDataRefunds() (gas: 999702)\n[PASS] testNoteTooSmall() (gas: 173034)\n[PASS] testNotedBuyTakesStampAndDeposit() (gas: 798269)\n[PASS] testNotedSellPaysOnePercentPlusStamp() (gas: 1107534)\n[PASS] testObservationsMustSpanAnHour() (gas: 1494821)\n[PASS] testPlainBuyTakesNothing() (gas: 230288)\n[PASS] testQuietSellPaysThreePercent() (gas: 336561)\n[PASS] testQuietThesisPoolSweeps() (gas: 305757)\n[PASS] testRetract() (gas: 951734)\n[PASS] testRightCallReturnsDepositAsImd() (gas: 1804313)\n[PASS] testSellingEarlyBreaksTheCall() (gas: 1772740)\n[PASS] testThesisParentChild() (gas: 1515324)\n[PASS] testThesisWithoutChildForfeits() (gas: 796971)\n[PASS] testTreasuryDrip() (gas: 348158)\n[PASS] testTwoBlockPumpObserveUnwindSettlesWrong() (gas: 1804300)\n[PASS] testUnansweredWeekCanBeRetried() (gas: 2441273)\n[PASS] testUpOnlyIsRefused() (gas: 340732)\n[PASS] testWeeklyThesisJudging() (gas: 3855108)\n[PASS] testWriterRefundCappedAtStamp() (gas: 1717001)\n[PASS] testWrongCallForfeitsWithKeeperReward() (gas: 1562166)\nSuite result: ok. 26 passed; 0 failed; 0 skipped; finished in 76.88ms (23.03ms CPU time)\n\nRan 10 tests for test/Round3Findings.t.sol:Round3FindingsTest\n[PASS] testABuyCallStillBreaksWhenTheAuthorSells() (gas: 1764134)\n[PASS] testAGiftOfAnySizeDoesNotVoidACorrectSellCall() (gas: 1710155)\n[PASS] testAGiftWorthTheDepositDoesNotVoidACorrectSellCall() (gas: 1810035)\n[PASS] testALaunchPoolCallStillScoresAndPaysTheLeaderboard() (gas: 1570750)\n[PASS] testASelfPricedVenueDrawsNothingFromTheLeaderboard() (gas: 2972803)\n[PASS] testAWrongCallOnAnotherVenueStillForfeitsButBooksNoScore() (gas: 2760625)\n[PASS] testAWrongSellCallStillForfeits() (gas: 1495739)\n[PASS] testFuzzSqrtIsTheIntegerFloor(uint256) (runs: 256, μ: 22855, ~: 21056)\n[PASS] testRetractingACallOnAnotherVenueBooksNoScore() (gas: 2004799)\n[PASS] testSqrtFloorsSmallInputs() (gas: 9204519)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 79.80ms (29.67ms CPU time)\n\nRan 2 tests for test/PotTranche.t.sol:PotTrancheTest\n[PASS] testForfeitedPotCanStillBeConvertedOnceItOutgrowsOneSale() (gas: 49910278)\nLogs:\n  potMarg: 36877975912613201326\n  imdOut: 10344028156678390861\n\n[PASS] testWhenNoTrancheSellsTheHookReasonSurfaces() (gas: 1266289)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 119.12ms (29.31ms CPU time)\n\nRan 10 tests for test/RevisionFindings.t.sol:RevisionFindingsTest\n[PASS] testABuyBackNoLongerVoidsASellCallItSettlesOnPrice() (gas: 1751715)\n[PASS] testADustPricedV4VenueCannotBePostedOn() (gas: 1635894)\n[PASS] testARevertingBalanceOfVoidsTheCallAsSoldNotAsNoData() (gas: 2639306)\n[PASS] testAStrangersDustTransferDoesNotVoidASellCall() (gas: 1695773)\n[PASS] testAnAttestationAboutAnotherChainIsRefused() (gas: 2324761)\n[PASS] testAnEmptyCanonicalV3PoolIsRefusedAsAVenue() (gas: 567946)\n[PASS] testHonestObserverOverwritesAPumpObserveUnwindInTheNextBlock() (gas: 3785409)\n[PASS] testPricerRefusesAPriceThatRoundsToZeroInBothOrientations() (gas: 58712)\n[PASS] testSweepNeedsTheStaleRequestAbandonedAndALateAnswerIsThenRefused() (gas: 2449618)\n[PASS] testTheHundredAndTwentyFirstThesisOfAWeekIsRefusedBeforePayment() (gas: 55395690)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 120.89ms (42.09ms CPU time)\n\nRan 10 test suites in 121.81ms (526.74ms CPU time): 81 tests passed, 0 failed, 1 skipped (82 total tests)\n","passed":true},{"durationMs":91,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"Marginalia.approve(address,uint256)\",\"Marginalia.transfer(address,uint256)\",\"Marginalia.transferFrom(address,address,uint256)\",\"MarginaliaHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"MarginaliaHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"MarginaliaHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"MarginaliaHook.claimDeposit(bytes32,bool)\",\"MarginaliaHook.claimLeaderboard(uint32)\",\"MarginaliaHook.claimRefund(bytes32)\",\"MarginaliaHook.drawForJudging(uint32,uint256,bool)\",\"MarginaliaHook.fundPot(uint256)\",\"MarginaliaHook.observe(bytes32)\",\"MarginaliaHook.payJudged(uint32,bytes32[3])\",\"MarginaliaHook.retract(bytes32,string)\",\"MarginaliaHook.sellPotMarg(uint256)\",\"MarginaliaHook.settle(bytes32)\",\"MarginaliaHook.settleThesis(bytes32)\",\"MarginaliaHook.sweep(uint8,uint32)\",\"MarginaliaHook.unlockCallback(bytes)\",\"MarginaliaJudge.abandonRequest(uint32)\",\"MarginaliaJudge.convertForfeits()\",\"MarginaliaJudge.init(address,address,bytes32,address)\",\"MarginaliaJudge.onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"MarginaliaJudge.payJudged(uint32)\",\"MarginaliaJudge.requestJudging(uint32)\",\"MarginaliaRouter.checkpointVenue((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address))\",\"MarginaliaRouter.init(address,address)\",\"MarginaliaRouter.note((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address),uint256,uint256,uint256)\",\"MarginaliaRouter.sellWithNote((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address),uint256,uint256,uint256)\",\"MarginaliaRouter.uniswapV3SwapCallback(int256,int256,bytes)\",\"MarginaliaRouter.unlockCallback(bytes)\",\"MarginaliaTreasury.drip()\",\"MarginaliaTreasury.init(address)\"],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":215,\"README.md\":154,\"SPEC.md\":264,\"dependencies.json\":28,\"foundry.toml\":21,\"helper/.gitignore\":3,\"helper/package-lock.json\":737,\"helper/package.json\":20,\"helper/public/index.html\":82,\"helper/server.js\":90,\"helper/src/app.js\":203,\"jobs/launch-1-hook.json\":43,\"jobs/launch-2-contracts.json\":38,\"jobs/launch-A-implementations.json\":47,\"jobs/launch-A2-implementations.json\":41,\"jobs/launch-hook-v3.json\":43,\"launch.json\":22,\"remappings.txt\":4,\"src/HookFlags.sol\":33,\"src/Marginalia.sol\":12,\"src/MarginaliaHook.sol\":925,\"src/MarginaliaImpls.sol\":14,\"src/MarginaliaJudge.sol\":290,\"src/MarginaliaPricer.sol\":305,\"src/MarginaliaRouter.sol\":446,\"src/MarginaliaTreasury.sol\":53,\"src/MarginaliaTypes.sol\":108,\"src/OracleAttestation.sol\":221,\"src/interfaces/IIntake.sol\":15,\"src/interfaces/ILaunchFactory.sol\":49,\"test/AuditFindings.t.sol\":178,\"test/Implementations.t.sol\":96,\"test/JudgeOracle.t.sol\":270,\"test/Lifecycle.t.sol\":511,\"test/PotTranche.t.sol\":189,\"test/PriceHistory.t.sol\":233,\"test/Pricer.t.sol\":88,\"test/RevisionFindings.t.sol\":318,\"test/Round3Findings.t.sol\":214,\"test/fork/MainnetLaunch.t.sol\":382,\"test/helpers/Fixture.sol\":278,\"test/mocks/MockERC20.sol\":13},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"08aac4fdf369cf01b9e264b4f60163bc2cd788ef0f5dbc8ff56e5ba6502d4d1d","verifiedTreeHash":"7c2589728dc41752a66356c904f177a1e893eea2","verifierVersion":"0.1.0+4ba55555"},{"checks":[{"durationMs":58292,"exitCode":0,"name":"build","output":"Compiling 106 files with Solc 0.8.26\nSolc 0.8.26 finished in 58.06s\nCompiler run successful with warnings:\nWarning (8760): This declaration has the same name as another declaration.\n   --> src/MarginaliaHook.sol:379:9:\n    |\n379 |         uint32 week = _week();\n    |         ^^^^^^^^^^^\nNote: The other declaration is here:\n   --> src/MarginaliaHook.sol:644:5:\n    |\n644 |     function week() external view returns (uint32) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:709:9:\n    |\n709 |         uint256 pool = thesisPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:86:5:\n   |\n86 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:730:9:\n    |\n730 |         uint256 pool = leaderboardPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:86:5:\n   |\n86 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2018): Function state mutability can be restricted to pure\n   --> test/helpers/Fixture.sol:114:5:\n    |\n114 |     function priceOf(bytes32, address) external view returns (uint256) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (2018): Function state mutability can be restricted to pure\n  --> test/fork/MainnetLaunch.t.sol:78:5:\n   |\n78 |     function _mine(bytes memory hookCode) internal view returns (bytes32 salt) {\n   |     ^ (Relevant source part starts here and spans across multiple lines).\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/MarginaliaTreasury.sol:51:9\n   │\n51 │         emit Dripped(day, amount);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/MarginaliaTreasury.sol:43:22\n   │\n43 │         uint32 day = uint32(block.timestamp / 1 days);\n   │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint32' is safe 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]: `jobHash` is changed without an event but is used for access control\n    ╭▸ src/MarginaliaRouter.sol:301:16\n    │\n301 │         delete jobHash;\n    │                ━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n   ╭▸ src/MarginaliaJudge.sol:87:18\n   │\n87 │         imdOut = hook.sellPotMarg(marg);\n   │                  ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/MarginaliaJudge.sol:96:47\n   │\n96 │         for (uint256 i = 0; i < all.length && n < MAX_JUDGED; ++i) {\n   │                                               ━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n   ╭▸ src/MarginaliaJudge.sol:97:35\n   │\n97 │             (,,, bool hasChild) = hook.noteMeta(all[i]);\n   │                                   ━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[unused-return]: return value of an external call is not used\n   ╭▸ src/MarginaliaJudge.sol:97:35\n   │\n97 │             (,,, bool hasChild) = hook.noteMeta(all[i]);\n   │                                   ━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:152:15\n    │\n152 │             ++n;\n    │               ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaJudge.sol:156:33\n    │\n156 │             out[i - 1] = bytes1(uint8(48 + v % 10));\n    │                                 ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaJudge.sol:166:46\n    │\n166 │         if (requestOf[week] != bytes32(0) && block.timestamp < requestedAt[week] + ANSWER_DEADLINE) {\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/MarginaliaJudge.sol:169:52\n    │\n169 │         return eligibleTheses(week).length == 0 || block.timestamp >= (uint256(week) + 1) * 7 days + 28 days;\n    │                                                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/MarginaliaHook.sol:71:38\n   │\n71 │     bytes32 public constant ACTION = bytes32(\"oracle.request@oracle-1\");\n   │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes32' is safe 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/MarginaliaHook.sol:189:44\n    │\n189 │     constructor(IPoolManager poolManager_, address token_, address factory_) {\n    │                                            ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[reentrancy-no-eth]: external call can be reentered before `requestOf` is updated\n    ╭▸ src/MarginaliaJudge.sol:185:9\n    │\n185 │         hook.drawForJudging(day, price, retry);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `requestOf` is updated\n    ╭▸ src/MarginaliaJudge.sol:188:21\n    │\n188 │           requestId = intake.request(\n    │ ┏━━━━━━━━━━━━━━━━━━━━━┛\n189 │ ┃             action, body, IIntake.Callback(address(this), this.onOracleResult.selector), imd, price\n190 │ ┃         );\n    │ ┗━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaJudge.sol:177:41\n    │\n177 │         if (judgedSet[day] || (retry && block.timestamp < requestedAt[day] + ANSWER_DEADLINE)) {\n    │                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaJudge.sol:196:9\n    │\n196 │         emit Requested(day, requestId, price);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaJudge.sol:194:28\n    │\n194 │         requestedAt[day] = uint64(block.timestamp);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaJudge.sol:224:9\n    │\n224 │ ┏         emit Judged(\n225 │ ┃             day,\n226 │ ┃             [\n227 │ ┃                 count > 0 ? ranked[0] : bytes32(0),\n    ‡ ┃\n231 │ ┃         );\n    │ ┗━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:245:17\n    │\n245 │             if (dup) continue;\n    │                 ━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:238:50\n    │\n238 │         for (uint256 i = 0; i < ranked.length && kept < 3; ++i) {\n    │                                                  ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaJudge.sol:239:77\n    │\n239 │             (address author, uint32 noteWeek, bool thesis, bool hasChild) = hook.noteMeta(ranked[i]);\n    │                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/MarginaliaJudge.sol:257:9\n    │\n257 │         hook.payJudged(day, top);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/MarginaliaPricer.sol:85:13\n   │\n85 │             n += 1;\n   │             ━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaPricer.sol:119:33\n    │\n119 │         if (w.startedAt == 0 || block.timestamp > uint256(w.startedAt) + POST_MAX_AGE) {\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:120:34\n    │\n120 │             return T.PriceWindow(uint64(block.timestamp), uint64(block.number), x, x, x, q, q);\n    │                                  ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:120:59\n    │\n120 │             return T.PriceWindow(uint64(block.timestamp), uint64(block.number), x, x, x, q, q);\n    │                                                           ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe 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/MarginaliaPricer.sol:141:20\n    │\n141 │                 || block.timestamp < uint256(w.startedAt) + POST_MIN_SPAN\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/MarginaliaPricer.sol:142:20\n    │\n142 │                 || block.timestamp > uint256(w.startedAt) + POST_MAX_AGE\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:148:69\n    │\n148 │             x = twap(v.kind, v.xIsToken0, w.xStart, w.startedAt, x, uint64(block.timestamp));\n    │                                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:165:55\n    │\n165 │         else if (v.kind == T.VenueKind.UniV3) xRead = uint256(_v3Cumulative(ref));\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/MarginaliaPricer.sol:208:28\n    │\n208 │             int256 delta = int256(c2) - int256(c1);\n    │                            ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:208:41\n    │\n208 │             int256 delta = int256(c2) - int256(c1);\n    │                                         ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:209:35\n    │\n209 │             int256 mean = delta / int256(dt);\n    │                                   ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:210:38\n    │\n210 │             if (delta < 0 && delta % int256(dt) != 0) mean -= 1; // round toward negative infinity, as v3 does\n    │                                      ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:212:57\n    │\n212 │             return fromSqrt(TickMath.getSqrtPriceAtTick(int24(mean)), xIsToken0);\n    │                                                         ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int24' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaPricer.sol:234:37\n    │\n234 │             (uint160 sqrtP,,,,,,) = IUniswapV3PoolOracle(ref).slot0();\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/MarginaliaPricer.sol:238:41\n    │\n238 │             (uint112 r0, uint112 r1,) = IUniswapV2PairOracle(ref).getReserves();\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/MarginaliaPricer.sol:260:33\n    │\n260 │         (int56[] memory cum,) = IUniswapV3PoolOracle(pool).observe(ago);\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:270:24\n    │\n270 │         uint32 nowTs = uint32(block.timestamp);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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/MarginaliaRouter.sol:249:13\n    │\n249 │         if (block.timestamp > deadline) revert Expired();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:250:41\n    │\n250 │         if (amountIn == 0 || amountIn > uint256(uint128(type(int128).max))) revert InvalidSwap();\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/MarginaliaRouter.sol:250:49\n    │\n250 │         if (amountIn == 0 || amountIn > uint256(uint128(type(int128).max))) revert InvalidSwap();\n    │                                                 ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:336:9\n    │\n336 │         emit Noted(job.payer, job.sellMarg, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:318:18\n    │\n318 │                 -int256(job.amountIn),\n    │                  ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:326:25\n    │\n326 │         uint256 spent = uint256(uint128(-inputDelta));\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/MarginaliaRouter.sol:326:33\n    │\n326 │         uint256 spent = uint256(uint128(-inputDelta));\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:327:28\n    │\n327 │         uint256 received = uint256(uint128(outputDelta));\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/MarginaliaRouter.sol:327:36\n    │\n327 │         uint256 received = uint256(uint128(outputDelta));\n    │                                    ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:371:9\n    │\n371 │         emit XTraded(payer, X_V4, xIn, xOut, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:353:18\n    │\n353 │                 -int256(x.amountIn),\n    │                  ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:361:25\n    │\n361 │         uint256 spent = uint256(uint128(-inputDelta));\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/MarginaliaRouter.sol:361:33\n    │\n361 │         uint256 spent = uint256(uint128(-inputDelta));\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:362:20\n    │\n362 │         received = uint256(uint128(outputDelta));\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/MarginaliaRouter.sol:362:28\n    │\n362 │         received = uint256(uint128(outputDelta));\n    │                            ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:401:9\n    │\n401 │         emit XTraded(payer, X_V3, xIn, xOut, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:392:13\n    │\n392 │             int256(x.amountIn),\n    │             ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:397:25\n    │\n397 │         uint256 spent = uint256(zeroForOne ? a0 : a1);\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/MarginaliaRouter.sol:407:78\n    │\n407 │         if (amount0Delta > 0) IERC20(pool.token0()).safeTransfer(msg.sender, uint256(amount0Delta));\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/MarginaliaRouter.sol:408:78\n    │\n408 │         if (amount1Delta > 0) IERC20(pool.token1()).safeTransfer(msg.sender, uint256(amount1Delta));\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:436:9\n    │\n436 │         emit XTraded(payer, X_V2, xIn, xOut, actualIn, received);\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/MarginaliaRouter.sol:424:37\n    │\n424 │         (uint112 r0, uint112 r1,) = pair.getReserves();\n    │                                     ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:291:21\n    │\n291 │                 if (uint256(-params.amountSpecified) <= STAMP * 2) revert NoteTooSmall();\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/MarginaliaHook.sol:299:17\n    │\n299 │             if (uint256(-params.amountSpecified) <= depositMarg * 2) revert NoteTooSmall();\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/MarginaliaHook.sol:305:30\n    │\n305 │             specifiedTake = (uint256(params.amountSpecified) * bps + (10_000 - bps) - 1) / (10_000 - bps);\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:385:9\n    │\n385 │         emit Accrued(day, 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/MarginaliaHook.sol:457:9\n    │\n457 │ ┏         emit NotePosted(\n458 │ ┃             id,\n459 │ ┃             author,\n460 │ ┃             p.x,\n    ‡ ┃\n469 │ ┃             p.text\n470 │ ┃         );\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/MarginaliaHook.sol:337:13\n    │\n337 │             emit SwapFee(true, author, poolImd, 0, STAMP);\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/MarginaliaHook.sol:353:13\n    │\n353 │             emit SwapFee(false, author, poolImd, fee - STAMP, STAMP);\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/MarginaliaHook.sol:372:9\n    │\n372 │         emit SwapFee(false, tx.origin, poolImd, quietFee, 0);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:322:33\n    │\n322 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\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/MarginaliaHook.sol:322:41\n    │\n322 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\n    │                                         ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:322:63\n    │\n322 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\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/MarginaliaHook.sol:322:71\n    │\n322 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\n    │                                                                       ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:327:29\n    │\n327 │             uint256 netIn = uint256(-params.amountSpecified) - STAMP;\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/MarginaliaHook.sol:329:31\n    │\n329 │             uint256 margOut = uint256(uint128(margDelta));\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/MarginaliaHook.sol:329:39\n    │\n329 │             uint256 margOut = uint256(uint128(margDelta));\n    │                                       ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:362:25\n    │\n362 │             quietFee = (uint256(params.amountSpecified) * bps + (10_000 - bps) - 1) / (10_000 - bps);\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/MarginaliaHook.sol:363:28\n    │\n363 │             if (poolImd != uint256(params.amountSpecified) + quietFee) revert PartialFill();\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:445:17\n    │\n445 │             if (weekTheses[_week()].length < MAX_DAY_NOTES) weekTheses[_week()].push(id);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:437:22\n    │\n437 │         n.postedAt = uint64(block.timestamp);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe 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/MarginaliaHook.sol:489:13\n    │\n489 │         if (block.timestamp < end) revert TooEarly();\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/MarginaliaHook.sol:490:13\n    │\n490 │         if (block.timestamp > end + SETTLE_WINDOW) revert TooLate();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:498:32\n    │\n498 │         obs.push(T.Observation(uint64(block.timestamp), uint64(block.number), xRead, quoteRead, balance));\n    │                                ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:498:57\n    │\n498 │         obs.push(T.Observation(uint64(block.timestamp), uint64(block.number), xRead, quoteRead, balance));\n    │                                                         ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:499:27\n    │\n499 │         emit Observed(id, uint64(block.timestamp), xRead, quoteRead, balance);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaHook.sol:548:35\n    │\n548 │         emit Settled(id, outcome, settlePrice, scoreDelta, msg.sender);\n    │                                   ━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:507:13\n    │\n507 │         if (block.timestamp <= end + SETTLE_WINDOW) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:618:13\n    │\n618 │             emit ThesisReleased(n.parentId);\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/MarginaliaHook.sol:548:9\n    │\n548 │         emit Settled(id, outcome, settlePrice, scoreDelta, msg.sender);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:534:26\n    │\n534 │             scoreDelta = int256(_difficulty(n));\n    │                          ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:537:27\n    │\n537 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:541:27\n    │\n541 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:556:13\n    │\n556 │         if (block.timestamp >= horizonEnd(id)) revert TooLate();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:565:9\n    │\n565 │         emit Retracted(id, text);\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/MarginaliaHook.sol:566:9\n    │\n566 │         emit Settled(id, T.Status.Retracted, 0, scoreDelta, address(0));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:558:30\n    │\n558 │         int256 scoreDelta = -int256(_difficulty(n) / 2);\n    │                              ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/MarginaliaHook.sol:574:13\n    │\n574 │         if (block.timestamp <= uint256(n.postedAt) + THESIS_GRACE) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:577:9\n    │\n577 │         emit ThesisForfeited(id);\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/MarginaliaHook.sol:595:9\n    │\n595 │         emit DepositClaimed(id, n.author, asImd, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:633:16\n    │\n633 │         return uint32(block.timestamp / 1 days);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:637:16\n    │\n637 │         return uint32(block.timestamp / 7 days);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:658:38\n    │\n658 │         uint256 prevPos = prev > 0 ? uint256(prev) : 0;\n    │                                      ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:659:38\n    │\n659 │         uint256 nextPos = next > 0 ? uint256(next) : 0;\n    │                                      ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:669:9\n    │\n669 │         emit PotFunded(_today(), amount, msg.sender);\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/MarginaliaHook.sol:681:9\n    │\n681 │         emit PotMargSold(amount, imdOut, _today());\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:701:27\n    │\n701 │         return (n.author, uint32(uint256(n.postedAt) / 7 days), n.targetBps == 0, n.children > 0);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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 `thesisPool` is updated\n    ╭▸ src/MarginaliaHook.sol:800:28\n    │\n800 │         bytes memory out = poolManager.unlock(data);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaHook.sol:800:28\n    │\n800 │         bytes memory out = poolManager.unlock(data);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:723:9\n    │\n723 │         emit JudgedPaid(w, paidAmounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/MarginaliaHook.sol:801:39\n    │\n801 │         if (unlockHash != bytes32(0)) revert InvalidUnlock();\n    │                                       ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:731:47\n    │\n731 │         uint256 share = FullMath.mulDiv(pool, uint256(s), weekTotal[w]);\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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:737:13\n    │\n737 │         if (w >= _week()) revert TooEarly();\n    │             ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:744:9\n    │\n744 │         emit LeaderboardClaimed(w, msg.sender, amount);\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/MarginaliaHook.sol:751:13\n    │\n751 │         if (n.day >= _today()) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:761:9\n    │\n761 │         emit RefundClaimed(id, msg.sender, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:759:30\n    │\n759 │         notesPerDay[n.day] = uint32(count - 1);\n    │                              ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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/MarginaliaHook.sol:770:17\n    │\n770 │             if (block.timestamp < (uint256(epoch) + 1) * 1 days + SWEEP_AFTER) revert TooEarly();\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/MarginaliaHook.sol:774:17\n    │\n774 │             if (block.timestamp < (uint256(epoch) + 1) * 7 days + SWEEP_AFTER) revert TooEarly();\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/MarginaliaHook.sol:778:17\n    │\n778 │             if (block.timestamp < (uint256(epoch) + 1) * 7 days + SWEEP_AFTER) revert TooEarly();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:811:40\n    │\n811 │             address currency = address(uint160(extra));\n    │                                        ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint160' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaHook.sol:820:13\n    │\n820 │             poolManager.settle();\n    │             ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:830:22\n    │\n830 │                     -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/MarginaliaHook.sol:839:17\n    │\n839 │             if (uint256(uint128(-margDelta)) != amount) revert InvalidUnlock();\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/MarginaliaHook.sol:839:25\n    │\n839 │             if (uint256(uint128(-margDelta)) != amount) revert InvalidUnlock();\n    │                         ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:841:30\n    │\n841 │             uint256 imdOut = uint256(uint128(imdDelta));\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/MarginaliaHook.sol:841:38\n    │\n841 │             uint256 imdOut = uint256(uint128(imdDelta));\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[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n   ╭▸ test/AuditFindings.t.sol:19:30\n   │\n19 │         uint256 startBlock = block.number;\n   │                              ━━━━━━━━━━━━\n   ‡\n23 │             vm.roll(startBlock + 25 * (i + 1));\n   │             ────────────────────────────────── `vm.roll` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockNumber()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/AuditFindings.t.sol:20:27\n   │\n20 │         uint256 startTs = block.timestamp;\n   │                           ━━━━━━━━━━━━━━━\n   ‡\n24 │             vm.warp(startTs + 31 minutes * (i + 1));\n   │             ─────────────────────────────────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/AuditFindings.t.sol:18:9\n    │\n 18 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/AuditFindings.t.sol:65:9\n    │\n 65 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/AuditFindings.t.sol:65:17\n   │\n65 │         vm.warp(block.timestamp + 7 days);\n   │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:126:9\n    │\n126 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:127:30\n    │\n127 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n131 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:128:27\n    │\n128 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n132 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:154:9\n    │\n154 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:155:30\n    │\n155 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n159 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:156:27\n    │\n156 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n160 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:178:9\n    │\n178 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:179:30\n    │\n179 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n183 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:180:27\n    │\n180 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n184 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:270:9\n    │\n270 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:270:17\n    │\n270 │         vm.warp(block.timestamp + 7 days);\n    │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:320:9\n    │\n320 │         vm.warp(hook.horizonEnd(a));\n    │         ─────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:321:30\n    │\n321 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n326 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:322:27\n    │\n322 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n327 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:400:9\n    │\n400 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:400:17\n    │\n400 │         vm.warp(block.timestamp + 7 days);\n    │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:466:9\n    │\n466 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:467:30\n    │\n467 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n470 │         vm.roll(startBlock + 25);\n    │         ──────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:468:27\n    │\n468 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n471 │         vm.warp(startTs + 30 minutes);\n    │         ───────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:490:9\n    │\n490 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:491:30\n    │\n491 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n495 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:492:27\n    │\n492 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n496 │             vm.warp(startTs + 10 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\n","passed":true},{"durationMs":156,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/fork/MainnetLaunch.t.sol:MainnetLaunchTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 622.34µs (0.00ns CPU time)\n\nRan 7 tests for test/Pricer.t.sol:PricerTest\n[PASS] testQuoteLegIsAdverseEvenUnderAV3Twap() (gas: 28379)\n[PASS] testTwapRefusesZeroSpanAndV4() (gas: 17708)\n[PASS] testV2TwapFromWrappingCumulative() (gas: 9484)\n[PASS] testV3TwapOfAConstantTickIsThatTick() (gas: 15421)\n[PASS] testV3TwapRoundsNegativeMeansDown() (gas: 14810)\n[PASS] testV3TwapWeightsByTime() (gas: 14677)\n[PASS] testV4SettlesOnTheAdverseExtreme() (gas: 26598)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 646.58µs (774.53µs CPU time)\n\nRan 7 tests for test/JudgeOracle.t.sol:JudgeOracleTest\n[PASS] testEmptySignedRankingIsAnExecutableNoWinnerResult() (gas: 247978)\n[PASS] testFiveIdsWithEoaSignatureFitStipend() (gas: 553767)\n[PASS] testFullRankingWithEoaSignatureFitsStipend() (gas: 633387)\n[PASS] testProtocolDigestSignatureAndSelectorConformanceOnClone() (gas: 3237905)\n[PASS] testRejectedAnswersDoNotConsumeThePendingRequest() (gas: 892198)\n[PASS] testRequestedHeadIsFilteredAndDeduplicatedWithoutPromotingTheTail() (gas: 250548)\n[PASS] testTimeoutRetryInvalidatesOldIntakeRequest() (gas: 523778)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 2.36ms (5.04ms CPU time)\n\nRan 8 tests for test/PriceHistory.t.sol:PriceHistoryTest\n[PASS] testBaselineRequiresMatureFreshHistory() (gas: 188329)\n[PASS] testEmptyVenueAndHubCannotBeCheckpointedObservedOrPriced() (gas: 284473)\n[PASS] testFuzzV4BaselineIsNeverFavourableToTheCall(int24,bool) (runs: 256, μ: 105907, ~: 106038)\nLogs:\n  Bound result 40243\n\n[PASS] testHubBaselineUsesOppositeExtremeFromSettlement() (gas: 180188)\n[PASS] testLiveCheckpointCannotEraseHonestExtremesOrRestartTheClock() (gas: 224136)\n[PASS] testV2BaselineIgnoresSameBlockReservesDumpAndPumpBothOrientations() (gas: 467438)\n[PASS] testV3BaselineIgnoresSameBlockTickChangesBothOrientations() (gas: 417955)\n[PASS] testV3BaselineWeightsElapsedTime() (gas: 370983)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 8.58ms (9.71ms CPU time)\n\nRan 26 tests for test/Lifecycle.t.sol:LifecycleTest\n[PASS] testAttestedClassCannotBeSelfDeclared() (gas: 342970)\n[PASS] testCallbackSelectorPinned() (gas: 3361)\n[PASS] testFakeVenueIsRefused() (gas: 382643)\n[PASS] testFlagsAndBinding() (gas: 55816)\n[PASS] testForfeitsConvertToImdForThePot() (gas: 1111031)\n[PASS] testLeaderboardProRataWithCap() (gas: 3237594)\n[PASS] testNoDataRefunds() (gas: 921203)\n[PASS] testNoteTooSmall() (gas: 172902)\n[PASS] testNotedBuyTakesStampAndDeposit() (gas: 797709)\n[PASS] testNotedSellPaysOnePercentPlusStamp() (gas: 1106493)\n[PASS] testObservationsMustSpanAnHour() (gas: 1429115)\n[PASS] testPlainBuyTakesNothing() (gas: 229914)\n[PASS] testQuietSellPaysThreePercent() (gas: 336209)\n[PASS] testQuietThesisPoolSweeps() (gas: 305287)\n[PASS] testRetract() (gas: 944843)\n[PASS] testRightCallReturnsDepositAsImd() (gas: 1799432)\n[PASS] testSellingEarlyBreaksTheCall() (gas: 1767952)\n[PASS] testThesisParentChild() (gas: 1450566)\n[PASS] testThesisWithoutChildForfeits() (gas: 796691)\n[PASS] testTreasuryDrip() (gas: 347870)\n[PASS] testTwoBlockPumpObserveUnwindSettlesWrong() (gas: 1799481)\n[PASS] testUnansweredWeekCanBeRetried() (gas: 2439911)\n[PASS] testUpOnlyIsRefused() (gas: 340578)\n[PASS] testWeeklyThesisJudging() (gas: 3852889)\n[PASS] testWriterRefundCappedAtStamp() (gas: 1709522)\n[PASS] testWrongCallForfeitsWithKeeperReward() (gas: 1557388)\nSuite result: ok. 26 passed; 0 failed; 0 skipped; finished in 16.60ms (24.10ms CPU time)\n\nRan 8 tests for test/AuditFindings.t.sol:AuditFindingsTest\n[PASS] testConversionAfterARealPriceFallNeedsAFreshMatureWindow() (gas: 1574034)\n[PASS] testEmptyV4ObservationIsRefused() (gas: 966273)\n[PASS] testExpiredBaselineRejectsPostWithoutTakingFunds() (gas: 643275)\n[PASS] testForfeitureConversionRejectsSameBlockDump() (gas: 1234412)\n[PASS] testLongRankingFitsIntakeStipend() (gas: 2191552)\n[PASS] testSameBlockDumpPostUnwindDoesNotWinBuy() (gas: 1911932)\n[PASS] testSameBlockPumpPostUnwindDoesNotWinSell() (gas: 1783360)\n[PASS] testUnpayableRankingRollsTheWholePoolForward() (gas: 2464505)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 19.88ms (8.06ms CPU time)\n\nRan 3 tests for test/Implementations.t.sol:ImplementationsTest\n[PASS] testClonesInitializeOnceOnlyFromTheirHook() (gas: 4551159)\n[PASS] testFactoryDeploysAllFourWithoutArgumentsOrExternalDependencies() (gas: 34030325)\nLogs:\n  four implementation CREATE2 deployments (gas): 8694125\n\n[PASS] testImplementationsRejectInitialization() (gas: 81332)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 52.22ms (52.99ms CPU time)\n\nRan 7 test suites in 53.05ms (100.91ms CPU time): 59 tests passed, 0 failed, 1 skipped (60 total tests)\n","passed":true},{"durationMs":64,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"Marginalia.approve(address,uint256)\",\"Marginalia.transfer(address,uint256)\",\"Marginalia.transferFrom(address,address,uint256)\",\"MarginaliaHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"MarginaliaHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"MarginaliaHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"MarginaliaHook.claimDeposit(bytes32,bool)\",\"MarginaliaHook.claimLeaderboard(uint32)\",\"MarginaliaHook.claimRefund(bytes32)\",\"MarginaliaHook.drawForJudging(uint32,uint256,bool)\",\"MarginaliaHook.fundPot(uint256)\",\"MarginaliaHook.observe(bytes32)\",\"MarginaliaHook.payJudged(uint32,bytes32[3])\",\"MarginaliaHook.retract(bytes32,string)\",\"MarginaliaHook.sellPotMarg(uint256)\",\"MarginaliaHook.settle(bytes32)\",\"MarginaliaHook.settleThesis(bytes32)\",\"MarginaliaHook.sweep(uint8,uint32)\",\"MarginaliaHook.unlockCallback(bytes)\",\"MarginaliaJudge.convertForfeits()\",\"MarginaliaJudge.init(address,address,bytes32,address)\",\"MarginaliaJudge.onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"MarginaliaJudge.payJudged(uint32)\",\"MarginaliaJudge.requestJudging(uint32)\",\"MarginaliaRouter.checkpointVenue((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address))\",\"MarginaliaRouter.init(address,address)\",\"MarginaliaRouter.note((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address),uint256,uint256,uint256)\",\"MarginaliaRouter.sellWithNote((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address),uint256,uint256,uint256)\",\"MarginaliaRouter.uniswapV3SwapCallback(int256,int256,bytes)\",\"MarginaliaRouter.unlockCallback(bytes)\",\"MarginaliaTreasury.drip()\",\"MarginaliaTreasury.init(address)\"],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":141,\"README.md\":123,\"SPEC.md\":263,\"dependencies.json\":28,\"foundry.toml\":21,\"helper/.gitignore\":3,\"helper/package-lock.json\":737,\"helper/package.json\":20,\"helper/public/index.html\":82,\"helper/server.js\":90,\"helper/src/app.js\":203,\"jobs/launch-1-hook.json\":43,\"jobs/launch-2-contracts.json\":38,\"jobs/launch-A-implementations.json\":47,\"jobs/launch-A2-implementations.json\":41,\"jobs/launch-hook-v3.json\":43,\"remappings.txt\":4,\"src/HookFlags.sol\":33,\"src/Marginalia.sol\":12,\"src/MarginaliaHook.sol\":863,\"src/MarginaliaImpls.sol\":14,\"src/MarginaliaJudge.sol\":259,\"src/MarginaliaPricer.sol\":292,\"src/MarginaliaRouter.sol\":444,\"src/MarginaliaTreasury.sol\":53,\"src/MarginaliaTypes.sol\":108,\"src/OracleAttestation.sol\":221,\"src/interfaces/IIntake.sol\":15,\"src/interfaces/ILaunchFactory.sol\":49,\"test/AuditFindings.t.sol\":178,\"test/Implementations.t.sol\":96,\"test/JudgeOracle.t.sol\":270,\"test/Lifecycle.t.sol\":502,\"test/PriceHistory.t.sol\":233,\"test/Pricer.t.sol\":88,\"test/fork/MainnetLaunch.t.sol\":382,\"test/helpers/Fixture.sol\":278,\"test/mocks/MockERC20.sol\":13},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":10971,"exitCode":0,"name":"slither","output":"[high/medium] weak-prng at src/MarginaliaPricer.sol:200: MarginaliaPricer.twap(MarginaliaTypes.VenueKind,bool,uint256,uint64,uint256,uint64) (src/MarginaliaPricer.sol#200-222) uses a weak PRNG: \"delta < 0 && delta % int256(dt) != 0 (src/MarginaliaPricer.sol#210)\"\n[high/medium] reentrancy-balance at src/MarginaliaRouter.sol:412: Reentrancy in MarginaliaRouter._tradeV2(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#412-437):\n[high/medium] reentrancy-balance at src/MarginaliaRouter.sol:285: Reentrancy in MarginaliaRouter._pull(address,uint256) (src/MarginaliaRouter.sol#285-290):\n[high/medium] reentrancy-balance at src/MarginaliaRouter.sol:412: Reentrancy in MarginaliaRouter._tradeV2(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#412-437):\n[high/medium] reentrancy-balance at src/MarginaliaRouter.sol:375: Reentrancy in MarginaliaRouter._tradeV3(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#375-402):\n[high/medium] reentrancy-balance at src/MarginaliaRouter.sol:412: Reentrancy in MarginaliaRouter._tradeV2(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#412-437):\n[high/medium] reentrancy-balance at src/MarginaliaRouter.sol:375: Reentrancy in MarginaliaRouter._tradeV3(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#375-402):\n[high/high] uninitialized-state at src/MarginaliaHook.sol:485: MarginaliaHook.observations (src/MarginaliaHook.sol#93) is never initialized. It is used in:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:285: MarginaliaRouter._pull(address,uint256) (src/MarginaliaRouter.sol#285-290) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:292: MarginaliaRouter._checkSubject(MarginaliaRouter.Job) (src/MarginaliaRouter.sol#292-295) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:297: MarginaliaRouter.unlockCallback(bytes) (src/MarginaliaRouter.sol#297-338) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaHook.sol:767: MarginaliaHook.sweep(uint8,uint32) (src/MarginaliaHook.sol#767-786) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaHook.sol:736: MarginaliaHook.claimLeaderboard(uint32) (src/MarginaliaHook.sol#736-745) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:375: MarginaliaRouter._tradeV3(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#375-402) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:240: MarginaliaRouter._run(bool,uint256,uint256,uint256,MarginaliaRouter.XTrade,MarginaliaTypes.NoteParams,PoolKey) (src/MarginaliaRouter.sol#240-282) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaHook.sol:794: MarginaliaHook._unlock(uint8,address,uint256,uint256) (src/MarginaliaHook.sol#794-803) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:412: MarginaliaRouter._tradeV2(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#412-437) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaPricer.sol:284: MarginaliaPricer.fromSqrt(uint160,bool) (src/MarginaliaPricer.sol#284-291) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaTreasury.sol:42: MarginaliaTreasury.drip() (src/MarginaliaTreasury.sol#42-52) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaPricer.sol:284: MarginaliaPricer.fromSqrt(uint160,bool) (src/MarginaliaPricer.sol#284-291) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaTreasury.sol:42: MarginaliaTreasury.drip() (src/MarginaliaTreasury.sol#42-52) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:412: MarginaliaRouter._tradeV2(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#412-437) uses a dangerous strict equality:\n[medium/medium] reentrancy-no-eth at src/MarginaliaHook.sol:503: Reentrancy in MarginaliaHook.settle(bytes32) (src/MarginaliaHook.sol#503-549):\n[medium/medium] reentrancy-no-eth at src/MarginaliaHook.sol:705: Reentrancy in MarginaliaHook.payJudged(uint32,bytes32[3]) (src/MarginaliaHook.sol#705-724):\n[medium/medium] reentrancy-no-eth at src/MarginaliaHook.sol:552: Reentrancy in MarginaliaHook.retract(bytes32,string) (src/MarginaliaHook.sol#552-567):\n[medium/medium] reentrancy-no-eth at src/MarginaliaJudge.sol:174: Reentrancy in MarginaliaJudge.requestJudging(uint32) (src/MarginaliaJudge.sol#174-197):\n[medium/medium] uninitialized-local at src/MarginaliaRouter.sol:178: MarginaliaRouter.sellWithNote(MarginaliaTypes.NoteParams,PoolKey,uint256,uint256,uint256).noX (src/MarginaliaRouter.sol#178) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaJudge.sol:109: MarginaliaJudge.questionBody(uint32).allow (src/MarginaliaJudge.sol#109) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaHook.sol:511: MarginaliaHook.settle(bytes32).settlePrice (src/MarginaliaHook.sol#511) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaRouter.sol:165: MarginaliaRouter.note(MarginaliaTypes.NoteParams,PoolKey,uint256,uint256,uint256).noX (src/MarginaliaRouter.sol#165) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaRouter.sol:255: MarginaliaRouter._run(bool,uint256,uint256,uint256,MarginaliaRouter.XTrade,MarginaliaTypes.NoteParams,PoolKey).job (src/MarginaliaRouter.sol#255) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaJudge.sol:95: MarginaliaJudge.eligibleTheses(uint32).n (src/MarginaliaJudge.sol#95) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaRouter.sol:204: MarginaliaRouter.validateVenue(MarginaliaTypes.NoteParams,PoolKey).t1 (src/MarginaliaRouter.sol#204) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaJudge.sol:241: MarginaliaJudge.judgedOf(uint32).dup (src/MarginaliaJudge.sol#241) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaJudge.sol:237: MarginaliaJudge.judgedOf(uint32).kept (src/MarginaliaJudge.sol#237) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaHook.sol:712: MarginaliaHook.payJudged(uint32,bytes32[3]).paidAmounts (src/MarginaliaHook.sol#712) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaJudge.sol:150: MarginaliaJudge._dec(uint256).n (src/MarginaliaJudge.sol#150) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaRouter.sol:203: MarginaliaRouter.validateVenue(MarginaliaTypes.NoteParams,PoolKey).t0 (src/MarginaliaRouter.sol#203) is a local variable never initialized\n[medium/medium] unused-return at src/MarginaliaHook.sol:805: MarginaliaHook.unlockCallback(bytes) (src/MarginaliaHook.sol#805-851) ignores return value by poolManager.settle() (src/MarginaliaHook.sol#820)\n[medium/medium] unused-return at src/MarginaliaJudge.sol:92: MarginaliaJudge.eligibleTheses(uint32) (src/MarginaliaJudge.sol#92-104) ignores return value by (None,None,None,hasChild) = hook.noteMeta(all[i]) (src/MarginaliaJudge.sol#97)\n[medium/medium] unused-return at src/MarginaliaPricer.sol:226: MarginaliaPricer._spotInQuote(IPoolManager,MarginaliaTypes.Venue) (src/MarginaliaPricer.sol#226-243) ignores return value by (sqrtP_scope_0,None,None,None,None,None,None) = IUniswapV3PoolOracle(ref).slot0() (src/MarginaliaPricer.sol#234)\n[medium/medium] unused-return at src/MarginaliaPricer.sol:246: MarginaliaPricer._quoteSpot(IPoolManager,address,address) (src/MarginaliaPricer.sol#246-255) ignores return value by (sqrtP,None,None,None) = manager.getSlot0(PoolId.wrap(HUB_POOL_ID)) (src/MarginaliaPricer.sol#251)\n[medium/medium] unused-return at src/MarginaliaHook.sol:273: MarginaliaHook.margPriceInImd() (src/MarginaliaHook.sol#273-276) ignores return value by (sqrtP,None,None,None) = poolManager.getSlot0(poolId) (src/MarginaliaHook.sol#274)\n[medium/medium] unused-return at src/MarginaliaPricer.sol:226: MarginaliaPricer._spotInQuote(IPoolManager,MarginaliaTypes.Venue) (src/MarginaliaPricer.sol#226-243) ignores return value by (r0,r1,None) = IUniswapV2PairOracle(ref).getReserves() (src/MarginaliaPricer.sol#238)\n[medium/medium] unused-return at src/MarginaliaPricer.sol:226: MarginaliaPricer._spotInQuote(IPoolManager,MarginaliaTypes.Venue) (src/MarginaliaPricer.sol#226-243) ignores return value by (sqrtP,None,None,None) = manager.getSlot0(PoolId.wrap(v.ref)) (src/MarginaliaPricer.sol#230)\n[medium/medium] unused-return at src/MarginaliaPricer.sol:258: MarginaliaPricer._v3Cumulative(address) (src/MarginaliaPricer.sol#258-262) ignores return value by (cum,None) = IUniswapV3PoolOracle(pool).observe(ago) (src/MarginaliaPricer.sol#260)\n[medium/medium] unused-return at src/MarginaliaRouter.sol:412: MarginaliaRouter._tradeV2(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#412-437) ignores return value by (r0,r1,None) = pair.getReserves() (src/MarginaliaRouter.sol#424)\n[low/high] shadowing-local at src/MarginaliaHook.sol:730: MarginaliaHook.leaderboardShare(uint32,address).pool (src/MarginaliaHook.sol#730) shadows:\n[low/high] shadowing-local at src/MarginaliaHook.sol:709: MarginaliaHook.payJudged(uint32,bytes32[3]).pool (src/MarginaliaHook.sol#709) shadows:\n[low/high] shadowing-local at src/MarginaliaHook.sol:644: MarginaliaHook._accrue(uint256).week (src/MarginaliaHook.sol#379) shadows:\n[low/high] shadowing-local at src/MarginaliaJudge.sol:14: IHookJudge.noteMeta(bytes32).week (src/MarginaliaJudge.sol#19) shadows:\n[low/high] shadowing-local at src/MarginaliaJudge.sol:14: IHookJudge.thesesOfWeek(uint32).week (src/MarginaliaJudge.sol#15) shadows:\n[low/high] shadowing-local at src/MarginaliaJudge.sol:14: IHookJudge.thesisPool(uint32).week (src/MarginaliaJudge.sol#12) shadows:\n[low/high] shadowing-local at src/MarginaliaJudge.sol:14: IHookJudge.drawForJudging(uint32,uint256,bool).week (src/MarginaliaJudge.sol#21) shadows:\n[low/medium] calls-loop at src/MarginaliaJudge.sol:92: MarginaliaJudge.eligibleTheses(uint32) (src/MarginaliaJudge.sol#92-104) has external calls inside a loop: (None,None,None,hasChild) = hook.noteMeta(all[i]) (src/MarginaliaJudge.sol#97)\n[low/medium] calls-loop at src/MarginaliaJudge.sol:235: MarginaliaJudge.judgedOf(uint32) (src/MarginaliaJudge.sol#235-248) has external calls inside a loop: (author,noteWeek,thesis,hasChild) = hook.noteMeta(ranked[i]) (src/MarginaliaJudge.sol#239)\n[low/medium] calls-loop at src/MarginaliaJudge.sol:92: MarginaliaJudge.eligibleTheses(uint32) (src/MarginaliaJudge.sol#92-104) has external calls inside a loop: (None,None,None,hasChild) = hook.noteMeta(all[i]) (src/MarginaliaJudge.sol#97)\n[low/medium] calls-loop at src/MarginaliaJudge.sol:235: MarginaliaJudge.judgedOf(uint32) (src/MarginaliaJudge.sol#235-248) has external calls inside a loop: (author,noteWeek,thesis,hasChild) = hook.noteMeta(ranked[i]) (src/MarginaliaJudge.sol#239)\n[low/medium] calls-loop at src/MarginaliaHook.sol:794: MarginaliaHook._unlock(uint8,address,uint256,uint256) (src/MarginaliaHook.sol#794-803) has external calls inside a loop: out = poolManager.unlock(data) (src/MarginaliaHook.sol#800)\n[low/medium] calls-loop at src/MarginaliaJudge.sol:92: MarginaliaJudge.eligibleTheses(uint32) (src/MarginaliaJudge.sol#92-104) has external calls inside a loop: (None,None,None,hasChild) = hook.noteMeta(all[i]) (src/MarginaliaJudge.sol#97)\n[low/medium] calls-loop at src/MarginaliaJudge.sol:92: MarginaliaJudge.eligibleTheses(uint32) (src/MarginaliaJudge.sol#92-104) has external calls inside a loop: (None,None,None,hasChild) = hook.noteMeta(all[i]) (src/MarginaliaJudge.sol#97)\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:503: Reentrancy in MarginaliaHook.settle(bytes32) (src/MarginaliaHook.sol#503-549):\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:664: Reentrancy in MarginaliaHook.fundPot(uint256) (src/MarginaliaHook.sol#664-670):\n[low/medium] reentrancy-benign at src/MarginaliaRouter.sol:375: Reentrancy in MarginaliaRouter._tradeV3(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#375-402):\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:310: Reentrancy in MarginaliaHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/MarginaliaHook.sol#310-374):\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:310: Reentrancy in MarginaliaHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/MarginaliaHook.sol#310-374):\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:673: Reentrancy in MarginaliaHook.sellPotMarg(uint256) (src/MarginaliaHook.sol#673-682):\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:310: Reentrancy in MarginaliaHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/MarginaliaHook.sol#310-374):\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:603: Reentrancy in MarginaliaHook._forfeit(MarginaliaTypes.Note,address) (src/MarginaliaHook.sol#603-610):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:310: Reentrancy in MarginaliaHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/MarginaliaHook.sol#310-374):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:673: Reentrancy in MarginaliaHook.sellPotMarg(uint256) (src/MarginaliaHook.sol#673-682):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:503: Reentrancy in MarginaliaHook.settle(bytes32) (src/MarginaliaHook.sol#503-549):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:748: Reentrancy in MarginaliaHook.claimRefund(bytes32) (src/MarginaliaHook.sol#748-762):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:705: Reentrancy in MarginaliaHook.payJudged(uint32,bytes32[3]) (src/MarginaliaHook.sol#705-724):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:310: Reentrancy in MarginaliaHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/MarginaliaHook.sol#310-374):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:552: Reentrancy in MarginaliaHook.retract(bytes32,string) (src/MarginaliaHook.sol#552-567):\n[low/medium] reentrancy-events at src/MarginaliaTreasury.sol:42: Reentrancy in MarginaliaTreasury.drip() (src/MarginaliaTreasury.sol#42-52):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:581: Reentrancy in MarginaliaHook.claimDeposit(bytes32,bool) (src/MarginaliaHook.sol#581-596):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:570: Reentrancy in MarginaliaHook.settleThesis(bytes32) (src/MarginaliaHook.sol#570-578):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:736: Reentrancy in MarginaliaHook.claimLeaderboard(uint32) (src/MarginaliaHook.sol#736-745):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:310: Reentrancy in MarginaliaHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/MarginaliaHook.sol#310-374):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:664: Reentrancy in MarginaliaHook.fundPot(uint256) (src/MarginaliaHook.sol#664-670):\n[low/medium] timestamp at src/MarginaliaHook.sol:686: MarginaliaHook.drawForJudging(uint32,uint256,bool) (src/MarginaliaHook.sol#686-692) uses timestamp for comparisons\n[low/medium] timestamp at src/MarginaliaPricer.sol:265: MarginaliaPricer._v2Cumulative(address,bool) (src/MarginaliaPricer.sol#265-277) uses timestamp for comparisons\n[low/medium] timestamp at src/MarginaliaPricer.sol:200: MarginaliaPricer.twap(MarginaliaTypes.VenueKind,bool,uint256,uint64,uint256,uint64) (src/MarginaliaPricer.sol#200-222) uses timestamp for comparisons\n[low/medium] timestamp at src/MarginaliaHook.sol:767: MarginaliaHook.sweep(uint8,uint32) (src/MarginaliaHook.sol#767-786) uses timestamp for comparisons\n[low/medium] timestamp at src/Margina","passed":true},{"durationMs":868,"exitCode":0,"name":"aderyn","output":"[high] eth-send-unchecked-address at src/MarginaliaHook.sol:664: ETH transferred without address checks (3 places)\n[high] reentrancy-state-change at src/MarginaliaHook.sol:203: Reentrancy: State change after external call (15 places)\n[low] costly-loop at src/MarginaliaHook.sol:714: Costly operations inside loop (2 places)\n[low] internal-function-used-once at src/HookFlags.sol:26: Internal Function Used Only Once (2 places)\n[low] large-numeric-literal at src/Marginalia.sol:10: Large Numeric Literal (22 places)\n[low] literal-instead-of-constant at src/MarginaliaHook.sol:298: Literal Instead of Constant (58 places)\n[low] local-variable-shadowing at src/MarginaliaHook.sol:709: Local Variable Shadows State Variable (2 places)\n[low] require-revert-in-loop at src/MarginaliaHook.sol:714: Loop Contains `require`/`revert`\n[low] state-change-without-event at src/MarginaliaHook.sol:278: State Change Without Event (7 places)\n[low] state-no-address-check at src/MarginaliaRouter.sol:134: Address State Variable Set Without Checks\n[low] unchecked-return at src/MarginaliaHook.sol:591: Unchecked Return (8 places)\n[low] uninitialized-local-variable at src/MarginaliaJudge.sol:150: Uninitialized Local Variable (2 places)","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"5b9289bab76acb6d84029fd7db2d47f82cc9a5569b8d74a5a9e2a3b6fd9f2cc0","verifiedTreeHash":"6b5673f9e1b548615ba5ddace73a210cf48f4ffa","verifierVersion":"0.1.0+fdeb4d4a"},{"checks":[{"durationMs":142417,"exitCode":0,"name":"build","output":"Compiling 114 files with Solc 0.8.26\nSolc 0.8.26 finished in 142.18s\nCompiler run successful with warnings:\nWarning (8760): This declaration has the same name as another declaration.\n   --> src/MarginaliaHook.sol:383:9:\n    |\n383 |         uint32 week = _week();\n    |         ^^^^^^^^^^^\nNote: The other declaration is here:\n   --> src/MarginaliaHook.sol:706:5:\n    |\n706 |     function week() external view returns (uint32) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:771:9:\n    |\n771 |         uint256 pool = thesisPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:90:5:\n   |\n90 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:792:9:\n    |\n792 |         uint256 pool = leaderboardPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:90:5:\n   |\n90 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2018): Function state mutability can be restricted to pure\n   --> test/helpers/Fixture.sol:114:5:\n    |\n114 |     function priceOf(bytes32, address) external view returns (uint256) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (2018): Function state mutability can be restricted to pure\n  --> test/fork/MainnetLaunch.t.sol:78:5:\n   |\n78 |     function _mine(bytes memory hookCode) internal view returns (bytes32 salt) {\n   |     ^ (Relevant source part starts here and spans across multiple lines).\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/MarginaliaTreasury.sol:51:9\n   │\n51 │         emit Dripped(day, amount);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/MarginaliaTreasury.sol:43:22\n   │\n43 │         uint32 day = uint32(block.timestamp / 1 days);\n   │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint32' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/MarginaliaPricer.sol:85:13\n   │\n85 │             n += 1;\n   │             ━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaPricer.sol:120:33\n    │\n120 │         if (w.startedAt == 0 || block.timestamp > uint256(w.startedAt) + POST_MAX_AGE) {\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[missing-events-access-control]: `jobHash` is changed without an event but is used for access control\n    ╭▸ src/MarginaliaRouter.sol:303:16\n    │\n303 │         delete jobHash;\n    │                ━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:121:34\n    │\n121 │             return T.PriceWindow(uint64(block.timestamp), uint64(block.number), x, x, x, q, q);\n    │                                  ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:121:59\n    │\n121 │             return T.PriceWindow(uint64(block.timestamp), uint64(block.number), x, x, x, q, q);\n    │                                                           ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe 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/MarginaliaPricer.sol:142:20\n    │\n142 │                 || block.timestamp < uint256(w.startedAt) + POST_MIN_SPAN\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/MarginaliaPricer.sol:143:20\n    │\n143 │                 || block.timestamp > uint256(w.startedAt) + POST_MAX_AGE\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:149:69\n    │\n149 │             x = twap(v.kind, v.xIsToken0, w.xStart, w.startedAt, x, uint64(block.timestamp));\n    │                                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:168:55\n    │\n168 │         else if (v.kind == T.VenueKind.UniV3) xRead = uint256(_v3Cumulative(ref));\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/MarginaliaPricer.sol:213:28\n    │\n213 │             int256 delta = int256(c2) - int256(c1);\n    │                            ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:213:41\n    │\n213 │             int256 delta = int256(c2) - int256(c1);\n    │                                         ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:214:35\n    │\n214 │             int256 mean = delta / int256(dt);\n    │                                   ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:215:38\n    │\n215 │             if (delta < 0 && delta % int256(dt) != 0) mean -= 1; // round toward negative infinity, as v3 does\n    │                                      ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:217:57\n    │\n217 │             return fromSqrt(TickMath.getSqrtPriceAtTick(int24(mean)), xIsToken0);\n    │                                                         ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int24' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaPricer.sol:241:37\n    │\n241 │             (uint160 sqrtP,,,,,,) = IUniswapV3PoolOracle(ref).slot0();\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/MarginaliaPricer.sol:245:41\n    │\n245 │             (uint112 r0, uint112 r1,) = IUniswapV2PairOracle(ref).getReserves();\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/MarginaliaPricer.sol:269:33\n    │\n269 │         (int56[] memory cum,) = IUniswapV3PoolOracle(pool).observe(ago);\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/MarginaliaHook.sol:75:38\n   │\n75 │     bytes32 public constant ACTION = bytes32(\"oracle.request@oracle-1\");\n   │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes32' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:279:24\n    │\n279 │         uint32 nowTs = uint32(block.timestamp);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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/MarginaliaHook.sol:193:44\n    │\n193 │     constructor(IPoolManager poolManager_, address token_, address factory_) {\n    │                                            ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n   ╭▸ src/MarginaliaJudge.sol:96:17\n   │\n96 │             try hook.sellPotMarg(marg) returns (uint256 out) {\n   │                 ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n   ╭▸ src/MarginaliaJudge.sol:96:17\n   │\n96 │             try hook.sellPotMarg(marg) returns (uint256 out) {\n   │                 ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:114:47\n    │\n114 │         for (uint256 i = 0; i < all.length && n < MAX_JUDGED; ++i) {\n    │                                               ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaJudge.sol:115:35\n    │\n115 │             (,,, bool hasChild) = hook.noteMeta(all[i]);\n    │                                   ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaJudge.sol:115:35\n    │\n115 │             (,,, bool hasChild) = hook.noteMeta(all[i]);\n    │                                   ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:170:15\n    │\n170 │             ++n;\n    │               ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaJudge.sol:174:33\n    │\n174 │             out[i - 1] = bytes1(uint8(48 + v % 10));\n    │                                 ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaJudge.sol:186:52\n    │\n186 │         return eligibleTheses(week).length == 0 || block.timestamp >= (uint256(week) + 1) * 7 days + 28 days;\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/MarginaliaJudge.sol:194:32\n    │\n194 │         if (judgedSet[week] || block.timestamp < requestedAt[week] + ANSWER_DEADLINE) {\n    │                                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-no-eth]: external call can be reentered before `requestOf` is updated\n    ╭▸ src/MarginaliaJudge.sol:214:9\n    │\n214 │         hook.drawForJudging(day, price, retry);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `requestOf` is updated\n    ╭▸ src/MarginaliaJudge.sol:217:21\n    │\n217 │           requestId = intake.request(\n    │ ┏━━━━━━━━━━━━━━━━━━━━━┛\n218 │ ┃             action, body, IIntake.Callback(address(this), this.onOracleResult.selector), imd, price\n219 │ ┃         );\n    │ ┗━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaJudge.sol:206:41\n    │\n206 │         if (judgedSet[day] || (retry && block.timestamp < requestedAt[day] + ANSWER_DEADLINE)) {\n    │                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaJudge.sol:225:9\n    │\n225 │         emit Requested(day, requestId, price);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaJudge.sol:223:28\n    │\n223 │         requestedAt[day] = uint64(block.timestamp);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaJudge.sol:255:9\n    │\n255 │ ┏         emit Judged(\n256 │ ┃             day,\n257 │ ┃             [\n258 │ ┃                 count > 0 ? ranked[0] : bytes32(0),\n    ‡ ┃\n262 │ ┃         );\n    │ ┗━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:276:17\n    │\n276 │             if (dup) continue;\n    │                 ━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:269:50\n    │\n269 │         for (uint256 i = 0; i < ranked.length && kept < 3; ++i) {\n    │                                                  ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaJudge.sol:270:77\n    │\n270 │             (address author, uint32 noteWeek, bool thesis, bool hasChild) = hook.noteMeta(ranked[i]);\n    │                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/MarginaliaJudge.sol:288:9\n    │\n288 │         hook.payJudged(day, top);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaRouter.sol:251:13\n    │\n251 │         if (block.timestamp > deadline) revert Expired();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:252:41\n    │\n252 │         if (amountIn == 0 || amountIn > uint256(uint128(type(int128).max))) revert InvalidSwap();\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/MarginaliaRouter.sol:252:49\n    │\n252 │         if (amountIn == 0 || amountIn > uint256(uint128(type(int128).max))) revert InvalidSwap();\n    │                                                 ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:338:9\n    │\n338 │         emit Noted(job.payer, job.sellMarg, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:320:18\n    │\n320 │                 -int256(job.amountIn),\n    │                  ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:328:25\n    │\n328 │         uint256 spent = uint256(uint128(-inputDelta));\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/MarginaliaRouter.sol:328:33\n    │\n328 │         uint256 spent = uint256(uint128(-inputDelta));\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:329:28\n    │\n329 │         uint256 received = uint256(uint128(outputDelta));\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/MarginaliaRouter.sol:329:36\n    │\n329 │         uint256 received = uint256(uint128(outputDelta));\n    │                                    ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:373:9\n    │\n373 │         emit XTraded(payer, X_V4, xIn, xOut, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:355:18\n    │\n355 │                 -int256(x.amountIn),\n    │                  ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:363:25\n    │\n363 │         uint256 spent = uint256(uint128(-inputDelta));\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/MarginaliaRouter.sol:363:33\n    │\n363 │         uint256 spent = uint256(uint128(-inputDelta));\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:364:20\n    │\n364 │         received = uint256(uint128(outputDelta));\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/MarginaliaRouter.sol:364:28\n    │\n364 │         received = uint256(uint128(outputDelta));\n    │                            ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:403:9\n    │\n403 │         emit XTraded(payer, X_V3, xIn, xOut, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:394:13\n    │\n394 │             int256(x.amountIn),\n    │             ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:399:25\n    │\n399 │         uint256 spent = uint256(zeroForOne ? a0 : a1);\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/MarginaliaRouter.sol:409:78\n    │\n409 │         if (amount0Delta > 0) IERC20(pool.token0()).safeTransfer(msg.sender, uint256(amount0Delta));\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/MarginaliaRouter.sol:410:78\n    │\n410 │         if (amount1Delta > 0) IERC20(pool.token1()).safeTransfer(msg.sender, uint256(amount1Delta));\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:438:9\n    │\n438 │         emit XTraded(payer, X_V2, xIn, xOut, actualIn, received);\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/MarginaliaRouter.sol:426:37\n    │\n426 │         (uint112 r0, uint112 r1,) = pair.getReserves();\n    │                                     ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:295:21\n    │\n295 │                 if (uint256(-params.amountSpecified) <= STAMP * 2) revert NoteTooSmall();\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/MarginaliaHook.sol:303:17\n    │\n303 │             if (uint256(-params.amountSpecified) <= depositMarg * 2) revert NoteTooSmall();\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/MarginaliaHook.sol:309:30\n    │\n309 │             specifiedTake = (uint256(params.amountSpecified) * bps + (10_000 - bps) - 1) / (10_000 - bps);\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:389:9\n    │\n389 │         emit Accrued(day, 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/MarginaliaHook.sol:463:9\n    │\n463 │ ┏         emit NotePosted(\n464 │ ┃             id,\n465 │ ┃             author,\n466 │ ┃             p.x,\n    ‡ ┃\n475 │ ┃             p.text\n476 │ ┃         );\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/MarginaliaHook.sol:341:13\n    │\n341 │             emit SwapFee(true, author, poolImd, 0, STAMP);\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/MarginaliaHook.sol:357:13\n    │\n357 │             emit SwapFee(false, author, poolImd, fee - STAMP, STAMP);\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/MarginaliaHook.sol:376:9\n    │\n376 │         emit SwapFee(false, tx.origin, poolImd, quietFee, 0);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:326:33\n    │\n326 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\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/MarginaliaHook.sol:326:41\n    │\n326 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\n    │                                         ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:326:63\n    │\n326 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\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/MarginaliaHook.sol:326:71\n    │\n326 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\n    │                                                                       ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:331:29\n    │\n331 │             uint256 netIn = uint256(-params.amountSpecified) - STAMP;\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/MarginaliaHook.sol:333:31\n    │\n333 │             uint256 margOut = uint256(uint128(margDelta));\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/MarginaliaHook.sol:333:39\n    │\n333 │             uint256 margOut = uint256(uint128(margDelta));\n    │                                       ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:366:25\n    │\n366 │             quietFee = (uint256(params.amountSpecified) * bps + (10_000 - bps) - 1) / (10_000 - bps);\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/MarginaliaHook.sol:367:28\n    │\n367 │             if (poolImd != uint256(params.amountSpecified) + quietFee) revert PartialFill();\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:449:17\n    │\n449 │             if (weekTheses[_week()].length >= MAX_WEEK_THESES) revert InvalidNote();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:441:22\n    │\n441 │         n.postedAt = uint64(block.timestamp);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe 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/MarginaliaHook.sol:497:13\n    │\n497 │         if (block.timestamp < end) revert TooEarly();\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/MarginaliaHook.sol:498:13\n    │\n498 │         if (block.timestamp > end + SETTLE_WINDOW) revert TooLate();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:511:9\n    │\n511 │         emit Observed(id, uint64(block.timestamp), xRead, quoteRead, balance);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:503:27\n    │\n503 │             T.Observation(uint64(block.timestamp), uint64(block.number), xRead, quoteRead, balance);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:503:52\n    │\n503 │             T.Observation(uint64(block.timestamp), uint64(block.number), xRead, quoteRead, balance);\n    │                                                    ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:511:27\n    │\n511 │         emit Observed(id, uint64(block.timestamp), xRead, quoteRead, balance);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[return-bomb]: external call with a gas limit may copy unbounded return data\n    ╭▸ src/MarginaliaHook.sol:519:13\n    │\n519 │             x.staticcall{gas: BALANCE_READ_GAS}(abi.encodeWithSelector(IERC20.balanceOf.selector, who));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/return-bomb\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaHook.sol:606:35\n    │\n606 │         emit Settled(id, outcome, settlePrice, scoreDelta, msg.sender);\n    │                                   ━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:556:13\n    │\n556 │         if (block.timestamp <= end + SETTLE_WINDOW) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:676:13\n    │\n676 │             emit ThesisReleased(n.parentId);\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/MarginaliaHook.sol:606:9\n    │\n606 │         emit Settled(id, outcome, settlePrice, scoreDelta, msg.sender);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:588:26\n    │\n588 │             scoreDelta = int256(_difficulty(n));\n    │                          ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:593:27\n    │\n593 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:595:27\n    │\n595 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:599:27\n    │\n599 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:614:13\n    │\n614 │         if (block.timestamp >= horizonEnd(id)) revert TooLate();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:623:9\n    │\n623 │         emit Retracted(id, text);\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/MarginaliaHook.sol:624:9\n    │\n624 │         emit Settled(id, T.Status.Retracted, 0, scoreDelta, address(0));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:616:30\n    │\n616 │         int256 scoreDelta = -int256(_difficulty(n) / 2);\n    │                              ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/MarginaliaHook.sol:632:13\n    │\n632 │         if (block.timestamp <= uint256(n.postedAt) + THESIS_GRACE) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:635:9\n    │\n635 │         emit ThesisForfeited(id);\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/MarginaliaHook.sol:653:9\n    │\n653 │         emit DepositClaimed(id, n.author, asImd, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:695:16\n    │\n695 │         return uint32(block.timestamp / 1 days);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:699:16\n    │\n699 │         return uint32(block.timestamp / 7 days);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:720:38\n    │\n720 │         uint256 prevPos = prev > 0 ? uint256(prev) : 0;\n    │                                      ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:721:38\n    │\n721 │         uint256 nextPos = next > 0 ? uint256(next) : 0;\n    │                                      ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:731:9\n    │\n731 │         emit PotFunded(_today(), amount, msg.sender);\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/MarginaliaHook.sol:743:9\n    │\n743 │         emit PotMargSold(amount, imdOut, _today());\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:763:27\n    │\n763 │         return (n.author, uint32(uint256(n.postedAt) / 7 days), n.targetBps == 0, n.children > 0);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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 `thesisPool` is updated\n    ╭▸ src/MarginaliaHook.sol:862:28\n    │\n862 │         bytes memory out = poolManager.unlock(data);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaHook.sol:862:28\n    │\n862 │         bytes memory out = poolManager.unlock(data);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:785:9\n    │\n785 │         emit JudgedPaid(w, paidAmounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/MarginaliaHook.sol:863:39\n    │\n863 │         if (unlockHash != bytes32(0)) revert InvalidUnlock();\n    │                                       ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:793:47\n    │\n793 │         uint256 share = FullMath.mulDiv(pool, uint256(s), weekTotal[w]);\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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:799:13\n    │\n799 │         if (w >= _week()) revert TooEarly();\n    │             ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:806:9\n    │\n806 │         emit LeaderboardClaimed(w, msg.sender, amount);\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/MarginaliaHook.sol:813:13\n    │\n813 │         if (n.day >= _today()) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:823:9\n    │\n823 │         emit RefundClaimed(id, msg.sender, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:821:30\n    │\n821 │         notesPerDay[n.day] = uint32(count - 1);\n    │                              ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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/MarginaliaHook.sol:832:17\n    │\n832 │             if (block.timestamp < (uint256(epoch) + 1) * 1 days + SWEEP_AFTER) revert TooEarly();\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/MarginaliaHook.sol:836:17\n    │\n836 │             if (block.timestamp < (uint256(epoch) + 1) * 7 days + SWEEP_AFTER) revert TooEarly();\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/MarginaliaHook.sol:840:17\n    │\n840 │             if (block.timestamp < (uint256(epoch) + 1) * 7 days + SWEEP_AFTER) revert TooEarly();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:873:40\n    │\n873 │             address currency = address(uint160(extra));\n    │                                        ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint160' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaHook.sol:882:13\n    │\n882 │             poolManager.settle();\n    │             ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:892:22\n    │\n892 │                     -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/MarginaliaHook.sol:901:17\n    │\n901 │             if (uint256(uint128(-margDelta)) != amount) revert InvalidUnlock();\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/MarginaliaHook.sol:901:25\n    │\n901 │             if (uint256(uint128(-margDelta)) != amount) revert InvalidUnlock();\n    │                         ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:903:30\n    │\n903 │             uint256 imdOut = uint256(uint128(imdDelta));\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/MarginaliaHook.sol:903:38\n    │\n903 │             uint256 imdOut = uint256(uint128(imdDelta));\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[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n   ╭▸ test/AuditFindings.t.sol:19:30\n   │\n19 │         uint256 startBlock = block.number;\n   │                              ━━━━━━━━━━━━\n   ‡\n23 │             vm.roll(startBlock + 25 * (i + 1));\n   │             ────────────────────────────────── `vm.roll` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockNumber()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/AuditFindings.t.sol:20:27\n   │\n20 │         uint256 startTs = block.timestamp;\n   │                           ━━━━━━━━━━━━━━━\n   ‡\n24 │             vm.warp(startTs + 31 minutes * (i + 1));\n   │             ─────────────────────────────────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/AuditFindings.t.sol:18:9\n    │\n 18 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/AuditFindings.t.sol:65:9\n    │\n 65 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/AuditFindings.t.sol:65:17\n   │\n65 │         vm.warp(block.timestamp + 7 days);\n   │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:130:9\n    │\n130 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:131:30\n    │\n131 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n135 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:132:27\n    │\n132 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n136 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:158:9\n    │\n158 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:159:30\n    │\n159 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n163 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:160:27\n    │\n160 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n164 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:182:9\n    │\n182 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:183:30\n    │\n183 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n187 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:184:27\n    │\n184 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n188 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:278:9\n    │\n278 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:278:17\n    │\n278 │         vm.warp(block.timestamp + 7 days);\n    │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:328:9\n    │\n328 │         vm.warp(hook.horizonEnd(a));\n    │         ─────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:329:30\n    │\n329 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n334 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:330:27\n    │\n330 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n335 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:408:9\n    │\n408 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:408:17\n    │\n408 │         vm.warp(block.timestamp + 7 days);\n    │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:475:9\n    │\n475 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:476:30\n    │\n476 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n479 │         vm.roll(startBlock + 25);\n    │         ──────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:477:27\n    │\n477 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n480 │         vm.warp(startTs + 30 minutes);\n    │         ───────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:499:9\n    │\n499 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:500:30\n    │\n500 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n504 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:501:27\n    │\n501 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n505 │             vm.warp(startTs + 10 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/RevisionFindings.t.sol:199:17\n    │\n199 │         vm.warp(block.timestamp + 1 hours);\n    │         ────────━━━━━━━━━━━━━━━─────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/RevisionFindings.t.sol:262:9\n    │\n262 │         vm.warp((uint256(w) + 1) * 7 days + 1);\n    │         ────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/Round3Findings.t.sol:67:17\n   │\n67 │         vm.warp(block.timestamp + 1 hours);\n   │         ────────━━━━━━━━━━━━━━━─────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\n","passed":true},{"durationMs":1113,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/fork/MainnetLaunch.t.sol:MainnetLaunchTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 500.71µs (0.00ns CPU time)\n\nRan 7 tests for test/JudgeOracle.t.sol:JudgeOracleTest\n[PASS] testEmptySignedRankingIsAnExecutableNoWinnerResult() (gas: 248153)\n[PASS] testFiveIdsWithEoaSignatureFitStipend() (gas: 554052)\n[PASS] testFullRankingWithEoaSignatureFitsStipend() (gas: 633672)\n[PASS] testProtocolDigestSignatureAndSelectorConformanceOnClone() (gas: 3322442)\n[PASS] testRejectedAnswersDoNotConsumeThePendingRequest() (gas: 892875)\n[PASS] testRequestedHeadIsFilteredAndDeduplicatedWithoutPromotingTheTail() (gas: 250679)\n[PASS] testTimeoutRetryInvalidatesOldIntakeRequest() (gas: 523953)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 9.57ms (8.29ms CPU time)\n\nRan 28 tests for test/CompanionFailures.t.sol:JudgeFailuresTest\n[PASS] testAJudgedWeekCannotBeAbandoned() (gas: 1257630)\n[PASS] testAbandonNeedsALiveRequestPastItsDeadline() (gas: 1190393)\n[PASS] testAbandonTakesNothingAndTheRetryDrawsAgain() (gas: 1467522)\n[PASS] testAnswerAtTheExactExpiryStillCountsAndOneSecondLaterDoesNot() (gas: 1257046)\n[PASS] testAnswerForAWeekAlreadyJudgedIsRefused() (gas: 1320679)\n[PASS] testAnswerSignedByAnotherKeyIsRefused() (gas: 1069433)\n[PASS] testAnswerSignedForAnotherConsumerIsRefused() (gas: 3952788)\n[PASS] testConvertForfeitsWithAnEmptyPotIsANoOp() (gas: 236930)\n[PASS] testConvertNeverSellsMoreThanThePot() (gas: 236488)\n[PASS] testConvertSellsTheLargestHalvingThePoolAbsorbs() (gas: 275386)\n[PASS] testConvertTriesExactlyNineTranchesDownToOneTwoHundredFiftySixth() (gas: 363686)\n[PASS] testCurrentAndFutureWeeksCannotBeRequested() (gas: 128617)\n[PASS] testEligibleThesesAreCappedAtTheJudgedMaximum() (gas: 14217218)\n[PASS] testImplementationHasAPlaceholderSignerAndCannotBeConfigured() (gas: 2726709)\n[PASS] testInitRequiresEveryConfigurationValue() (gas: 2953442)\n[PASS] testIntakeReturningAnIdAlreadyPendingIsRefused() (gas: 1599187)\n[PASS] testJudgedOfFiltersWrongWeekShortFormAndChildlessIds() (gas: 1439829)\n[PASS] testJudgedWeekCannotBeRequestedAgainEvenAfterTheDeadline() (gas: 1242650)\n[PASS] testMalformedAnswerBytesAreRefused() (gas: 1067354)\n[PASS] testOnlyTheHeadOfThreeIsStoredAndTheTailNeverPromotes() (gas: 1221812)\n[PASS] testPayBeforeAnAnswerReverts() (gas: 1064318)\n[PASS] testPayIsPermissionlessAndOnce() (gas: 1438634)\n[PASS] testQuestionBodyNamesTheConsumerChainAndEligibleIdsOnly() (gas: 2516225)\n[PASS] testRepeatRequestBeforeTheDeadlineIsRefused() (gas: 1419149)\n[PASS] testRequestDrawsExactlyThePriceAndKeepsNothing() (gas: 1028228)\n[PASS] testWeekClosedStates() (gas: 1940695)\n[PASS] testWeekWithoutEligibleThesesCannotBeRequested() (gas: 244665)\n[PASS] testZeroAndExcessiveOraclePricesAreRefused() (gas: 1345941)\nSuite result: ok. 28 passed; 0 failed; 0 skipped; finished in 35.97ms (24.03ms CPU time)\n\nRan 9 tests for test/CompanionFailures.t.sol:TreasuryFailuresTest\n[PASS] testDripFailsWhenTheHookCannotTakeTheFunds() (gas: 673929)\n[PASS] testDripIsPermissionlessAndCompounds() (gas: 518661)\n[PASS] testDripOfDustRoundsToZeroAndReverts() (gas: 258318)\n[PASS] testDripWithNothingHeldReverts() (gas: 54033)\n[PASS] testInitOnlyByTheNamedHookAndOnlyOnce() (gas: 623926)\n[PASS] testInitRefusesTheZeroHook() (gas: 556415)\n[PASS] testNoWithdrawOrAdminSurface() (gas: 274868)\n[PASS] testSecondDripOnTheSameDayRevertsAndTheNextDayWorks() (gas: 372660)\n[PASS] testTreasuryRefusesEth() (gas: 71164)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 69.44ms (1.78ms CPU time)\n\nRan 3 tests for test/Implementations.t.sol:ImplementationsTest\n[PASS] testClonesInitializeOnceOnlyFromTheirHook() (gas: 4551335)\n[PASS] testFactoryDeploysAllFourWithoutArgumentsOrExternalDependencies() (gas: 34608585)\nLogs:\n  four implementation CREATE2 deployments (gas): 8829579\n\n[PASS] testImplementationsRejectInitialization() (gas: 81376)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 77.18ms (40.51ms CPU time)\n\nRan 8 tests for test/PriceHistory.t.sol:PriceHistoryTest\n[PASS] testBaselineRequiresMatureFreshHistory() (gas: 188472)\n[PASS] testEmptyVenueAndHubCannotBeCheckpointedObservedOrPriced() (gas: 284549)\n[PASS] testFuzzV4BaselineIsNeverFavourableToTheCall(int24,bool) (runs: 256, μ: 106002, ~: 106150)\nLogs:\n  Bound result 4621\n\n[PASS] testHubBaselineUsesOppositeExtremeFromSettlement() (gas: 180334)\n[PASS] testLiveCheckpointCannotEraseHonestExtremesOrRestartTheClock() (gas: 224282)\n[PASS] testV2BaselineIgnoresSameBlockReservesDumpAndPumpBothOrientations() (gas: 467543)\n[PASS] testV3BaselineIgnoresSameBlockTickChangesBothOrientations() (gas: 418025)\n[PASS] testV3BaselineWeightsElapsedTime() (gas: 371037)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 77.25ms (78.88ms CPU time)\n\nRan 12 tests for test/HoldRule.t.sol:HoldRuleTest\n[PASS] testABreachIsNeverReplacedByANonBreachInsideTheGap() (gas: 1743076)\n[PASS] testABreachReplacesANonBreachInsideTheGap() (gas: 1753879)\n[PASS] testABuyCallWithAnUnreadableBalanceIsVoidSold() (gas: 1574310)\n[PASS] testASellAuthorMayDumpTheirWholeRemainingBalance() (gas: 1758901)\n[PASS] testASellAuthorWhoBuysBackTheirWholePostBalanceIsStillRight() (gas: 1869939)\n[PASS] testASellCallWithAnUnreadableBalanceStillSettlesOnPrice() (gas: 1641519)\n[PASS] testASellCallsBalanceIsNeverAnAdverseReading() (gas: 1443322)\n[PASS] testAWrongSellCallForfeitsWhateverTheBalanceDid() (gas: 1531765)\n[PASS] testAnEqualReadingInsideTheGapIsRefused() (gas: 1100844)\n[PASS] testAtTheCapAHigherReadingCannotLiftABuyCallsMinimum() (gas: 3998107)\n[PASS] testAtTheCapOnlyAMoreAdverseReadingGetsIn() (gas: 4267305)\n[PASS] testBuyCallHasNoToleranceDownwards() (gas: 1660272)\nSuite result: ok. 12 passed; 0 failed; 0 skipped; finished in 77.22ms (15.39ms CPU time)\n\nRan 14 tests for test/CompanionFailures.t.sol:RouterFailuresTest\n[PASS] testExpiredDeadlineTakesNothing() (gas: 736479)\n[PASS] testExpiredWindowRefusesPostsUntilAFreshCheckpointMatures() (gas: 1908222)\n[PASS] testInitRequiresAManagerWithCode() (gas: 4169863)\n[PASS] testSlippageFloorRefundsEverything() (gas: 708269)\n[PASS] testStrangersCannotEnterTheCallbacks() (gas: 133302)\n[PASS] testTradeAndNoteRefusesNoTradeZeroTradeAndNativeInput() (gas: 290819)\n[PASS] testTradedNoteMustBeAboutTheTokenTraded() (gas: 1059266)\n[PASS] testTradedV4LegUnderAForeignHookOrEmptyPoolIsRefused() (gas: 396313)\n[PASS] testUnapprovedOrUnfundedAuthorIsRefused() (gas: 224399)\n[PASS] testV4VenueUnderAForeignHookIsRefused() (gas: 69803)\n[PASS] testV4VenueWithoutLiquidityIsRefused() (gas: 135005)\n[PASS] testVenueFieldsAreDerivedFromThePoolNotTheCaller() (gas: 48665)\n[PASS] testVenueKindNoneIsRefusedForAPricedCall() (gas: 116335)\n[PASS] testZeroAndOversizedAmountsAreRefused() (gas: 138629)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 77.17ms (4.74ms CPU time)\n\nRan 7 tests for test/Pricer.t.sol:PricerTest\n[PASS] testQuoteLegIsAdverseEvenUnderAV3Twap() (gas: 28455)\n[PASS] testTwapRefusesZeroSpanAndV4() (gas: 17708)\n[PASS] testV2TwapFromWrappingCumulative() (gas: 9503)\n[PASS] testV3TwapOfAConstantTickIsThatTick() (gas: 15459)\n[PASS] testV3TwapRoundsNegativeMeansDown() (gas: 14848)\n[PASS] testV3TwapWeightsByTime() (gas: 14715)\n[PASS] testV4SettlesOnTheAdverseExtreme() (gas: 26636)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 77.28ms (586.31µs CPU time)\n\nRan 31 tests for test/PricerProperties.t.sol:PricerPropertiesTest\n[PASS] testDifficultyAnchors() (gas: 56436)\n[PASS] testDifficultyRefusesAZeroHorizon() (gas: 10063)\n[PASS] testDifficultyTiersStepExactlyAtTheThresholds() (gas: 79314)\n[PASS] testEmptyPoolsAreRefusedOnBothLegs() (gas: 161813)\n[PASS] testEthQuoteIsOnlyPriceableOnMainnet() (gas: 40894)\n[PASS] testFromSqrtRefusesAnEmptyOrUnpriceableReading() (gas: 53891)\n[PASS] testFromSqrtZeroThresholdIsSharpInBothOrientations() (gas: 1024182)\n[PASS] testFuzzAppendingAnObservationNeverHelpsTheCall(uint256[16],uint256[16],uint8) (runs: 1000, μ: 129854, ~: 113426)\nLogs:\n  Bound result 4\n  Bound result 536455059765039003450245451955\n  Bound result 610361688436193366688705381421\n  Bound result 622108149258335249994161473727\n  Bound result 154544360634\n  Bound result 285797903556266876299312797175\n  Bound result 999999999999999999999999999999\n  Bound result 210463424218\n  Bound result 279424103465255915804\n\n[PASS] testFuzzBuyDifficultyGrowsWithTheTarget(uint32,uint32,uint16,uint256) (runs: 1000, μ: 36902, ~: 36875)\nLogs:\n  Bound result 6870148\n  Bound result 9989079\n  Bound result 30\n  Bound result 933946457066679894660190384535\n\n[PASS] testFuzzCheckpointKeepsStartAndWidensExtremes(uint160,uint160,uint256) (runs: 512, μ: 141522, ~: 141856)\nLogs:\n  Bound result 347735535648662613654784219691\n  Bound result 1266412660188944021221806094248\n  Bound result 28798\n\n[PASS] testFuzzDifficultyFallsWithTheHorizon(uint32,uint16,uint16,uint256) (runs: 1000, μ: 36734, ~: 36871)\nLogs:\n  Bound result 244114\n  Bound result 6\n  Bound result 30\n  Bound result 933946457066679894660190384535\n\n[PASS] testFuzzFromSqrtIsMonotoneAndInverts(uint160,uint160) (runs: 1000, μ: 23273, ~: 21542)\nLogs:\n  Bound result 1461446703485210103287273052103988828087290338113\n  Bound result 103581848716553409699088278848732557927241\n\n[PASS] testFuzzLog2IsBracketedAndMonotone(uint256,uint256) (runs: 1000, μ: 39609, ~: 39295)\nLogs:\n  Bound result 4072899634061633\n  Bound result 4346332533580854924\n\n[PASS] testFuzzLog2IsExactAtPowersOfTwo(uint8) (runs: 512, μ: 16273, ~: 14721)\nLogs:\n  Bound result 1\n\n[PASS] testFuzzPostPriceWindowBoundaries(uint256,bool) (runs: 512, μ: 54136, ~: 51987)\nLogs:\n  Bound result 155\n\n[PASS] testFuzzSellDifficultyGrowsAsTheTargetFalls(uint32,uint32,uint16,uint256) (runs: 1000, μ: 36379, ~: 36369)\nLogs:\n  Bound result 151\n  Bound result 78\n  Bound result 30\n  Bound result 933946457066679894660190384535\n\n[PASS] testFuzzSqrtIsTheIntegerFloor(uint256) (runs: 1000, μ: 18753, ~: 16081)\n[PASS] testFuzzV2TwapOfAConstantRatioIsThatRatio(uint112,uint112,uint32,bool) (runs: 512, μ: 21370, ~: 21299)\nLogs:\n  Bound result 5192296858534827628530496329220095\n  Bound result 5192296858534827628530496329220095\n  Bound result 837\n\n[PASS] testFuzzV3SettlementIgnoresMiddleReadings(int24,uint256[16],uint8,bool) (runs: 512, μ: 63774, ~: 60292)\nLogs:\n  Bound result 2\n  Bound result 8\n\n[PASS] testFuzzV4SettlesOnTheExtremeOfEveryObservation(uint256[16],uint256[16],uint8) (runs: 1000, μ: 98960, ~: 83084)\nLogs:\n  Bound result 3\n  Bound result 415978906521570653435304214169\n  Bound result 3264592782\n  Bound result 1410\n  Bound result 33157\n  Bound result 84966997727330242082538205943\n  Bound result 600\n\n[PASS] testObserveRefusesUnknownVenuesAndUnpriceableQuotes() (gas: 150448)\n[PASS] testPostPriceRefusesAnEmptyWindow() (gas: 15317)\n[PASS] testPostPriceWhoseProductRoundsToZeroIsRefused() (gas: 293627)\n[PASS] testSellDifficultyRefusesAZeroTarget() (gas: 9518)\n[PASS] testSettlementRefusesAnEmptyOrUnspannedSeries() (gas: 39083)\n[PASS] testSqrtIsExactOnEveryHorizonDifficultyUses() (gas: 903275)\n[PASS] testSqrtPins() (gas: 123131)\n[PASS] testTwapRefusesTimeRunningBackwards() (gas: 9132)\n[PASS] testV2TwapAndSpotOfADustRatioAreRefused() (gas: 220677)\n[PASS] testV3TwapRefusesAMeanTickOutsideTheRange() (gas: 27255)\n[PASS] testV4SeriesWithADustExtremeIsRefusedNotSettledAtZero() (gas: 33519)\nSuite result: ok. 31 passed; 0 failed; 0 skipped; finished in 77.24ms (797.83ms CPU time)\n\nRan 10 tests for test/Round3Findings.t.sol:Round3FindingsTest\n[PASS] testABuyCallStillBreaksWhenTheAuthorSells() (gas: 1764134)\n[PASS] testAGiftOfAnySizeDoesNotVoidACorrectSellCall() (gas: 1710155)\n[PASS] testAGiftWorthTheDepositDoesNotVoidACorrectSellCall() (gas: 1810035)\n[PASS] testALaunchPoolCallStillScoresAndPaysTheLeaderboard() (gas: 1570750)\n[PASS] testASelfPricedVenueDrawsNothingFromTheLeaderboard() (gas: 2972803)\n[PASS] testAWrongCallOnAnotherVenueStillForfeitsButBooksNoScore() (gas: 2760625)\n[PASS] testAWrongSellCallStillForfeits() (gas: 1495739)\n[PASS] testFuzzSqrtIsTheIntegerFloor(uint256) (runs: 256, μ: 22774, ~: 20376)\n[PASS] testRetractingACallOnAnotherVenueBooksNoScore() (gas: 2004799)\n[PASS] testSqrtFloorsSmallInputs() (gas: 9204519)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 101.70ms (22.41ms CPU time)\n\nRan 26 tests for test/Lifecycle.t.sol:LifecycleTest\n[PASS] testAttestedClassCannotBeSelfDeclared() (gas: 343124)\n[PASS] testCallbackSelectorPinned() (gas: 3361)\n[PASS] testFakeVenueIsRefused() (gas: 382714)\n[PASS] testFlagsAndBinding() (gas: 55923)\n[PASS] testForfeitsConvertToImdForThePot() (gas: 1118696)\n[PASS] testLeaderboardProRataWithCap() (gas: 3247485)\n[PASS] testNoDataRefunds() (gas: 999702)\n[PASS] testNoteTooSmall() (gas: 173034)\n[PASS] testNotedBuyTakesStampAndDeposit() (gas: 798269)\n[PASS] testNotedSellPaysOnePercentPlusStamp() (gas: 1107534)\n[PASS] testObservationsMustSpanAnHour() (gas: 1494821)\n[PASS] testPlainBuyTakesNothing() (gas: 230288)\n[PASS] testQuietSellPaysThreePercent() (gas: 336561)\n[PASS] testQuietThesisPoolSweeps() (gas: 305757)\n[PASS] testRetract() (gas: 951734)\n[PASS] testRightCallReturnsDepositAsImd() (gas: 1804313)\n[PASS] testSellingEarlyBreaksTheCall() (gas: 1772740)\n[PASS] testThesisParentChild() (gas: 1515324)\n[PASS] testThesisWithoutChildForfeits() (gas: 796971)\n[PASS] testTreasuryDrip() (gas: 348158)\n[PASS] testTwoBlockPumpObserveUnwindSettlesWrong() (gas: 1804300)\n[PASS] testUnansweredWeekCanBeRetried() (gas: 2441273)\n[PASS] testUpOnlyIsRefused() (gas: 340732)\n[PASS] testWeeklyThesisJudging() (gas: 3855108)\n[PASS] testWriterRefundCappedAtStamp() (gas: 1717001)\n[PASS] testWrongCallForfeitsWithKeeperReward() (gas: 1562166)\nSuite result: ok. 26 passed; 0 failed; 0 skipped; finished in 109.53ms (22.74ms CPU time)\n\nRan 8 tests for test/AuditFindings.t.sol:AuditFindingsTest\n[PASS] testConversionAfterARealPriceFallNeedsAFreshMatureWindow() (gas: 2244515)\n[PASS] testEmptyV4ObservationIsRefused() (gas: 1028673)\n[PASS] testExpiredBaselineRejectsPostWithoutTakingFunds() (gas: 643517)\n[PASS] testForfeitureConversionRejectsSameBlockDump() (gas: 2224133)\n[PASS] testLongRankingFitsIntakeStipend() (gas: 2192588)\n[PASS] testSameBlockDumpPostUnwindDoesNotWinBuy() (gas: 1916921)\n[PASS] testSameBlockPumpPostUnwindDoesNotWinSell() (gas: 1785783)\n[PASS] testUnpayableRankingRollsTheWholePoolForward() (gas: 2465804)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 113.61ms (9.74ms CPU time)\n\nRan 10 tests for test/RevisionFindings.t.sol:RevisionFindingsTest\n[PASS] testABuyBackNoLongerVoidsASellCallItSettlesOnPrice() (gas: 1751715)\n[PASS] testADustPricedV4VenueCannotBePostedOn() (gas: 1635894)\n[PASS] testARevertingBalanceOfVoidsTheCallAsSoldNotAsNoData() (gas: 2639306)\n[PASS] testAStrangersDustTransferDoesNotVoidASellCall() (gas: 1695773)\n[PASS] testAnAttestationAboutAnotherChainIsRefused() (gas: 2324761)\n[PASS] testAnEmptyCanonicalV3PoolIsRefusedAsAVenue() (gas: 567946)\n[PASS] testHonestObserverOverwritesAPumpObserveUnwindInTheNextBlock() (gas: 3785409)\n[PASS] testPricerRefusesAPriceThatRoundsToZeroInBothOrientations() (gas: 58712)\n[PASS] testSweepNeedsTheStaleRequestAbandonedAndALateAnswerIsThenRefused() (gas: 2449618)\n[PASS] testTheHundredAndTwentyFirstThesisOfAWeekIsRefusedBeforePayment() (gas: 55395690)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 115.42ms (43.81ms CPU time)\n\nRan 2 tests for test/PotTranche.t.sol:PotTrancheTest\n[PASS] testForfeitedPotCanStillBeConvertedOnceItOutgrowsOneSale() (gas: 49910278)\nLogs:\n  potMarg: 36877975912613201326\n  imdOut: 10344028156678390861\n\n[PASS] testWhenNoTrancheSellsTheHookReasonSurfaces() (gas: 1266289)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 132.04ms (28.30ms CPU time)\n\nRan 1 test for test/RouterInvariant.t.sol:RouterInvariantTest\n[PASS]\nRouterInvariantTest invariants:\n[PASS] invariant_bindingsPinned\n[PASS] invariant_everyNoteCameThroughTheRouter\n[PASS] invariant_managerBacksTheHooksClaims\n[PASS] invariant_routerKeepsNothing\n RouterInvariantTest invariants (runs: 48, calls: 1920, reverts: 6)\n\n╭---------------+----------------+-------+---------+----------╮\n| Contract      | Selector       | Calls | Reverts | Discards |\n+=============================================================+\n| RouterHandler | advance        | 196   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | checkpoint     | 245   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | noteBuy        | 413   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | noteSell       | 229   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | plainBuy       | 226   | 6       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | plainSell      | 214   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | strayCallbacks | 198   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | thesis         | 199   | 0       | 0        |\n╰---------------+----------------+-------+---------+----------╯\n\nLogs:\n  Bound result 2\n  Bound result 751282172667661949861\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 300000\n  Bound result 4582\n  Bound result 0\n  Bound result 469426950\n  Bound result 13445\n  Bound result 77\n  Bound result 0\n  Bound result 5393\n  Bound result 46842\n  Bound result 96\n  Bound result 48\n  Bound result 1\n  Bound result 0\n  Bound result 1731687303715884105728\n  Bound result 50049\n  Bound result 2\n  Bound result 0\n  Bound result 4973889995611649343\n  Bound result 48490\n  Bound result 33\n  Bound result 16958\n  Bound result 1\n  Bound result 0\n  Bound result 500000000000000001\n  Bound result 51120\n  Bound result 77\n  Bound result 0\n  Bound result 1\n  Bound result 12500\n  Bound result 112\n  Bound result 27\n  Bound result 1\n  Bound result 4198\n  Bound result 1\n  Bound result 1581197094\n  Bound result 14937\n  Bound result 22\n  Bound result 0\n  Bound result 172746253684029974021\n  Bound result 38509\n  Bound result 4\n  Bound result 1\n  Bound result 311\n  Bound result 4903\n  Bound result 15\n  Bound result 0\n  Bound result 1\n  Bound result 10000000\n  Bound result 10001\n  Bound result 71\n  Bound result 20000000000000000000\n  Bound result 0\n  Bound result 0\n  Bound result 64\n  Bound result 1\n  Bound result 922335293464162364962\n  Bound result 10000\n  Bound result 69\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 20\n  Bound result 0\n  Bound result 3191\n  Bound result 51120\n  Bound result 27\n  Bound result 0\n  Bound result 11264\n  Bound result 0\n  Bound result 2\n  Bound result 53507506885370446792\n  Bound result 0\n  Bound result 8453\n  Bound result 0\n  Bound result 75475858034050927669300\n  Bound result 0\n  Bound result 9987258178627298350533\n  Bound result 2\n  Bound result 1130\n  Bound result 345\n  Bound result 60\n  Bound result 15361\n  Bound result 1\n  Bound result 2\n  Bound result 0\n  Bound result 1457584007913129639836\n  Bound result 18825\n  Bound result 98\n  Bound result 1\n  Bound result 316679010346293428347\n  Bound result 18598\n  Bound result 56\n  Bound result 1\n  Bound result 10190\n  Bound result 0\n  Bound result 2\n  Bound result 12511838043343513\n  Bound result 43605\n  Bound result 1\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 528.27ms (457.94ms CPU time)\n\nRan 1 test for test/TreasuryInvariant.t.sol:TreasuryInvariantTest\n[PASS]\nTreasuryInvariantTest invariants:\n[PASS] invariant_balanceIsGiftsMinusDrips\n[PASS] invariant_dripNeverExceedsTwoPercent\n[PASS] invariant_holdsNoEth\n[PASS] invariant_hookHoldsExactlyTheDrips\n[PASS] invariant_hookIsPinned\n[PASS] invariant_lastDripDayMatchesTheLastSuccessfulDrip\n TreasuryInvariantTest invariants (runs: 256, calls: 12288, reverts: 0)\n\n╭-----------------+-----------+-------+---------+----------╮\n| Contract        | Selector  | Calls | Reverts | Discards |\n+==========================================================+\n| TreasuryHandler | advance   | 2421  | 0       | 0        |\n|-----------------+-----------+-------+---------+----------|\n| TreasuryHandler | drip      | 2507  | 0       | 0        |\n|-----------------+-----------+-------+---------+----------|\n| TreasuryHandler | gift      | 2494  | 0       | 0        |\n|-----------------+-----------+-------+---------+----------|\n| TreasuryHandler | initAgain | 2421  | 0       | 0        |\n|-----------------+-----------+-------+---------+----------|\n| TreasuryHandler | sendEth   | 2445  | 0       | 0        |\n╰-----------------+-----------+-------+---------+----------╯\n\nLogs:\n  Bound result 1569824666248765321\n  Bound result 500000000000000000\n  Bound result 7\n  Bound result 5749\n  Bound result 56\n  Bound result 6819747615123204196\n  Bound result 1337181797\n  Bound result 2887634441604769804\n  Bound result 200\n  Bound result 128712398267185319455986162121619350587969857853\n  Bound result 644352895405360304141124\n  Bound result 167896\n  Bound result 123178971002\n  Bound result 647\n  Bound result 161127380233399419534214\n  Bound result 500000000000000000\n  Bound result 100000000000000000000000\n  Bound result 9367\n  Bound result 625\n  Bound result 119\n  Bound result 10000000000000000000\n  Bound result 27\n  Bound result 390\n  Bound result 7132168796771975168\n  Bound result 2279\n  Bound result 2219\n  Bound result 317913925943136366386884\n  Bound result 123894\n  Bound result 5912\n  Bound result 7599\n  Bound result 79228162514264337593543950336000000000\n  Bound result 857540799114289204183696\n  Bound result 12000\n  Bound result 1196\n  Bound result 81257132168796771935554\n  Bound result 440\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.01s (1.00s CPU time)\n\nRan 17 test suites in 1.01s (2.68s CPU time): 177 tests passed, 0 failed, 1 skipped (178 total tests)\n","passed":true},{"durationMs":106,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"Marginalia.approve(address,uint256)\",\"Marginalia.transfer(address,uint256)\",\"Marginalia.transferFrom(address,address,uint256)\",\"MarginaliaHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"MarginaliaHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"MarginaliaHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"MarginaliaHook.claimDeposit(bytes32,bool)\",\"MarginaliaHook.claimLeaderboard(uint32)\",\"MarginaliaHook.claimRefund(bytes32)\",\"MarginaliaHook.drawForJudging(uint32,uint256,bool)\",\"MarginaliaHook.fundPot(uint256)\",\"MarginaliaHook.observe(bytes32)\",\"MarginaliaHook.payJudged(uint32,bytes32[3])\",\"MarginaliaHook.retract(bytes32,string)\",\"MarginaliaHook.sellPotMarg(uint256)\",\"MarginaliaHook.settle(bytes32)\",\"MarginaliaHook.settleThesis(bytes32)\",\"MarginaliaHook.sweep(uint8,uint32)\",\"MarginaliaHook.unlockCallback(bytes)\",\"MarginaliaJudge.abandonRequest(uint32)\",\"MarginaliaJudge.convertForfeits()\",\"MarginaliaJudge.init(address,address,bytes32,address)\",\"MarginaliaJudge.onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"MarginaliaJudge.payJudged(uint32)\",\"MarginaliaJudge.requestJudging(uint32)\",\"MarginaliaRouter.checkpointVenue((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address))\",\"MarginaliaRouter.init(address,address)\",\"MarginaliaRouter.note((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address),uint256,uint256,uint256)\",\"MarginaliaRouter.sellWithNote((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address),uint256,uint256,uint256)\",\"MarginaliaRouter.uniswapV3SwapCallback(int256,int256,bytes)\",\"MarginaliaRouter.unlockCallback(bytes)\",\"MarginaliaTreasury.drip()\",\"MarginaliaTreasury.init(address)\"],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":215,\"README.md\":154,\"SPEC.md\":264,\"dependencies.json\":28,\"foundry.toml\":21,\"helper/.gitignore\":3,\"helper/package-lock.json\":737,\"helper/package.json\":20,\"helper/public/index.html\":82,\"helper/server.js\":90,\"helper/src/app.js\":203,\"jobs/launch-1-hook.json\":43,\"jobs/launch-2-contracts.json\":38,\"jobs/launch-A-implementations.json\":47,\"jobs/launch-A2-implementations.json\":41,\"jobs/launch-hook-v3.json\":43,\"remappings.txt\":4,\"src/HookFlags.sol\":33,\"src/Marginalia.sol\":12,\"src/MarginaliaHook.sol\":925,\"src/MarginaliaImpls.sol\":14,\"src/MarginaliaJudge.sol\":290,\"src/MarginaliaPricer.sol\":305,\"src/MarginaliaRouter.sol\":446,\"src/MarginaliaTreasury.sol\":53,\"src/MarginaliaTypes.sol\":108,\"src/OracleAttestation.sol\":221,\"src/interfaces/IIntake.sol\":15,\"src/interfaces/ILaunchFactory.sol\":49,\"test/AuditFindings.t.sol\":178,\"test/CompanionFailures.t.sol\":941,\"test/HoldRule.t.sol\":259,\"test/Implementations.t.sol\":96,\"test/JudgeOracle.t.sol\":270,\"test/Lifecycle.t.sol\":511,\"test/PotTranche.t.sol\":189,\"test/PriceHistory.t.sol\":233,\"test/Pricer.t.sol\":88,\"test/PricerProperties.t.sol\":569,\"test/RevisionFindings.t.sol\":318,\"test/Round3Findings.t.sol\":214,\"test/RouterInvariant.t.sol\":248,\"test/TreasuryInvariant.t.sol\":167,\"test/fork/MainnetLaunch.t.sol\":382,\"test/helpers/Fixture.sol\":278,\"test/mocks/MockERC20.sol\":13},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"5fd7e914a4ebb6bef97f84acff10bafe1ad6d8fe7181c5f251af57c7ad043542","verifiedTreeHash":"78ab7e39c0c0b97cae2754b3204d3160c85b579e","verifierVersion":"0.1.0+4ba55555"},{"checks":[{"durationMs":76424,"exitCode":0,"name":"build","output":"Compiling 108 files with Solc 0.8.26\nSolc 0.8.26 finished in 76.18s\nCompiler run successful with warnings:\nWarning (8760): This declaration has the same name as another declaration.\n   --> src/MarginaliaHook.sol:386:9:\n    |\n386 |         uint32 week = _week();\n    |         ^^^^^^^^^^^\nNote: The other declaration is here:\n   --> src/MarginaliaHook.sol:708:5:\n    |\n708 |     function week() external view returns (uint32) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:773:9:\n    |\n773 |         uint256 pool = thesisPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:93:5:\n   |\n93 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:794:9:\n    |\n794 |         uint256 pool = leaderboardPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:93:5:\n   |\n93 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2018): Function state mutability can be restricted to pure\n   --> test/helpers/Fixture.sol:114:5:\n    |\n114 |     function priceOf(bytes32, address) external view returns (uint256) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (2018): Function state mutability can be restricted to pure\n  --> test/fork/MainnetLaunch.t.sol:78:5:\n   |\n78 |     function _mine(bytes memory hookCode) internal view returns (bytes32 salt) {\n   |     ^ (Relevant source part starts here and spans across multiple lines).\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/MarginaliaTreasury.sol:51:9\n   │\n51 │         emit Dripped(day, amount);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/MarginaliaTreasury.sol:43:22\n   │\n43 │         uint32 day = uint32(block.timestamp / 1 days);\n   │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint32' is safe 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]: `jobHash` is changed without an event but is used for access control\n    ╭▸ src/MarginaliaRouter.sol:303:16\n    │\n303 │         delete jobHash;\n    │                ━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/MarginaliaHook.sol:78:38\n   │\n78 │     bytes32 public constant ACTION = bytes32(\"oracle.request@oracle-1\");\n   │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes32' is safe 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/MarginaliaHook.sol:196:44\n    │\n196 │     constructor(IPoolManager poolManager_, address token_, address factory_) {\n    │                                            ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/MarginaliaPricer.sol:85:13\n   │\n85 │             n += 1;\n   │             ━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaPricer.sol:119:33\n    │\n119 │         if (w.startedAt == 0 || block.timestamp > uint256(w.startedAt) + POST_MAX_AGE) {\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/MarginaliaRouter.sol:251:13\n    │\n251 │         if (block.timestamp > deadline) revert Expired();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:120:34\n    │\n120 │             return T.PriceWindow(uint64(block.timestamp), uint64(block.number), x, x, x, q, q);\n    │                                  ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:120:59\n    │\n120 │             return T.PriceWindow(uint64(block.timestamp), uint64(block.number), x, x, x, q, q);\n    │                                                           ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:252:41\n    │\n252 │         if (amountIn == 0 || amountIn > uint256(uint128(type(int128).max))) revert InvalidSwap();\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/MarginaliaRouter.sol:252:49\n    │\n252 │         if (amountIn == 0 || amountIn > uint256(uint128(type(int128).max))) revert InvalidSwap();\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/MarginaliaPricer.sol:141:20\n    │\n141 │                 || block.timestamp < uint256(w.startedAt) + POST_MIN_SPAN\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/MarginaliaPricer.sol:142:20\n    │\n142 │                 || block.timestamp > uint256(w.startedAt) + POST_MAX_AGE\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:148:69\n    │\n148 │             x = twap(v.kind, v.xIsToken0, w.xStart, w.startedAt, x, uint64(block.timestamp));\n    │                                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:167:55\n    │\n167 │         else if (v.kind == T.VenueKind.UniV3) xRead = uint256(_v3Cumulative(ref));\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/MarginaliaPricer.sol:212:28\n    │\n212 │             int256 delta = int256(c2) - int256(c1);\n    │                            ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:212:41\n    │\n212 │             int256 delta = int256(c2) - int256(c1);\n    │                                         ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:213:35\n    │\n213 │             int256 mean = delta / int256(dt);\n    │                                   ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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 `_status` is updated\n   ╭▸ src/MarginaliaJudge.sol:96:17\n   │\n96 │             try hook.sellPotMarg(marg) returns (uint256 out) {\n   │                 ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:214:38\n    │\n214 │             if (delta < 0 && delta % int256(dt) != 0) mean -= 1; // round toward negative infinity, as v3 does\n    │                                      ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:216:57\n    │\n216 │             return fromSqrt(TickMath.getSqrtPriceAtTick(int24(mean)), xIsToken0);\n    │                                                         ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int24' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[calls-loop]: external call inside a loop\n   ╭▸ src/MarginaliaJudge.sol:96:17\n   │\n96 │             try hook.sellPotMarg(marg) returns (uint256 out) {\n   │                 ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaPricer.sol:240:37\n    │\n240 │             (uint160 sqrtP,,,,,,) = IUniswapV3PoolOracle(ref).slot0();\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/MarginaliaPricer.sol:244:41\n    │\n244 │             (uint112 r0, uint112 r1,) = IUniswapV2PairOracle(ref).getReserves();\n    │                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:114:47\n    │\n114 │         for (uint256 i = 0; i < all.length && n < MAX_JUDGED; ++i) {\n    │                                               ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaJudge.sol:115:35\n    │\n115 │             (,,, bool hasChild) = hook.noteMeta(all[i]);\n    │                                   ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaPricer.sol:268:33\n    │\n268 │         (int56[] memory cum,) = IUniswapV3PoolOracle(pool).observe(ago);\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/MarginaliaJudge.sol:115:35\n    │\n115 │             (,,, bool hasChild) = hook.noteMeta(all[i]);\n    │                                   ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:278:24\n    │\n278 │         uint32 nowTs = uint32(block.timestamp);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:170:15\n    │\n170 │             ++n;\n    │               ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaJudge.sol:174:33\n    │\n174 │             out[i - 1] = bytes1(uint8(48 + v % 10));\n    │                                 ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaJudge.sol:186:52\n    │\n186 │         return eligibleTheses(week).length == 0 || block.timestamp >= (uint256(week) + 1) * 7 days + 28 days;\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/MarginaliaJudge.sol:194:32\n    │\n194 │         if (judgedSet[week] || block.timestamp < requestedAt[week] + ANSWER_DEADLINE) {\n    │                                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:338:9\n    │\n338 │         emit Noted(job.payer, job.sellMarg, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:320:18\n    │\n320 │                 -int256(job.amountIn),\n    │                  ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:328:25\n    │\n328 │         uint256 spent = uint256(uint128(-inputDelta));\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/MarginaliaRouter.sol:328:33\n    │\n328 │         uint256 spent = uint256(uint128(-inputDelta));\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:329:28\n    │\n329 │         uint256 received = uint256(uint128(outputDelta));\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/MarginaliaRouter.sol:329:36\n    │\n329 │         uint256 received = uint256(uint128(outputDelta));\n    │                                    ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:373:9\n    │\n373 │         emit XTraded(payer, X_V4, xIn, xOut, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:355:18\n    │\n355 │                 -int256(x.amountIn),\n    │                  ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:363:25\n    │\n363 │         uint256 spent = uint256(uint128(-inputDelta));\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/MarginaliaRouter.sol:363:33\n    │\n363 │         uint256 spent = uint256(uint128(-inputDelta));\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:364:20\n    │\n364 │         received = uint256(uint128(outputDelta));\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/MarginaliaRouter.sol:364:28\n    │\n364 │         received = uint256(uint128(outputDelta));\n    │                            ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:403:9\n    │\n403 │         emit XTraded(payer, X_V3, xIn, xOut, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:394:13\n    │\n394 │             int256(x.amountIn),\n    │             ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:399:25\n    │\n399 │         uint256 spent = uint256(zeroForOne ? a0 : a1);\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/MarginaliaRouter.sol:409:78\n    │\n409 │         if (amount0Delta > 0) IERC20(pool.token0()).safeTransfer(msg.sender, uint256(amount0Delta));\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/MarginaliaRouter.sol:410:78\n    │\n410 │         if (amount1Delta > 0) IERC20(pool.token1()).safeTransfer(msg.sender, uint256(amount1Delta));\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:438:9\n    │\n438 │         emit XTraded(payer, X_V2, xIn, xOut, actualIn, received);\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/MarginaliaRouter.sol:426:37\n    │\n426 │         (uint112 r0, uint112 r1,) = pair.getReserves();\n    │                                     ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `requestOf` is updated\n    ╭▸ src/MarginaliaJudge.sol:214:9\n    │\n214 │         hook.drawForJudging(day, price, retry);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `requestOf` is updated\n    ╭▸ src/MarginaliaJudge.sol:217:21\n    │\n217 │           requestId = intake.request(\n    │ ┏━━━━━━━━━━━━━━━━━━━━━┛\n218 │ ┃             action, body, IIntake.Callback(address(this), this.onOracleResult.selector), imd, price\n219 │ ┃         );\n    │ ┗━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaJudge.sol:206:41\n    │\n206 │         if (judgedSet[day] || (retry && block.timestamp < requestedAt[day] + ANSWER_DEADLINE)) {\n    │                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaJudge.sol:225:9\n    │\n225 │         emit Requested(day, requestId, price);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaJudge.sol:223:28\n    │\n223 │         requestedAt[day] = uint64(block.timestamp);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaJudge.sol:255:9\n    │\n255 │ ┏         emit Judged(\n256 │ ┃             day,\n257 │ ┃             [\n258 │ ┃                 count > 0 ? ranked[0] : bytes32(0),\n    ‡ ┃\n262 │ ┃         );\n    │ ┗━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:269:50\n    │\n269 │         for (uint256 i = 0; i < ranked.length && kept < 3; ++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/MarginaliaJudge.sol:276:17\n    │\n276 │             if (dup) continue;\n    │                 ━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaJudge.sol:270:77\n    │\n270 │             (address author, uint32 noteWeek, bool thesis, bool hasChild) = hook.noteMeta(ranked[i]);\n    │                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/MarginaliaJudge.sol:288:9\n    │\n288 │         hook.payJudged(day, top);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:298:21\n    │\n298 │                 if (uint256(-params.amountSpecified) <= STAMP * 2) revert NoteTooSmall();\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/MarginaliaHook.sol:306:17\n    │\n306 │             if (uint256(-params.amountSpecified) <= depositMarg * 2) revert NoteTooSmall();\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/MarginaliaHook.sol:312:30\n    │\n312 │             specifiedTake = (uint256(params.amountSpecified) * bps + (10_000 - bps) - 1) / (10_000 - bps);\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:392:9\n    │\n392 │         emit Accrued(day, 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/MarginaliaHook.sol:466:9\n    │\n466 │ ┏         emit NotePosted(\n467 │ ┃             id,\n468 │ ┃             author,\n469 │ ┃             p.x,\n    ‡ ┃\n478 │ ┃             p.text\n479 │ ┃         );\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/MarginaliaHook.sol:344:13\n    │\n344 │             emit SwapFee(true, author, poolImd, 0, STAMP);\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/MarginaliaHook.sol:360:13\n    │\n360 │             emit SwapFee(false, author, poolImd, fee - STAMP, STAMP);\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/MarginaliaHook.sol:379:9\n    │\n379 │         emit SwapFee(false, tx.origin, poolImd, quietFee, 0);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:329:33\n    │\n329 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\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/MarginaliaHook.sol:329:41\n    │\n329 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\n    │                                         ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:329:63\n    │\n329 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\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/MarginaliaHook.sol:329:71\n    │\n329 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\n    │                                                                       ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:334:29\n    │\n334 │             uint256 netIn = uint256(-params.amountSpecified) - STAMP;\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/MarginaliaHook.sol:336:31\n    │\n336 │             uint256 margOut = uint256(uint128(margDelta));\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/MarginaliaHook.sol:336:39\n    │\n336 │             uint256 margOut = uint256(uint128(margDelta));\n    │                                       ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:369:25\n    │\n369 │             quietFee = (uint256(params.amountSpecified) * bps + (10_000 - bps) - 1) / (10_000 - bps);\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/MarginaliaHook.sol:370:28\n    │\n370 │             if (poolImd != uint256(params.amountSpecified) + quietFee) revert PartialFill();\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:452:17\n    │\n452 │             if (weekTheses[_week()].length >= MAX_WEEK_THESES) revert InvalidNote();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:444:22\n    │\n444 │         n.postedAt = uint64(block.timestamp);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe 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/MarginaliaHook.sol:500:13\n    │\n500 │         if (block.timestamp < end) revert TooEarly();\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/MarginaliaHook.sol:501:13\n    │\n501 │         if (block.timestamp > end + SETTLE_WINDOW) revert TooLate();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:514:9\n    │\n514 │         emit Observed(id, uint64(block.timestamp), xRead, quoteRead, balance);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:506:27\n    │\n506 │             T.Observation(uint64(block.timestamp), uint64(block.number), xRead, quoteRead, balance);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:506:52\n    │\n506 │             T.Observation(uint64(block.timestamp), uint64(block.number), xRead, quoteRead, balance);\n    │                                                    ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:514:27\n    │\n514 │         emit Observed(id, uint64(block.timestamp), xRead, quoteRead, balance);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[return-bomb]: external call with a gas limit may copy unbounded return data\n    ╭▸ src/MarginaliaHook.sol:522:13\n    │\n522 │             x.staticcall{gas: BALANCE_READ_GAS}(abi.encodeWithSelector(IERC20.balanceOf.selector, who));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/return-bomb\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaHook.sol:612:35\n    │\n612 │         emit Settled(id, outcome, settlePrice, scoreDelta, msg.sender);\n    │                                   ━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:562:13\n    │\n562 │         if (block.timestamp <= end + SETTLE_WINDOW) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:682:13\n    │\n682 │             emit ThesisReleased(n.parentId);\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/MarginaliaHook.sol:612:9\n    │\n612 │         emit Settled(id, outcome, settlePrice, scoreDelta, msg.sender);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:594:26\n    │\n594 │             scoreDelta = int256(_difficulty(n));\n    │                          ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:599:27\n    │\n599 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:601:27\n    │\n601 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:605:27\n    │\n605 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:620:13\n    │\n620 │         if (block.timestamp >= horizonEnd(id)) revert TooLate();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:629:9\n    │\n629 │         emit Retracted(id, text);\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/MarginaliaHook.sol:630:9\n    │\n630 │         emit Settled(id, T.Status.Retracted, 0, scoreDelta, address(0));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:622:30\n    │\n622 │         int256 scoreDelta = -int256(_difficulty(n) / 2);\n    │                              ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/MarginaliaHook.sol:638:13\n    │\n638 │         if (block.timestamp <= uint256(n.postedAt) + THESIS_GRACE) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:641:9\n    │\n641 │         emit ThesisForfeited(id);\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/MarginaliaHook.sol:659:9\n    │\n659 │         emit DepositClaimed(id, n.author, asImd, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:697:16\n    │\n697 │         return uint32(block.timestamp / 1 days);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:701:16\n    │\n701 │         return uint32(block.timestamp / 7 days);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:722:38\n    │\n722 │         uint256 prevPos = prev > 0 ? uint256(prev) : 0;\n    │                                      ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:723:38\n    │\n723 │         uint256 nextPos = next > 0 ? uint256(next) : 0;\n    │                                      ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:733:9\n    │\n733 │         emit PotFunded(_today(), amount, msg.sender);\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/MarginaliaHook.sol:745:9\n    │\n745 │         emit PotMargSold(amount, imdOut, _today());\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:765:27\n    │\n765 │         return (n.author, uint32(uint256(n.postedAt) / 7 days), n.targetBps == 0, n.children > 0);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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 `thesisPool` is updated\n    ╭▸ src/MarginaliaHook.sol:864:28\n    │\n864 │         bytes memory out = poolManager.unlock(data);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaHook.sol:864:28\n    │\n864 │         bytes memory out = poolManager.unlock(data);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:787:9\n    │\n787 │         emit JudgedPaid(w, paidAmounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/MarginaliaHook.sol:865:39\n    │\n865 │         if (unlockHash != bytes32(0)) revert InvalidUnlock();\n    │                                       ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:795:47\n    │\n795 │         uint256 share = FullMath.mulDiv(pool, uint256(s), weekTotal[w]);\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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:801:13\n    │\n801 │         if (w >= _week()) revert TooEarly();\n    │             ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:808:9\n    │\n808 │         emit LeaderboardClaimed(w, msg.sender, amount);\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/MarginaliaHook.sol:815:13\n    │\n815 │         if (n.day >= _today()) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:825:9\n    │\n825 │         emit RefundClaimed(id, msg.sender, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:823:30\n    │\n823 │         notesPerDay[n.day] = uint32(count - 1);\n    │                              ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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/MarginaliaHook.sol:834:17\n    │\n834 │             if (block.timestamp < (uint256(epoch) + 1) * 1 days + SWEEP_AFTER) revert TooEarly();\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/MarginaliaHook.sol:838:17\n    │\n838 │             if (block.timestamp < (uint256(epoch) + 1) * 7 days + SWEEP_AFTER) revert TooEarly();\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/MarginaliaHook.sol:842:17\n    │\n842 │             if (block.timestamp < (uint256(epoch) + 1) * 7 days + SWEEP_AFTER) revert TooEarly();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:875:40\n    │\n875 │             address currency = address(uint160(extra));\n    │                                        ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint160' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaHook.sol:884:13\n    │\n884 │             poolManager.settle();\n    │             ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:894:22\n    │\n894 │                     -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/MarginaliaHook.sol:903:17\n    │\n903 │             if (uint256(uint128(-margDelta)) != amount) revert InvalidUnlock();\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/MarginaliaHook.sol:903:25\n    │\n903 │             if (uint256(uint128(-margDelta)) != amount) revert InvalidUnlock();\n    │                         ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:905:30\n    │\n905 │             uint256 imdOut = uint256(uint128(imdDelta));\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/MarginaliaHook.sol:905:38\n    │\n905 │             uint256 imdOut = uint256(uint128(imdDelta));\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[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n   ╭▸ test/AuditFindings.t.sol:19:30\n   │\n19 │         uint256 startBlock = block.number;\n   │                              ━━━━━━━━━━━━\n   ‡\n23 │             vm.roll(startBlock + 25 * (i + 1));\n   │             ────────────────────────────────── `vm.roll` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockNumber()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/AuditFindings.t.sol:20:27\n   │\n20 │         uint256 startTs = block.timestamp;\n   │                           ━━━━━━━━━━━━━━━\n   ‡\n24 │             vm.warp(startTs + 31 minutes * (i + 1));\n   │             ─────────────────────────────────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/AuditFindings.t.sol:18:9\n    │\n 18 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/AuditFindings.t.sol:65:9\n    │\n 65 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/AuditFindings.t.sol:65:17\n   │\n65 │         vm.warp(block.timestamp + 7 days);\n   │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:130:9\n    │\n130 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:131:30\n    │\n131 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n135 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:132:27\n    │\n132 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n136 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:158:9\n    │\n158 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:159:30\n    │\n159 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n163 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:160:27\n    │\n160 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n164 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:182:9\n    │\n182 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:183:30\n    │\n183 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n187 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:184:27\n    │\n184 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n188 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:278:9\n    │\n278 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:278:17\n    │\n278 │         vm.warp(block.timestamp + 7 days);\n    │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:328:9\n    │\n328 │         vm.warp(hook.horizonEnd(a));\n    │         ─────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:329:30\n    │\n329 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n334 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:330:27\n    │\n330 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n335 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:408:9\n    │\n408 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:408:17\n    │\n408 │         vm.warp(block.timestamp + 7 days);\n    │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:475:9\n    │\n475 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:476:30\n    │\n476 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n479 │         vm.roll(startBlock + 25);\n    │         ──────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:477:27\n    │\n477 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n480 │         vm.warp(startTs + 30 minutes);\n    │         ───────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:499:9\n    │\n499 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:500:30\n    │\n500 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n504 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:501:27\n    │\n501 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n505 │             vm.warp(startTs + 10 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/RevisionFindings.t.sol:197:17\n    │\n197 │         vm.warp(block.timestamp + 1 hours);\n    │         ────────━━━━━━━━━━━━━━━─────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/RevisionFindings.t.sol:258:9\n    │\n258 │         vm.warp((uint256(w) + 1) * 7 days + 1);\n    │         ────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\n","passed":true},{"durationMs":167,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/fork/MainnetLaunch.t.sol:MainnetLaunchTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 569.06µs (0.00ns CPU time)\n\nRan 7 tests for test/Pricer.t.sol:PricerTest\n[PASS] testQuoteLegIsAdverseEvenUnderAV3Twap() (gas: 28455)\n[PASS] testTwapRefusesZeroSpanAndV4() (gas: 17708)\n[PASS] testV2TwapFromWrappingCumulative() (gas: 9503)\n[PASS] testV3TwapOfAConstantTickIsThatTick() (gas: 15459)\n[PASS] testV3TwapRoundsNegativeMeansDown() (gas: 14848)\n[PASS] testV3TwapWeightsByTime() (gas: 14715)\n[PASS] testV4SettlesOnTheAdverseExtreme() (gas: 26636)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 763.55µs (853.86µs CPU time)\n\nRan 7 tests for test/JudgeOracle.t.sol:JudgeOracleTest\n[PASS] testEmptySignedRankingIsAnExecutableNoWinnerResult() (gas: 248153)\n[PASS] testFiveIdsWithEoaSignatureFitStipend() (gas: 554052)\n[PASS] testFullRankingWithEoaSignatureFitsStipend() (gas: 633672)\n[PASS] testProtocolDigestSignatureAndSelectorConformanceOnClone() (gas: 3322442)\n[PASS] testRejectedAnswersDoNotConsumeThePendingRequest() (gas: 892875)\n[PASS] testRequestedHeadIsFilteredAndDeduplicatedWithoutPromotingTheTail() (gas: 250679)\n[PASS] testTimeoutRetryInvalidatesOldIntakeRequest() (gas: 523953)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 2.56ms (7.18ms CPU time)\n\nRan 8 tests for test/PriceHistory.t.sol:PriceHistoryTest\n[PASS] testBaselineRequiresMatureFreshHistory() (gas: 188472)\n[PASS] testEmptyVenueAndHubCannotBeCheckpointedObservedOrPriced() (gas: 284549)\n[PASS] testFuzzV4BaselineIsNeverFavourableToTheCall(int24,bool) (runs: 256, μ: 106089, ~: 106143)\nLogs:\n  Bound result 17624\n\n[PASS] testHubBaselineUsesOppositeExtremeFromSettlement() (gas: 180334)\n[PASS] testLiveCheckpointCannotEraseHonestExtremesOrRestartTheClock() (gas: 224282)\n[PASS] testV2BaselineIgnoresSameBlockReservesDumpAndPumpBothOrientations() (gas: 467543)\n[PASS] testV3BaselineIgnoresSameBlockTickChangesBothOrientations() (gas: 418025)\n[PASS] testV3BaselineWeightsElapsedTime() (gas: 371037)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 9.45ms (10.65ms CPU time)\n\nRan 8 tests for test/AuditFindings.t.sol:AuditFindingsTest\n[PASS] testConversionAfterARealPriceFallNeedsAFreshMatureWindow() (gas: 2239771)\n[PASS] testEmptyV4ObservationIsRefused() (gas: 1022543)\n[PASS] testExpiredBaselineRejectsPostWithoutTakingFunds() (gas: 643715)\n[PASS] testForfeitureConversionRejectsSameBlockDump() (gas: 2218773)\n[PASS] testLongRankingFitsIntakeStipend() (gas: 2193239)\n[PASS] testSameBlockDumpPostUnwindDoesNotWinBuy() (gas: 1914995)\n[PASS] testSameBlockPumpPostUnwindDoesNotWinSell() (gas: 1787168)\n[PASS] testUnpayableRankingRollsTheWholePoolForward() (gas: 2466565)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 16.75ms (9.39ms CPU time)\n\nRan 26 tests for test/Lifecycle.t.sol:LifecycleTest\n[PASS] testAttestedClassCannotBeSelfDeclared() (gas: 343256)\n[PASS] testCallbackSelectorPinned() (gas: 3361)\n[PASS] testFakeVenueIsRefused() (gas: 382780)\n[PASS] testFlagsAndBinding() (gas: 55989)\n[PASS] testForfeitsConvertToImdForThePot() (gas: 1112852)\n[PASS] testLeaderboardProRataWithCap() (gas: 3243602)\n[PASS] testNoDataRefunds() (gas: 993629)\n[PASS] testNoteTooSmall() (gas: 173144)\n[PASS] testNotedBuyTakesStampAndDeposit() (gas: 798665)\n[PASS] testNotedSellPaysOnePercentPlusStamp() (gas: 1108348)\n[PASS] testObservationsMustSpanAnHour() (gas: 1488779)\n[PASS] testPlainBuyTakesNothing() (gas: 230618)\n[PASS] testQuietSellPaysThreePercent() (gas: 336869)\n[PASS] testQuietThesisPoolSweeps() (gas: 306043)\n[PASS] testRetract() (gas: 945582)\n[PASS] testRightCallReturnsDepositAsImd() (gas: 1802343)\n[PASS] testSellingEarlyBreaksTheCall() (gas: 1770726)\n[PASS] testThesisParentChild() (gas: 1509361)\n[PASS] testThesisWithoutChildForfeits() (gas: 797205)\n[PASS] testTreasuryDrip() (gas: 348364)\n[PASS] testTwoBlockPumpObserveUnwindSettlesWrong() (gas: 1802286)\n[PASS] testUnansweredWeekCanBeRetried() (gas: 2442021)\n[PASS] testUpOnlyIsRefused() (gas: 340864)\n[PASS] testWeeklyThesisJudging() (gas: 3856451)\n[PASS] testWriterRefundCappedAtStamp() (gas: 1711148)\n[PASS] testWrongCallForfeitsWithKeeperReward() (gas: 1560130)\nSuite result: ok. 26 passed; 0 failed; 0 skipped; finished in 27.42ms (25.96ms CPU time)\n\nRan 3 tests for test/Implementations.t.sol:ImplementationsTest\n[PASS] testClonesInitializeOnceOnlyFromTheirHook() (gas: 4551335)\n[PASS] testFactoryDeploysAllFourWithoutArgumentsOrExternalDependencies() (gas: 34594277)\nLogs:\n  four implementation CREATE2 deployments (gas): 8826312\n\n[PASS] testImplementationsRejectInitialization() (gas: 81376)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 49.83ms (50.67ms CPU time)\n\nRan 2 tests for test/PotTranche.t.sol:PotTrancheTest\n[PASS] testForfeitedPotCanStillBeConvertedOnceItOutgrowsOneSale() (gas: 49410352)\nLogs:\n  potMarg: 36877975912613201326\n  imdOut: 10344028156678390861\n\n[PASS] testWhenNoTrancheSellsTheHookReasonSurfaces() (gas: 1260643)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 52.97ms (35.26ms CPU time)\n\nRan 10 tests for test/RevisionFindings.t.sol:RevisionFindingsTest\n[PASS] testADustPricedV4VenueCannotBePostedOn() (gas: 1636136)\n[PASS] testARealBuyBackStillVoidsASellCall() (gas: 1791662)\n[PASS] testARevertingBalanceOfVoidsTheCallAsSoldNotAsNoData() (gas: 2678007)\n[PASS] testAStrangersDustTransferDoesNotVoidASellCall() (gas: 1697092)\n[PASS] testAnAttestationAboutAnotherChainIsRefused() (gas: 2325368)\n[PASS] testAnEmptyCanonicalV3PoolIsRefusedAsAVenue() (gas: 567990)\n[PASS] testHonestObserverOverwritesAPumpObserveUnwindInTheNextBlock() (gas: 3783793)\n[PASS] testPricerRefusesAPriceThatRoundsToZeroInBothOrientations() (gas: 58727)\n[PASS] testSweepNeedsTheStaleRequestAbandonedAndALateAnswerIsThenRefused() (gas: 2450533)\n[PASS] testTheHundredAndTwentyFirstThesisOfAWeekIsRefusedBeforePayment() (gas: 55411706)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 59.04ms (39.39ms CPU time)\n\nRan 9 test suites in 60.01ms (219.34ms CPU time): 71 tests passed, 0 failed, 1 skipped (72 total tests)\n","passed":true},{"durationMs":67,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"Marginalia.approve(address,uint256)\",\"Marginalia.transfer(address,uint256)\",\"Marginalia.transferFrom(address,address,uint256)\",\"MarginaliaHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"MarginaliaHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"MarginaliaHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"MarginaliaHook.claimDeposit(bytes32,bool)\",\"MarginaliaHook.claimLeaderboard(uint32)\",\"MarginaliaHook.claimRefund(bytes32)\",\"MarginaliaHook.drawForJudging(uint32,uint256,bool)\",\"MarginaliaHook.fundPot(uint256)\",\"MarginaliaHook.observe(bytes32)\",\"MarginaliaHook.payJudged(uint32,bytes32[3])\",\"MarginaliaHook.retract(bytes32,string)\",\"MarginaliaHook.sellPotMarg(uint256)\",\"MarginaliaHook.settle(bytes32)\",\"MarginaliaHook.settleThesis(bytes32)\",\"MarginaliaHook.sweep(uint8,uint32)\",\"MarginaliaHook.unlockCallback(bytes)\",\"MarginaliaJudge.abandonRequest(uint32)\",\"MarginaliaJudge.convertForfeits()\",\"MarginaliaJudge.init(address,address,bytes32,address)\",\"MarginaliaJudge.onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"MarginaliaJudge.payJudged(uint32)\",\"MarginaliaJudge.requestJudging(uint32)\",\"MarginaliaRouter.checkpointVenue((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address))\",\"MarginaliaRouter.init(address,address)\",\"MarginaliaRouter.note((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address),uint256,uint256,uint256)\",\"MarginaliaRouter.sellWithNote((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address),uint256,uint256,uint256)\",\"MarginaliaRouter.uniswapV3SwapCallback(int256,int256,bytes)\",\"MarginaliaRouter.unlockCallback(bytes)\",\"MarginaliaTreasury.drip()\",\"MarginaliaTreasury.init(address)\"],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":179,\"README.md\":143,\"SPEC.md\":263,\"dependencies.json\":28,\"foundry.toml\":21,\"helper/.gitignore\":3,\"helper/package-lock.json\":737,\"helper/package.json\":20,\"helper/public/index.html\":82,\"helper/server.js\":90,\"helper/src/app.js\":203,\"jobs/launch-1-hook.json\":43,\"jobs/launch-2-contracts.json\":38,\"jobs/launch-A-implementations.json\":47,\"jobs/launch-A2-implementations.json\":41,\"jobs/launch-hook-v3.json\":43,\"remappings.txt\":4,\"src/HookFlags.sol\":33,\"src/Marginalia.sol\":12,\"src/MarginaliaHook.sol\":927,\"src/MarginaliaImpls.sol\":14,\"src/MarginaliaJudge.sol\":290,\"src/MarginaliaPricer.sol\":304,\"src/MarginaliaRouter.sol\":446,\"src/MarginaliaTreasury.sol\":53,\"src/MarginaliaTypes.sol\":108,\"src/OracleAttestation.sol\":221,\"src/interfaces/IIntake.sol\":15,\"src/interfaces/ILaunchFactory.sol\":49,\"test/AuditFindings.t.sol\":178,\"test/Implementations.t.sol\":96,\"test/JudgeOracle.t.sol\":270,\"test/Lifecycle.t.sol\":511,\"test/PotTranche.t.sol\":189,\"test/PriceHistory.t.sol\":233,\"test/Pricer.t.sol\":88,\"test/RevisionFindings.t.sol\":314,\"test/fork/MainnetLaunch.t.sol\":382,\"test/helpers/Fixture.sol\":278,\"test/mocks/MockERC20.sol\":13},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":11958,"exitCode":0,"name":"slither","output":"[high/medium] weak-prng at src/MarginaliaPricer.sol:204: MarginaliaPricer.twap(MarginaliaTypes.VenueKind,bool,uint256,uint64,uint256,uint64) (src/MarginaliaPricer.sol#204-228) uses a weak PRNG: \"delta < 0 && delta % int256(dt) != 0 (src/MarginaliaPricer.sol#214)\"\n[high/medium] reentrancy-balance at src/MarginaliaRouter.sol:414: Reentrancy in MarginaliaRouter._tradeV2(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#414-439):\n[high/medium] reentrancy-balance at src/MarginaliaRouter.sol:414: Reentrancy in MarginaliaRouter._tradeV2(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#414-439):\n[high/medium] reentrancy-balance at src/MarginaliaRouter.sol:377: Reentrancy in MarginaliaRouter._tradeV3(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#377-404):\n[high/medium] reentrancy-balance at src/MarginaliaRouter.sol:377: Reentrancy in MarginaliaRouter._tradeV3(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#377-404):\n[high/medium] reentrancy-balance at src/MarginaliaRouter.sol:414: Reentrancy in MarginaliaRouter._tradeV2(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#414-439):\n[high/medium] reentrancy-balance at src/MarginaliaRouter.sol:287: Reentrancy in MarginaliaRouter._pull(address,uint256) (src/MarginaliaRouter.sol#287-292):\n[high/high] uninitialized-state at src/MarginaliaHook.sol:496: MarginaliaHook.observations (src/MarginaliaHook.sol#100) is never initialized. It is used in:\n[medium/high] incorrect-equality at src/MarginaliaHook.sol:800: MarginaliaHook.claimLeaderboard(uint32) (src/MarginaliaHook.sol#800-809) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaHook.sol:530: MarginaliaHook._broken(MarginaliaTypes.Note,uint256) (src/MarginaliaHook.sol#530-537) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:377: MarginaliaRouter._tradeV3(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#377-404) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaPricer.sol:134: MarginaliaPricer.postPrice(IPoolManager,MarginaliaTypes.Venue,address,bool,MarginaliaTypes.PriceWindow) (src/MarginaliaPricer.sol#134-154) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:414: MarginaliaRouter._tradeV2(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#414-439) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaPricer.sol:294: MarginaliaPricer.fromSqrt(uint160,bool) (src/MarginaliaPricer.sol#294-303) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:299: MarginaliaRouter.unlockCallback(bytes) (src/MarginaliaRouter.sol#299-340) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:294: MarginaliaRouter._checkSubject(MarginaliaRouter.Job) (src/MarginaliaRouter.sol#294-297) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaPricer.sol:294: MarginaliaPricer.fromSqrt(uint160,bool) (src/MarginaliaPricer.sol#294-303) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaPricer.sol:204: MarginaliaPricer.twap(MarginaliaTypes.VenueKind,bool,uint256,uint64,uint256,uint64) (src/MarginaliaPricer.sol#204-228) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaHook.sol:831: MarginaliaHook.sweep(uint8,uint32) (src/MarginaliaHook.sol#831-850) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:287: MarginaliaRouter._pull(address,uint256) (src/MarginaliaRouter.sol#287-292) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaTreasury.sol:42: MarginaliaTreasury.drip() (src/MarginaliaTreasury.sol#42-52) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaPricer.sol:294: MarginaliaPricer.fromSqrt(uint160,bool) (src/MarginaliaPricer.sol#294-303) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaTreasury.sol:42: MarginaliaTreasury.drip() (src/MarginaliaTreasury.sol#42-52) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaPricer.sol:175: MarginaliaPricer.settlePrice(MarginaliaTypes.Venue,bool,MarginaliaTypes.Observation[]) (src/MarginaliaPricer.sol#175-200) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaHook.sol:858: MarginaliaHook._unlock(uint8,address,uint256,uint256) (src/MarginaliaHook.sol#858-867) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:414: MarginaliaRouter._tradeV2(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#414-439) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:242: MarginaliaRouter._run(bool,uint256,uint256,uint256,MarginaliaRouter.XTrade,MarginaliaTypes.NoteParams,PoolKey) (src/MarginaliaRouter.sol#242-284) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaHook.sol:406: MarginaliaHook._postNote(address,MarginaliaTypes.NoteParams,uint256,uint256,uint256) (src/MarginaliaHook.sol#406-480) uses a dangerous strict equality:\n[medium/medium] reentrancy-no-eth at src/MarginaliaHook.sol:616: Reentrancy in MarginaliaHook.retract(bytes32,string) (src/MarginaliaHook.sol#616-631):\n[medium/medium] reentrancy-no-eth at src/MarginaliaHook.sol:769: Reentrancy in MarginaliaHook.payJudged(uint32,bytes32[3]) (src/MarginaliaHook.sol#769-788):\n[medium/medium] reentrancy-no-eth at src/MarginaliaHook.sol:558: Reentrancy in MarginaliaHook.settle(bytes32) (src/MarginaliaHook.sol#558-613):\n[medium/medium] reentrancy-no-eth at src/MarginaliaJudge.sol:203: Reentrancy in MarginaliaJudge.requestJudging(uint32) (src/MarginaliaJudge.sol#203-226):\n[medium/medium] uninitialized-local at src/MarginaliaRouter.sol:179: MarginaliaRouter.sellWithNote(MarginaliaTypes.NoteParams,PoolKey,uint256,uint256,uint256).noX (src/MarginaliaRouter.sol#179) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaJudge.sol:127: MarginaliaJudge.questionBody(uint32).allow (src/MarginaliaJudge.sol#127) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaHook.sol:566: MarginaliaHook.settle(bytes32).settlePrice (src/MarginaliaHook.sol#566) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaRouter.sol:166: MarginaliaRouter.note(MarginaliaTypes.NoteParams,PoolKey,uint256,uint256,uint256).noX (src/MarginaliaRouter.sol#166) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaRouter.sol:257: MarginaliaRouter._run(bool,uint256,uint256,uint256,MarginaliaRouter.XTrade,MarginaliaTypes.NoteParams,PoolKey).job (src/MarginaliaRouter.sol#257) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaJudge.sol:113: MarginaliaJudge.eligibleTheses(uint32).n (src/MarginaliaJudge.sol#113) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaRouter.sol:205: MarginaliaRouter.validateVenue(MarginaliaTypes.NoteParams,PoolKey).t1 (src/MarginaliaRouter.sol#205) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaJudge.sol:272: MarginaliaJudge.judgedOf(uint32).dup (src/MarginaliaJudge.sol#272) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaJudge.sol:268: MarginaliaJudge.judgedOf(uint32).kept (src/MarginaliaJudge.sol#268) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaHook.sol:776: MarginaliaHook.payJudged(uint32,bytes32[3]).paidAmounts (src/MarginaliaHook.sol#776) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaJudge.sol:168: MarginaliaJudge._dec(uint256).n (src/MarginaliaJudge.sol#168) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaRouter.sol:204: MarginaliaRouter.validateVenue(MarginaliaTypes.NoteParams,PoolKey).t0 (src/MarginaliaRouter.sol#204) is a local variable never initialized\n[medium/medium] unused-return at src/MarginaliaPricer.sol:232: MarginaliaPricer._spotInQuote(IPoolManager,MarginaliaTypes.Venue) (src/MarginaliaPricer.sol#232-251) ignores return value by (r0,r1,None) = IUniswapV2PairOracle(ref).getReserves() (src/MarginaliaPricer.sol#244)\n[medium/medium] unused-return at src/MarginaliaHook.sol:280: MarginaliaHook.margPriceInImd() (src/MarginaliaHook.sol#280-283) ignores return value by (sqrtP,None,None,None) = poolManager.getSlot0(poolId) (src/MarginaliaHook.sol#281)\n[medium/medium] unused-return at src/MarginaliaPricer.sol:254: MarginaliaPricer._quoteSpot(IPoolManager,address,address) (src/MarginaliaPricer.sol#254-263) ignores return value by (sqrtP,None,None,None) = manager.getSlot0(PoolId.wrap(HUB_POOL_ID)) (src/MarginaliaPricer.sol#259)\n[medium/medium] unused-return at src/MarginaliaPricer.sol:266: MarginaliaPricer._v3Cumulative(address) (src/MarginaliaPricer.sol#266-270) ignores return value by (cum,None) = IUniswapV3PoolOracle(pool).observe(ago) (src/MarginaliaPricer.sol#268)\n[medium/medium] unused-return at src/MarginaliaHook.sol:869: MarginaliaHook.unlockCallback(bytes) (src/MarginaliaHook.sol#869-915) ignores return value by poolManager.settle() (src/MarginaliaHook.sol#884)\n[medium/medium] unused-return at src/MarginaliaJudge.sol:110: MarginaliaJudge.eligibleTheses(uint32) (src/MarginaliaJudge.sol#110-122) ignores return value by (None,None,None,hasChild) = hook.noteMeta(all[i]) (src/MarginaliaJudge.sol#115)\n[medium/medium] unused-return at src/MarginaliaRouter.sol:414: MarginaliaRouter._tradeV2(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#414-439) ignores return value by (r0,r1,None) = pair.getReserves() (src/MarginaliaRouter.sol#426)\n[medium/medium] unused-return at src/MarginaliaPricer.sol:232: MarginaliaPricer._spotInQuote(IPoolManager,MarginaliaTypes.Venue) (src/MarginaliaPricer.sol#232-251) ignores return value by (sqrtP_scope_0,None,None,None,None,None,None) = IUniswapV3PoolOracle(ref).slot0() (src/MarginaliaPricer.sol#240)\n[medium/medium] unused-return at src/MarginaliaPricer.sol:232: MarginaliaPricer._spotInQuote(IPoolManager,MarginaliaTypes.Venue) (src/MarginaliaPricer.sol#232-251) ignores return value by (sqrtP,None,None,None) = manager.getSlot0(PoolId.wrap(v.ref)) (src/MarginaliaPricer.sol#236)\n[low/high] shadowing-local at src/MarginaliaHook.sol:794: MarginaliaHook.leaderboardShare(uint32,address).pool (src/MarginaliaHook.sol#794) shadows:\n[low/high] shadowing-local at src/MarginaliaHook.sol:773: MarginaliaHook.payJudged(uint32,bytes32[3]).pool (src/MarginaliaHook.sol#773) shadows:\n[low/high] shadowing-local at src/MarginaliaHook.sol:708: MarginaliaHook._accrue(uint256).week (src/MarginaliaHook.sol#386) shadows:\n[low/high] shadowing-local at src/MarginaliaJudge.sol:14: IHookJudge.noteMeta(bytes32).week (src/MarginaliaJudge.sol#19) shadows:\n[low/high] shadowing-local at src/MarginaliaJudge.sol:14: IHookJudge.thesesOfWeek(uint32).week (src/MarginaliaJudge.sol#15) shadows:\n[low/high] shadowing-local at src/MarginaliaJudge.sol:14: IHookJudge.thesisPool(uint32).week (src/MarginaliaJudge.sol#12) shadows:\n[low/high] shadowing-local at src/MarginaliaJudge.sol:14: IHookJudge.drawForJudging(uint32,uint256,bool).week (src/MarginaliaJudge.sol#21) shadows:\n[low/medium] calls-loop at src/MarginaliaJudge.sol:110: MarginaliaJudge.eligibleTheses(uint32) (src/MarginaliaJudge.sol#110-122) has external calls inside a loop: (None,None,None,hasChild) = hook.noteMeta(all[i]) (src/MarginaliaJudge.sol#115)\n[low/medium] calls-loop at src/MarginaliaJudge.sol:110: MarginaliaJudge.eligibleTheses(uint32) (src/MarginaliaJudge.sol#110-122) has external calls inside a loop: (None,None,None,hasChild) = hook.noteMeta(all[i]) (src/MarginaliaJudge.sol#115)\n[low/medium] calls-loop at src/MarginaliaJudge.sol:266: MarginaliaJudge.judgedOf(uint32) (src/MarginaliaJudge.sol#266-279) has external calls inside a loop: (author,noteWeek,thesis,hasChild) = hook.noteMeta(ranked[i]) (src/MarginaliaJudge.sol#270)\n[low/medium] calls-loop at src/MarginaliaHook.sol:858: MarginaliaHook._unlock(uint8,address,uint256,uint256) (src/MarginaliaHook.sol#858-867) has external calls inside a loop: out = poolManager.unlock(data) (src/MarginaliaHook.sol#864)\n[low/medium] calls-loop at src/MarginaliaJudge.sol:91: MarginaliaJudge.convertForfeits() (src/MarginaliaJudge.sol#91-106) has external calls inside a loop: out = hook.sellPotMarg(marg) (src/MarginaliaJudge.sol#96-100)\n[low/medium] calls-loop at src/MarginaliaJudge.sol:266: MarginaliaJudge.judgedOf(uint32) (src/MarginaliaJudge.sol#266-279) has external calls inside a loop: (author,noteWeek,thesis,hasChild) = hook.noteMeta(ranked[i]) (src/MarginaliaJudge.sol#270)\n[low/medium] calls-loop at src/MarginaliaJudge.sol:110: MarginaliaJudge.eligibleTheses(uint32) (src/MarginaliaJudge.sol#110-122) has external calls inside a loop: (None,None,None,hasChild) = hook.noteMeta(all[i]) (src/MarginaliaJudge.sol#115)\n[low/medium] calls-loop at src/MarginaliaJudge.sol:110: MarginaliaJudge.eligibleTheses(uint32) (src/MarginaliaJudge.sol#110-122) has external calls inside a loop: (None,None,None,hasChild) = hook.noteMeta(all[i]) (src/MarginaliaJudge.sol#115)\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:317: Reentrancy in MarginaliaHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/MarginaliaHook.sol#317-381):\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:317: Reentrancy in MarginaliaHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/MarginaliaHook.sol#317-381):\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:558: Reentrancy in MarginaliaHook.settle(bytes32) (src/MarginaliaHook.sol#558-613):\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:728: Reentrancy in MarginaliaHook.fundPot(uint256) (src/MarginaliaHook.sol#728-734):\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:317: Reentrancy in MarginaliaHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/MarginaliaHook.sol#317-381):\n[low/medium] reentrancy-benign at src/MarginaliaRouter.sol:377: Reentrancy in MarginaliaRouter._tradeV3(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#377-404):\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:667: Reentrancy in MarginaliaHook._forfeit(MarginaliaTypes.Note,address) (src/MarginaliaHook.sol#667-674):\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:737: Reentrancy in MarginaliaHook.sellPotMarg(uint256) (src/MarginaliaHook.sol#737-746):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:634: Reentrancy in MarginaliaHook.settleThesis(bytes32) (src/MarginaliaHook.sol#634-642):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:645: Reentrancy in MarginaliaHook.claimDeposit(bytes32,bool) (src/MarginaliaHook.sol#645-660):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:616: Reentrancy in MarginaliaHook.retract(bytes32,string) (src/MarginaliaHook.sol#616-631):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:728: Reentrancy in MarginaliaHook.fundPot(uint256) (src/MarginaliaHook.sol#728-734):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:800: Reentrancy in MarginaliaHook.claimLeaderboard(uint32) (src/MarginaliaHook.sol#800-809):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:769: Reentrancy in MarginaliaHook.payJudged(uint32,bytes32[3]) (src/MarginaliaHook.sol#769-788):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:812: Reentrancy in MarginaliaHook.claimRefund(bytes32) (src/MarginaliaHook.sol#812-826):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:317: Reentrancy in MarginaliaHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/MarginaliaHook.sol#317-381):\n[low/medium] reentrancy-events at","passed":true},{"durationMs":805,"exitCode":0,"name":"aderyn","output":"[high] eth-send-unchecked-address at src/MarginaliaHook.sol:728: ETH transferred without address checks (3 places)\n[high] reentrancy-state-change at src/MarginaliaHook.sol:210: Reentrancy: State change after external call (14 places)\n[high] storage-array-memory-edit at src/MarginaliaHook.sol:509: Storage Array Edited with Memory\n[low] costly-loop at src/MarginaliaHook.sol:778: Costly operations inside loop (2 places)\n[low] internal-function-used-once at src/HookFlags.sol:26: Internal Function Used Only Once (2 places)\n[low] large-numeric-literal at src/Marginalia.sol:10: Large Numeric Literal (24 places)\n[low] literal-instead-of-constant at src/MarginaliaHook.sol:305: Literal Instead of Constant (64 places)\n[low] local-variable-shadowing at src/MarginaliaHook.sol:773: Local Variable Shadows State Variable (2 places)\n[low] require-revert-in-loop at src/MarginaliaHook.sol:571: Loop Contains `require`/`revert` (2 places)\n[low] state-change-without-event at src/MarginaliaHook.sol:285: State Change Without Event (7 places)\n[low] state-no-address-check at src/MarginaliaRouter.sol:135: Address State Variable Set Without Checks\n[low] unchecked-return at src/MarginaliaHook.sol:655: Unchecked Return (8 places)\n[low] uninitialized-local-variable at src/MarginaliaJudge.sol:168: Uninitialized Local Variable (2 places)","passed":true},{"durationMs":15356,"exitCode":0,"name":"proof 70ce87bf5dd7","output":"Compiling 100 files with Solc 0.8.26\nSolc 0.8.26 finished in 14.59s\nCompiler run successful with warnings:\nWarning (8760): This declaration has the same name as another declaration.\n   --> src/MarginaliaHook.sol:386:9:\n    |\n386 |         uint32 week = _week();\n    |         ^^^^^^^^^^^\nNote: The other declaration is here:\n   --> src/MarginaliaHook.sol:708:5:\n    |\n708 |     function week() external view returns (uint32) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:773:9:\n    |\n773 |         uint256 pool = thesisPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:93:5:\n   |\n93 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:794:9:\n    |\n794 |         uint256 pool = leaderboardPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:93:5:\n   |\n93 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2018): Function state mutability can be restricted to pure\n   --> test/helpers/Fixture.sol:114:5:\n    |\n114 |     function priceOf(bytes32, address) external view returns (uint256) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\n\nRan 1 test for test/imd-proof-04a0ebfd/Proof_70ce87bf5dd7.t.sol:PotStrandedProof\n[PASS] testForfeitedPotCanStillBeConvertedOnceItOutgrowsOneSale() (gas: 48620125)\nLogs:\n  potMarg: 36877975912613201326\n  imdOut: 10344028156678390861\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 46.75ms (28.61ms CPU time)\n\nRan 1 test suite in 47.82ms (46.75ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)\n","passed":true},{"durationMs":6852,"exitCode":0,"name":"proof 4772e72bc17c","output":"2026-10-10T15:17:14.329142Z ERROR foundry_compilers_artifacts_solc::sources: error=\"/tmp/imd-verify-3qpqgt/repo/test/imd-proof-04a0ebfd/Proof_70ce87bf5dd7.t.sol\": No such file or directory (os error 2)\nCompiling 1 files with Solc 0.8.26\nSolc 0.8.26 finished in 6.24s\nCompiler run successful!\n\nRan 1 test for test/imd-proof-8c4680ac/Proof_4772e72bc17c.t.sol:ZeroPriceProofTest\n[PASS] testAPricedCallNeverGetsAZeroBaselineOrSettlement() (gas: 27169)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 993.74µs (54.89µs CPU time)\n\nRan 1 test suite in 3.68ms (993.74µs CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"65027068ed4a04582788addea6f2097c3e16ed56d979b045d04a362957c04a90","verifiedTreeHash":"b920980a8199ae3becb7c7c30b7758464481260f","verifierVersion":"0.1.0+fdeb4d4a"},{"checks":[{"durationMs":133223,"exitCode":0,"name":"build","output":"Compiling 113 files with Solc 0.8.26\nSolc 0.8.26 finished in 132.96s\nCompiler run successful with warnings:\nWarning (8760): This declaration has the same name as another declaration.\n   --> src/MarginaliaHook.sol:386:9:\n    |\n386 |         uint32 week = _week();\n    |         ^^^^^^^^^^^\nNote: The other declaration is here:\n   --> src/MarginaliaHook.sol:708:5:\n    |\n708 |     function week() external view returns (uint32) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:773:9:\n    |\n773 |         uint256 pool = thesisPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:93:5:\n   |\n93 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:794:9:\n    |\n794 |         uint256 pool = leaderboardPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:93:5:\n   |\n93 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2018): Function state mutability can be restricted to pure\n   --> test/helpers/Fixture.sol:114:5:\n    |\n114 |     function priceOf(bytes32, address) external view returns (uint256) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (2018): Function state mutability can be restricted to pure\n  --> test/fork/MainnetLaunch.t.sol:78:5:\n   |\n78 |     function _mine(bytes memory hookCode) internal view returns (bytes32 salt) {\n   |     ^ (Relevant source part starts here and spans across multiple lines).\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/MarginaliaTreasury.sol:51:9\n   │\n51 │         emit Dripped(day, amount);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/MarginaliaTreasury.sol:43:22\n   │\n43 │         uint32 day = uint32(block.timestamp / 1 days);\n   │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint32' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/MarginaliaPricer.sol:85:13\n   │\n85 │             n += 1;\n   │             ━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaPricer.sol:119:33\n    │\n119 │         if (w.startedAt == 0 || block.timestamp > uint256(w.startedAt) + POST_MAX_AGE) {\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:120:34\n    │\n120 │             return T.PriceWindow(uint64(block.timestamp), uint64(block.number), x, x, x, q, q);\n    │                                  ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:120:59\n    │\n120 │             return T.PriceWindow(uint64(block.timestamp), uint64(block.number), x, x, x, q, q);\n    │                                                           ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe 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/MarginaliaPricer.sol:141:20\n    │\n141 │                 || block.timestamp < uint256(w.startedAt) + POST_MIN_SPAN\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/MarginaliaPricer.sol:142:20\n    │\n142 │                 || block.timestamp > uint256(w.startedAt) + POST_MAX_AGE\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:148:69\n    │\n148 │             x = twap(v.kind, v.xIsToken0, w.xStart, w.startedAt, x, uint64(block.timestamp));\n    │                                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:167:55\n    │\n167 │         else if (v.kind == T.VenueKind.UniV3) xRead = uint256(_v3Cumulative(ref));\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 `_status` is updated\n   ╭▸ src/MarginaliaJudge.sol:96:17\n   │\n96 │             try hook.sellPotMarg(marg) returns (uint256 out) {\n   │                 ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n   ╭▸ src/MarginaliaJudge.sol:96:17\n   │\n96 │             try hook.sellPotMarg(marg) returns (uint256 out) {\n   │                 ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:114:47\n    │\n114 │         for (uint256 i = 0; i < all.length && n < MAX_JUDGED; ++i) {\n    │                                               ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaJudge.sol:115:35\n    │\n115 │             (,,, bool hasChild) = hook.noteMeta(all[i]);\n    │                                   ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaJudge.sol:115:35\n    │\n115 │             (,,, bool hasChild) = hook.noteMeta(all[i]);\n    │                                   ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:212:28\n    │\n212 │             int256 delta = int256(c2) - int256(c1);\n    │                            ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:212:41\n    │\n212 │             int256 delta = int256(c2) - int256(c1);\n    │                                         ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:213:35\n    │\n213 │             int256 mean = delta / int256(dt);\n    │                                   ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:214:38\n    │\n214 │             if (delta < 0 && delta % int256(dt) != 0) mean -= 1; // round toward negative infinity, as v3 does\n    │                                      ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:216:57\n    │\n216 │             return fromSqrt(TickMath.getSqrtPriceAtTick(int24(mean)), xIsToken0);\n    │                                                         ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int24' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:170:15\n    │\n170 │             ++n;\n    │               ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaJudge.sol:174:33\n    │\n174 │             out[i - 1] = bytes1(uint8(48 + v % 10));\n    │                                 ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/MarginaliaHook.sol:78:38\n   │\n78 │     bytes32 public constant ACTION = bytes32(\"oracle.request@oracle-1\");\n   │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes32' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaPricer.sol:240:37\n    │\n240 │             (uint160 sqrtP,,,,,,) = IUniswapV3PoolOracle(ref).slot0();\n    │                                     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaJudge.sol:186:52\n    │\n186 │         return eligibleTheses(week).length == 0 || block.timestamp >= (uint256(week) + 1) * 7 days + 28 days;\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/MarginaliaPricer.sol:244:41\n    │\n244 │             (uint112 r0, uint112 r1,) = IUniswapV2PairOracle(ref).getReserves();\n    │                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaJudge.sol:194:32\n    │\n194 │         if (judgedSet[week] || block.timestamp < requestedAt[week] + ANSWER_DEADLINE) {\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/MarginaliaPricer.sol:268:33\n    │\n268 │         (int56[] memory cum,) = IUniswapV3PoolOracle(pool).observe(ago);\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/MarginaliaHook.sol:196:44\n    │\n196 │     constructor(IPoolManager poolManager_, address token_, address factory_) {\n    │                                            ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:278:24\n    │\n278 │         uint32 nowTs = uint32(block.timestamp);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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 `requestOf` is updated\n    ╭▸ src/MarginaliaJudge.sol:214:9\n    │\n214 │         hook.drawForJudging(day, price, retry);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `requestOf` is updated\n    ╭▸ src/MarginaliaJudge.sol:217:21\n    │\n217 │           requestId = intake.request(\n    │ ┏━━━━━━━━━━━━━━━━━━━━━┛\n218 │ ┃             action, body, IIntake.Callback(address(this), this.onOracleResult.selector), imd, price\n219 │ ┃         );\n    │ ┗━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaJudge.sol:206:41\n    │\n206 │         if (judgedSet[day] || (retry && block.timestamp < requestedAt[day] + ANSWER_DEADLINE)) {\n    │                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaJudge.sol:225:9\n    │\n225 │         emit Requested(day, requestId, price);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaJudge.sol:223:28\n    │\n223 │         requestedAt[day] = uint64(block.timestamp);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaJudge.sol:255:9\n    │\n255 │ ┏         emit Judged(\n256 │ ┃             day,\n257 │ ┃             [\n258 │ ┃                 count > 0 ? ranked[0] : bytes32(0),\n    ‡ ┃\n262 │ ┃         );\n    │ ┗━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:269:50\n    │\n269 │         for (uint256 i = 0; i < ranked.length && kept < 3; ++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/MarginaliaJudge.sol:276:17\n    │\n276 │             if (dup) continue;\n    │                 ━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaJudge.sol:270:77\n    │\n270 │             (address author, uint32 noteWeek, bool thesis, bool hasChild) = hook.noteMeta(ranked[i]);\n    │                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/MarginaliaJudge.sol:288:9\n    │\n288 │         hook.payJudged(day, top);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[missing-events-access-control]: `jobHash` is changed without an event but is used for access control\n    ╭▸ src/MarginaliaRouter.sol:303:16\n    │\n303 │         delete jobHash;\n    │                ━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaRouter.sol:251:13\n    │\n251 │         if (block.timestamp > deadline) revert Expired();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:252:41\n    │\n252 │         if (amountIn == 0 || amountIn > uint256(uint128(type(int128).max))) revert InvalidSwap();\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/MarginaliaRouter.sol:252:49\n    │\n252 │         if (amountIn == 0 || amountIn > uint256(uint128(type(int128).max))) revert InvalidSwap();\n    │                                                 ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:338:9\n    │\n338 │         emit Noted(job.payer, job.sellMarg, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:320:18\n    │\n320 │                 -int256(job.amountIn),\n    │                  ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:328:25\n    │\n328 │         uint256 spent = uint256(uint128(-inputDelta));\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/MarginaliaRouter.sol:328:33\n    │\n328 │         uint256 spent = uint256(uint128(-inputDelta));\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:329:28\n    │\n329 │         uint256 received = uint256(uint128(outputDelta));\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/MarginaliaRouter.sol:329:36\n    │\n329 │         uint256 received = uint256(uint128(outputDelta));\n    │                                    ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:373:9\n    │\n373 │         emit XTraded(payer, X_V4, xIn, xOut, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:355:18\n    │\n355 │                 -int256(x.amountIn),\n    │                  ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:363:25\n    │\n363 │         uint256 spent = uint256(uint128(-inputDelta));\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/MarginaliaRouter.sol:363:33\n    │\n363 │         uint256 spent = uint256(uint128(-inputDelta));\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:364:20\n    │\n364 │         received = uint256(uint128(outputDelta));\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/MarginaliaRouter.sol:364:28\n    │\n364 │         received = uint256(uint128(outputDelta));\n    │                            ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:403:9\n    │\n403 │         emit XTraded(payer, X_V3, xIn, xOut, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:394:13\n    │\n394 │             int256(x.amountIn),\n    │             ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:399:25\n    │\n399 │         uint256 spent = uint256(zeroForOne ? a0 : a1);\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/MarginaliaRouter.sol:409:78\n    │\n409 │         if (amount0Delta > 0) IERC20(pool.token0()).safeTransfer(msg.sender, uint256(amount0Delta));\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/MarginaliaRouter.sol:410:78\n    │\n410 │         if (amount1Delta > 0) IERC20(pool.token1()).safeTransfer(msg.sender, uint256(amount1Delta));\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:438:9\n    │\n438 │         emit XTraded(payer, X_V2, xIn, xOut, actualIn, received);\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/MarginaliaRouter.sol:426:37\n    │\n426 │         (uint112 r0, uint112 r1,) = pair.getReserves();\n    │                                     ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:298:21\n    │\n298 │                 if (uint256(-params.amountSpecified) <= STAMP * 2) revert NoteTooSmall();\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/MarginaliaHook.sol:306:17\n    │\n306 │             if (uint256(-params.amountSpecified) <= depositMarg * 2) revert NoteTooSmall();\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/MarginaliaHook.sol:312:30\n    │\n312 │             specifiedTake = (uint256(params.amountSpecified) * bps + (10_000 - bps) - 1) / (10_000 - bps);\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:392:9\n    │\n392 │         emit Accrued(day, 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/MarginaliaHook.sol:466:9\n    │\n466 │ ┏         emit NotePosted(\n467 │ ┃             id,\n468 │ ┃             author,\n469 │ ┃             p.x,\n    ‡ ┃\n478 │ ┃             p.text\n479 │ ┃         );\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/MarginaliaHook.sol:344:13\n    │\n344 │             emit SwapFee(true, author, poolImd, 0, STAMP);\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/MarginaliaHook.sol:360:13\n    │\n360 │             emit SwapFee(false, author, poolImd, fee - STAMP, STAMP);\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/MarginaliaHook.sol:379:9\n    │\n379 │         emit SwapFee(false, tx.origin, poolImd, quietFee, 0);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:329:33\n    │\n329 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\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/MarginaliaHook.sol:329:41\n    │\n329 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\n    │                                         ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:329:63\n    │\n329 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\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/MarginaliaHook.sol:329:71\n    │\n329 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\n    │                                                                       ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:334:29\n    │\n334 │             uint256 netIn = uint256(-params.amountSpecified) - STAMP;\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/MarginaliaHook.sol:336:31\n    │\n336 │             uint256 margOut = uint256(uint128(margDelta));\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/MarginaliaHook.sol:336:39\n    │\n336 │             uint256 margOut = uint256(uint128(margDelta));\n    │                                       ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:369:25\n    │\n369 │             quietFee = (uint256(params.amountSpecified) * bps + (10_000 - bps) - 1) / (10_000 - bps);\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/MarginaliaHook.sol:370:28\n    │\n370 │             if (poolImd != uint256(params.amountSpecified) + quietFee) revert PartialFill();\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:452:17\n    │\n452 │             if (weekTheses[_week()].length >= MAX_WEEK_THESES) revert InvalidNote();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:444:22\n    │\n444 │         n.postedAt = uint64(block.timestamp);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe 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/MarginaliaHook.sol:500:13\n    │\n500 │         if (block.timestamp < end) revert TooEarly();\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/MarginaliaHook.sol:501:13\n    │\n501 │         if (block.timestamp > end + SETTLE_WINDOW) revert TooLate();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:514:9\n    │\n514 │         emit Observed(id, uint64(block.timestamp), xRead, quoteRead, balance);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:506:27\n    │\n506 │             T.Observation(uint64(block.timestamp), uint64(block.number), xRead, quoteRead, balance);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:506:52\n    │\n506 │             T.Observation(uint64(block.timestamp), uint64(block.number), xRead, quoteRead, balance);\n    │                                                    ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:514:27\n    │\n514 │         emit Observed(id, uint64(block.timestamp), xRead, quoteRead, balance);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[return-bomb]: external call with a gas limit may copy unbounded return data\n    ╭▸ src/MarginaliaHook.sol:522:13\n    │\n522 │             x.staticcall{gas: BALANCE_READ_GAS}(abi.encodeWithSelector(IERC20.balanceOf.selector, who));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/return-bomb\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaHook.sol:612:35\n    │\n612 │         emit Settled(id, outcome, settlePrice, scoreDelta, msg.sender);\n    │                                   ━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:562:13\n    │\n562 │         if (block.timestamp <= end + SETTLE_WINDOW) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:682:13\n    │\n682 │             emit ThesisReleased(n.parentId);\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/MarginaliaHook.sol:612:9\n    │\n612 │         emit Settled(id, outcome, settlePrice, scoreDelta, msg.sender);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:594:26\n    │\n594 │             scoreDelta = int256(_difficulty(n));\n    │                          ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:599:27\n    │\n599 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:601:27\n    │\n601 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:605:27\n    │\n605 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:620:13\n    │\n620 │         if (block.timestamp >= horizonEnd(id)) revert TooLate();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:629:9\n    │\n629 │         emit Retracted(id, text);\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/MarginaliaHook.sol:630:9\n    │\n630 │         emit Settled(id, T.Status.Retracted, 0, scoreDelta, address(0));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:622:30\n    │\n622 │         int256 scoreDelta = -int256(_difficulty(n) / 2);\n    │                              ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/MarginaliaHook.sol:638:13\n    │\n638 │         if (block.timestamp <= uint256(n.postedAt) + THESIS_GRACE) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:641:9\n    │\n641 │         emit ThesisForfeited(id);\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/MarginaliaHook.sol:659:9\n    │\n659 │         emit DepositClaimed(id, n.author, asImd, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:697:16\n    │\n697 │         return uint32(block.timestamp / 1 days);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:701:16\n    │\n701 │         return uint32(block.timestamp / 7 days);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:722:38\n    │\n722 │         uint256 prevPos = prev > 0 ? uint256(prev) : 0;\n    │                                      ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:723:38\n    │\n723 │         uint256 nextPos = next > 0 ? uint256(next) : 0;\n    │                                      ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:733:9\n    │\n733 │         emit PotFunded(_today(), amount, msg.sender);\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/MarginaliaHook.sol:745:9\n    │\n745 │         emit PotMargSold(amount, imdOut, _today());\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:765:27\n    │\n765 │         return (n.author, uint32(uint256(n.postedAt) / 7 days), n.targetBps == 0, n.children > 0);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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 `thesisPool` is updated\n    ╭▸ src/MarginaliaHook.sol:864:28\n    │\n864 │         bytes memory out = poolManager.unlock(data);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaHook.sol:864:28\n    │\n864 │         bytes memory out = poolManager.unlock(data);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:787:9\n    │\n787 │         emit JudgedPaid(w, paidAmounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/MarginaliaHook.sol:865:39\n    │\n865 │         if (unlockHash != bytes32(0)) revert InvalidUnlock();\n    │                                       ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:795:47\n    │\n795 │         uint256 share = FullMath.mulDiv(pool, uint256(s), weekTotal[w]);\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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:801:13\n    │\n801 │         if (w >= _week()) revert TooEarly();\n    │             ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:808:9\n    │\n808 │         emit LeaderboardClaimed(w, msg.sender, amount);\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/MarginaliaHook.sol:815:13\n    │\n815 │         if (n.day >= _today()) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:825:9\n    │\n825 │         emit RefundClaimed(id, msg.sender, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:823:30\n    │\n823 │         notesPerDay[n.day] = uint32(count - 1);\n    │                              ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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/MarginaliaHook.sol:834:17\n    │\n834 │             if (block.timestamp < (uint256(epoch) + 1) * 1 days + SWEEP_AFTER) revert TooEarly();\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/MarginaliaHook.sol:838:17\n    │\n838 │             if (block.timestamp < (uint256(epoch) + 1) * 7 days + SWEEP_AFTER) revert TooEarly();\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/MarginaliaHook.sol:842:17\n    │\n842 │             if (block.timestamp < (uint256(epoch) + 1) * 7 days + SWEEP_AFTER) revert TooEarly();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:875:40\n    │\n875 │             address currency = address(uint160(extra));\n    │                                        ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint160' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaHook.sol:884:13\n    │\n884 │             poolManager.settle();\n    │             ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:894:22\n    │\n894 │                     -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/MarginaliaHook.sol:903:17\n    │\n903 │             if (uint256(uint128(-margDelta)) != amount) revert InvalidUnlock();\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/MarginaliaHook.sol:903:25\n    │\n903 │             if (uint256(uint128(-margDelta)) != amount) revert InvalidUnlock();\n    │                         ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:905:30\n    │\n905 │             uint256 imdOut = uint256(uint128(imdDelta));\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/MarginaliaHook.sol:905:38\n    │\n905 │             uint256 imdOut = uint256(uint128(imdDelta));\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[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n   ╭▸ test/AuditFindings.t.sol:19:30\n   │\n19 │         uint256 startBlock = block.number;\n   │                              ━━━━━━━━━━━━\n   ‡\n23 │             vm.roll(startBlock + 25 * (i + 1));\n   │             ────────────────────────────────── `vm.roll` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockNumber()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/AuditFindings.t.sol:20:27\n   │\n20 │         uint256 startTs = block.timestamp;\n   │                           ━━━━━━━━━━━━━━━\n   ‡\n24 │             vm.warp(startTs + 31 minutes * (i + 1));\n   │             ─────────────────────────────────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/AuditFindings.t.sol:18:9\n    │\n 18 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/AuditFindings.t.sol:65:9\n    │\n 65 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/AuditFindings.t.sol:65:17\n   │\n65 │         vm.warp(block.timestamp + 7 days);\n   │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:130:9\n    │\n130 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:131:30\n    │\n131 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n135 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:132:27\n    │\n132 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n136 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:158:9\n    │\n158 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:159:30\n    │\n159 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n163 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:160:27\n    │\n160 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n164 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:182:9\n    │\n182 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:183:30\n    │\n183 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n187 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:184:27\n    │\n184 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n188 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:278:9\n    │\n278 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:278:17\n    │\n278 │         vm.warp(block.timestamp + 7 days);\n    │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:328:9\n    │\n328 │         vm.warp(hook.horizonEnd(a));\n    │         ─────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:329:30\n    │\n329 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n334 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:330:27\n    │\n330 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n335 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:408:9\n    │\n408 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:408:17\n    │\n408 │         vm.warp(block.timestamp + 7 days);\n    │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:475:9\n    │\n475 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:476:30\n    │\n476 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n479 │         vm.roll(startBlock + 25);\n    │         ──────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:477:27\n    │\n477 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n480 │         vm.warp(startTs + 30 minutes);\n    │         ───────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:499:9\n    │\n499 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:500:30\n    │\n500 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n504 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:501:27\n    │\n501 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n505 │             vm.warp(startTs + 10 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/RevisionFindings.t.sol:197:17\n    │\n197 │         vm.warp(block.timestamp + 1 hours);\n    │         ────────━━━━━━━━━━━━━━━─────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/RevisionFindings.t.sol:258:9\n    │\n258 │         vm.warp((uint256(w) + 1) * 7 days + 1);\n    │         ────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\n","passed":true},{"durationMs":1182,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/fork/MainnetLaunch.t.sol:MainnetLaunchTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 695.56µs (0.00ns CPU time)\n\nRan 7 tests for test/JudgeOracle.t.sol:JudgeOracleTest\n[PASS] testEmptySignedRankingIsAnExecutableNoWinnerResult() (gas: 248153)\n[PASS] testFiveIdsWithEoaSignatureFitStipend() (gas: 554052)\n[PASS] testFullRankingWithEoaSignatureFitsStipend() (gas: 633672)\n[PASS] testProtocolDigestSignatureAndSelectorConformanceOnClone() (gas: 3322442)\n[PASS] testRejectedAnswersDoNotConsumeThePendingRequest() (gas: 892875)\n[PASS] testRequestedHeadIsFilteredAndDeduplicatedWithoutPromotingTheTail() (gas: 250679)\n[PASS] testTimeoutRetryInvalidatesOldIntakeRequest() (gas: 523953)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 5.58ms (4.29ms CPU time)\n\nRan 14 tests for test/CompanionFailures.t.sol:RouterFailuresTest\n[PASS] testExpiredDeadlineTakesNothing() (gas: 736655)\n[PASS] testExpiredWindowRefusesPostsUntilAFreshCheckpointMatures() (gas: 1908838)\n[PASS] testInitRequiresAManagerWithCode() (gas: 4169863)\n[PASS] testSlippageFloorRefundsEverything() (gas: 708445)\n[PASS] testStrangersCannotEnterTheCallbacks() (gas: 133302)\n[PASS] testTradeAndNoteRefusesNoTradeZeroTradeAndNativeInput() (gas: 290929)\n[PASS] testTradedNoteMustBeAboutTheTokenTraded() (gas: 1059618)\n[PASS] testTradedV4LegUnderAForeignHookOrEmptyPoolIsRefused() (gas: 396401)\n[PASS] testUnapprovedOrUnfundedAuthorIsRefused() (gas: 224509)\n[PASS] testV4VenueUnderAForeignHookIsRefused() (gas: 69825)\n[PASS] testV4VenueWithoutLiquidityIsRefused() (gas: 135027)\n[PASS] testVenueFieldsAreDerivedFromThePoolNotTheCaller() (gas: 48687)\n[PASS] testVenueKindNoneIsRefusedForAPricedCall() (gas: 116379)\n[PASS] testZeroAndOversizedAmountsAreRefused() (gas: 138629)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 28.34ms (6.21ms CPU time)\n\nRan 10 tests for test/HoldRule.t.sol:HoldRuleTest\n[PASS] testABreachIsNeverReplacedByANonBreachInsideTheGap() (gas: 1740909)\n[PASS] testABreachReplacesANonBreachInsideTheGap() (gas: 1751712)\n[PASS] testASingleObservationPastTheToleranceVoidsTheCall() (gas: 1783185)\n[PASS] testAnEqualReadingInsideTheGapIsRefused() (gas: 1101068)\n[PASS] testAtTheCapAHigherReadingCannotLiftABuyCallsMinimum() (gas: 3996340)\n[PASS] testAtTheCapOnlyAMoreAdverseReadingGetsIn() (gas: 4265456)\n[PASS] testBuyCallHasNoToleranceDownwards() (gas: 1658101)\n[PASS] testSellCallBreaksOneWeiPastTheTolerance() (gas: 1799854)\n[PASS] testSellCallHoldsExactlyAtTheTolerance() (gas: 1799604)\n[PASS] testSmallAuthorIsBoundByTheDepositsWorthNotTenPercent() (gas: 1873421)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 33.12ms (9.04ms CPU time)\n\nRan 8 tests for test/AuditFindings.t.sol:AuditFindingsTest\n[PASS] testConversionAfterARealPriceFallNeedsAFreshMatureWindow() (gas: 2239771)\n[PASS] testEmptyV4ObservationIsRefused() (gas: 1022543)\n[PASS] testExpiredBaselineRejectsPostWithoutTakingFunds() (gas: 643715)\n[PASS] testForfeitureConversionRejectsSameBlockDump() (gas: 2218773)\n[PASS] testLongRankingFitsIntakeStipend() (gas: 2193239)\n[PASS] testSameBlockDumpPostUnwindDoesNotWinBuy() (gas: 1914995)\n[PASS] testSameBlockPumpPostUnwindDoesNotWinSell() (gas: 1787168)\n[PASS] testUnpayableRankingRollsTheWholePoolForward() (gas: 2466565)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 42.92ms (10.73ms CPU time)\n\nRan 2 tests for test/PotTranche.t.sol:PotTrancheTest\n[PASS] testForfeitedPotCanStillBeConvertedOnceItOutgrowsOneSale() (gas: 49410352)\nLogs:\n  potMarg: 36877975912613201326\n  imdOut: 10344028156678390861\n\n[PASS] testWhenNoTrancheSellsTheHookReasonSurfaces() (gas: 1260643)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 46.12ms (30.67ms CPU time)\n\nRan 26 tests for test/Lifecycle.t.sol:LifecycleTest\n[PASS] testAttestedClassCannotBeSelfDeclared() (gas: 343256)\n[PASS] testCallbackSelectorPinned() (gas: 3361)\n[PASS] testFakeVenueIsRefused() (gas: 382780)\n[PASS] testFlagsAndBinding() (gas: 55989)\n[PASS] testForfeitsConvertToImdForThePot() (gas: 1112852)\n[PASS] testLeaderboardProRataWithCap() (gas: 3243602)\n[PASS] testNoDataRefunds() (gas: 993629)\n[PASS] testNoteTooSmall() (gas: 173144)\n[PASS] testNotedBuyTakesStampAndDeposit() (gas: 798665)\n[PASS] testNotedSellPaysOnePercentPlusStamp() (gas: 1108348)\n[PASS] testObservationsMustSpanAnHour() (gas: 1488779)\n[PASS] testPlainBuyTakesNothing() (gas: 230618)\n[PASS] testQuietSellPaysThreePercent() (gas: 336869)\n[PASS] testQuietThesisPoolSweeps() (gas: 306043)\n[PASS] testRetract() (gas: 945582)\n[PASS] testRightCallReturnsDepositAsImd() (gas: 1802343)\n[PASS] testSellingEarlyBreaksTheCall() (gas: 1770726)\n[PASS] testThesisParentChild() (gas: 1509361)\n[PASS] testThesisWithoutChildForfeits() (gas: 797205)\n[PASS] testTreasuryDrip() (gas: 348364)\n[PASS] testTwoBlockPumpObserveUnwindSettlesWrong() (gas: 1802286)\n[PASS] testUnansweredWeekCanBeRetried() (gas: 2442021)\n[PASS] testUpOnlyIsRefused() (gas: 340864)\n[PASS] testWeeklyThesisJudging() (gas: 3856451)\n[PASS] testWriterRefundCappedAtStamp() (gas: 1711148)\n[PASS] testWrongCallForfeitsWithKeeperReward() (gas: 1560130)\nSuite result: ok. 26 passed; 0 failed; 0 skipped; finished in 66.99ms (17.23ms CPU time)\n\nRan 28 tests for test/CompanionFailures.t.sol:JudgeFailuresTest\n[PASS] testAJudgedWeekCannotBeAbandoned() (gas: 1257630)\n[PASS] testAbandonNeedsALiveRequestPastItsDeadline() (gas: 1190393)\n[PASS] testAbandonTakesNothingAndTheRetryDrawsAgain() (gas: 1467522)\n[PASS] testAnswerAtTheExactExpiryStillCountsAndOneSecondLaterDoesNot() (gas: 1257046)\n[PASS] testAnswerForAWeekAlreadyJudgedIsRefused() (gas: 1320679)\n[PASS] testAnswerSignedByAnotherKeyIsRefused() (gas: 1069433)\n[PASS] testAnswerSignedForAnotherConsumerIsRefused() (gas: 3952788)\n[PASS] testConvertForfeitsWithAnEmptyPotIsANoOp() (gas: 236930)\n[PASS] testConvertNeverSellsMoreThanThePot() (gas: 236488)\n[PASS] testConvertSellsTheLargestHalvingThePoolAbsorbs() (gas: 275386)\n[PASS] testConvertTriesExactlyNineTranchesDownToOneTwoHundredFiftySixth() (gas: 363686)\n[PASS] testCurrentAndFutureWeeksCannotBeRequested() (gas: 128617)\n[PASS] testEligibleThesesAreCappedAtTheJudgedMaximum() (gas: 14217218)\n[PASS] testImplementationHasAPlaceholderSignerAndCannotBeConfigured() (gas: 2726709)\n[PASS] testInitRequiresEveryConfigurationValue() (gas: 2953442)\n[PASS] testIntakeReturningAnIdAlreadyPendingIsRefused() (gas: 1599187)\n[PASS] testJudgedOfFiltersWrongWeekShortFormAndChildlessIds() (gas: 1439829)\n[PASS] testJudgedWeekCannotBeRequestedAgainEvenAfterTheDeadline() (gas: 1242650)\n[PASS] testMalformedAnswerBytesAreRefused() (gas: 1067354)\n[PASS] testOnlyTheHeadOfThreeIsStoredAndTheTailNeverPromotes() (gas: 1221812)\n[PASS] testPayBeforeAnAnswerReverts() (gas: 1064318)\n[PASS] testPayIsPermissionlessAndOnce() (gas: 1438634)\n[PASS] testQuestionBodyNamesTheConsumerChainAndEligibleIdsOnly() (gas: 2516225)\n[PASS] testRepeatRequestBeforeTheDeadlineIsRefused() (gas: 1419149)\n[PASS] testRequestDrawsExactlyThePriceAndKeepsNothing() (gas: 1028228)\n[PASS] testWeekClosedStates() (gas: 1940695)\n[PASS] testWeekWithoutEligibleThesesCannotBeRequested() (gas: 244665)\n[PASS] testZeroAndExcessiveOraclePricesAreRefused() (gas: 1345941)\nSuite result: ok. 28 passed; 0 failed; 0 skipped; finished in 72.10ms (48.97ms CPU time)\n\nRan 3 tests for test/Implementations.t.sol:ImplementationsTest\n[PASS] testClonesInitializeOnceOnlyFromTheirHook() (gas: 4551335)\n[PASS] testFactoryDeploysAllFourWithoutArgumentsOrExternalDependencies() (gas: 34594277)\nLogs:\n  four implementation CREATE2 deployments (gas): 8826312\n\n[PASS] testImplementationsRejectInitialization() (gas: 81376)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 77.34ms (55.27ms CPU time)\n\nRan 7 tests for test/Pricer.t.sol:PricerTest\n[PASS] testQuoteLegIsAdverseEvenUnderAV3Twap() (gas: 28455)\n[PASS] testTwapRefusesZeroSpanAndV4() (gas: 17708)\n[PASS] testV2TwapFromWrappingCumulative() (gas: 9503)\n[PASS] testV3TwapOfAConstantTickIsThatTick() (gas: 15459)\n[PASS] testV3TwapRoundsNegativeMeansDown() (gas: 14848)\n[PASS] testV3TwapWeightsByTime() (gas: 14715)\n[PASS] testV4SettlesOnTheAdverseExtreme() (gas: 26636)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 77.34ms (562.84µs CPU time)\n\nRan 8 tests for test/PriceHistory.t.sol:PriceHistoryTest\n[PASS] testBaselineRequiresMatureFreshHistory() (gas: 188472)\n[PASS] testEmptyVenueAndHubCannotBeCheckpointedObservedOrPriced() (gas: 284549)\n[PASS] testFuzzV4BaselineIsNeverFavourableToTheCall(int24,bool) (runs: 256, μ: 106017, ~: 106151)\nLogs:\n  Bound result 180\n\n[PASS] testHubBaselineUsesOppositeExtremeFromSettlement() (gas: 180334)\n[PASS] testLiveCheckpointCannotEraseHonestExtremesOrRestartTheClock() (gas: 224282)\n[PASS] testV2BaselineIgnoresSameBlockReservesDumpAndPumpBothOrientations() (gas: 467543)\n[PASS] testV3BaselineIgnoresSameBlockTickChangesBothOrientations() (gas: 418025)\n[PASS] testV3BaselineWeightsElapsedTime() (gas: 371037)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 102.29ms (36.03ms CPU time)\n\nRan 10 tests for test/RevisionFindings.t.sol:RevisionFindingsTest\n[PASS] testADustPricedV4VenueCannotBePostedOn() (gas: 1636136)\n[PASS] testARealBuyBackStillVoidsASellCall() (gas: 1791662)\n[PASS] testARevertingBalanceOfVoidsTheCallAsSoldNotAsNoData() (gas: 2678007)\n[PASS] testAStrangersDustTransferDoesNotVoidASellCall() (gas: 1697092)\n[PASS] testAnAttestationAboutAnotherChainIsRefused() (gas: 2325368)\n[PASS] testAnEmptyCanonicalV3PoolIsRefusedAsAVenue() (gas: 567990)\n[PASS] testHonestObserverOverwritesAPumpObserveUnwindInTheNextBlock() (gas: 3783793)\n[PASS] testPricerRefusesAPriceThatRoundsToZeroInBothOrientations() (gas: 58727)\n[PASS] testSweepNeedsTheStaleRequestAbandonedAndALateAnswerIsThenRefused() (gas: 2450533)\n[PASS] testTheHundredAndTwentyFirstThesisOfAWeekIsRefusedBeforePayment() (gas: 55411706)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 102.29ms (60.47ms CPU time)\n\nRan 9 tests for test/CompanionFailures.t.sol:TreasuryFailuresTest\n[PASS] testDripFailsWhenTheHookCannotTakeTheFunds() (gas: 673929)\n[PASS] testDripIsPermissionlessAndCompounds() (gas: 518661)\n[PASS] testDripOfDustRoundsToZeroAndReverts() (gas: 258318)\n[PASS] testDripWithNothingHeldReverts() (gas: 54033)\n[PASS] testInitOnlyByTheNamedHookAndOnlyOnce() (gas: 623926)\n[PASS] testInitRefusesTheZeroHook() (gas: 556415)\n[PASS] testNoWithdrawOrAdminSurface() (gas: 274868)\n[PASS] testSecondDripOnTheSameDayRevertsAndTheNextDayWorks() (gas: 372660)\n[PASS] testTreasuryRefusesEth() (gas: 71164)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 102.44ms (1.52ms CPU time)\n\nRan 31 tests for test/PricerProperties.t.sol:PricerPropertiesTest\n[PASS] testDifficultyAnchors() (gas: 56326)\n[PASS] testDifficultyRefusesAZeroHorizon() (gas: 10063)\n[PASS] testDifficultyTiersStepExactlyAtTheThresholds() (gas: 79182)\n[PASS] testEmptyPoolsAreRefusedOnBothLegs() (gas: 161813)\n[PASS] testEthQuoteIsOnlyPriceableOnMainnet() (gas: 40894)\n[PASS] testFromSqrtRefusesAnEmptyOrUnpriceableReading() (gas: 53891)\n[PASS] testFromSqrtZeroThresholdIsSharpInBothOrientations() (gas: 1024204)\n[PASS] testFuzzAppendingAnObservationNeverHelpsTheCall(uint256[16],uint256[16],uint8) (runs: 1000, μ: 131610, ~: 114644)\nLogs:\n  Bound result 2\n  Bound result 999999999999999999999000000021\n  Bound result 790900084040348498382543954915\n  Bound result 582988905446511441171610839829\n  Bound result 686540126554517274566437207636\n\n[PASS] testFuzzBuyDifficultyGrowsWithTheTarget(uint32,uint32,uint16,uint256) (runs: 1000, μ: 36878, ~: 36914)\nLogs:\n  Bound result 16712\n  Bound result 20938\n  Bound result 56\n  Bound result 48\n\n[PASS] testFuzzCheckpointKeepsStartAndWidensExtremes(uint160,uint160,uint256) (runs: 512, μ: 141463, ~: 141865)\nLogs:\n  Bound result 1237940039285380274899124224\n  Bound result 1237940039285380274899124224\n  Bound result 28800\n\n[PASS] testFuzzDifficultyFallsWithTheHorizon(uint32,uint16,uint16,uint256) (runs: 1000, μ: 36714, ~: 36857)\nLogs:\n  Bound result 724952\n  Bound result 65\n  Bound result 43\n  Bound result 23125\n\n[PASS] testFuzzFromSqrtIsMonotoneAndInverts(uint160,uint160) (runs: 1000, μ: 23522, ~: 21564)\nLogs:\n  Bound result 158463096878581935577856642341082729\n  Bound result 1461446703485210103287273052103988822378723970348\n\n[PASS] testFuzzLog2IsBracketedAndMonotone(uint256,uint256) (runs: 1000, μ: 39769, ~: 39503)\nLogs:\n  Bound result 9178615601838078631124023225309410649\n  Bound result 180454008847365271119622520421816231\n\n[PASS] testFuzzLog2IsExactAtPowersOfTwo(uint8) (runs: 512, μ: 16093, ~: 14210)\nLogs:\n  Bound result 136\n\n[PASS] testFuzzPostPriceWindowBoundaries(uint256,bool) (runs: 512, μ: 54413, ~: 51987)\nLogs:\n  Bound result 12399\n\n[PASS] testFuzzSellDifficultyGrowsAsTheTargetFalls(uint32,uint32,uint16,uint256) (runs: 1000, μ: 36377, ~: 36368)\nLogs:\n  Bound result 4152\n  Bound result 3766\n  Bound result 77\n  Bound result 9999\n\n[PASS] testFuzzSqrtIsTheIntegerFloor(uint256) (runs: 1000, μ: 22518, ~: 20410)\nLogs:\n  Bound result 2400\n\n[PASS] testFuzzV2TwapOfAConstantRatioIsThatRatio(uint112,uint112,uint32,bool) (runs: 512, μ: 21354, ~: 21299)\nLogs:\n  Bound result 23664096763251671\n  Bound result 2129181855976\n  Bound result 1057396\n\n[PASS] testFuzzV3SettlementIgnoresMiddleReadings(int24,uint256[16],uint8,bool) (runs: 512, μ: 63189, ~: 58634)\nLogs:\n  Bound result 186244\n  Bound result 3\n\n[PASS] testFuzzV4SettlesOnTheExtremeOfEveryObservation(uint256[16],uint256[16],uint8) (runs: 1000, μ: 102234, ~: 93511)\nLogs:\n  Bound result 12\n  Bound result 600\n  Bound result 127\n  Bound result 17746\n  Bound result 12245\n  Bound result 400000000000000000000\n  Bound result 120209876281281145568259943\n  Bound result 17815\n  Bound result 13035\n  Bound result 50\n  Bound result 1\n  Bound result 1800000000\n  Bound result 1341\n  Bound result 3052\n  Bound result 250\n  Bound result 10500\n  Bound result 999001\n  Bound result 1000000000\n  Bound result 256\n  Bound result 6356\n  Bound result 806583589928461891782872549115\n  Bound result 9859\n  Bound result 21990\n  Bound result 12146\n  Bound result 8001\n\n[PASS] testObserveRefusesUnknownVenuesAndUnpriceableQuotes() (gas: 150448)\n[PASS] testPostPriceRefusesAnEmptyWindow() (gas: 15317)\n[PASS] testPostPriceWhoseProductRoundsToZeroIsRefused() (gas: 293627)\n[PASS] testSellDifficultyRefusesAZeroTarget() (gas: 9518)\n[PASS] testSettlementRefusesAnEmptyOrUnspannedSeries() (gas: 39083)\n[PASS] testSqrtIsExactOnEveryHorizonDifficultyUses() (gas: 901295)\n[PASS] testSqrtPins() (gas: 96564)\n[PASS] testTwapRefusesTimeRunningBackwards() (gas: 9132)\n[PASS] testV2TwapAndSpotOfADustRatioAreRefused() (gas: 220677)\n[PASS] testV3TwapRefusesAMeanTickOutsideTheRange() (gas: 27255)\n[PASS] testV4SeriesWithADustExtremeIsRefusedNotSettledAtZero() (gas: 33519)\nSuite result: ok. 31 passed; 0 failed; 0 skipped; finished in 102.42ms (982.57ms CPU time)\n\nRan 1 test for test/RouterInvariant.t.sol:RouterInvariantTest\n[PASS]\nRouterInvariantTest invariants:\n[PASS] invariant_bindingsPinned\n[PASS] invariant_everyNoteCameThroughTheRouter\n[PASS] invariant_managerBacksTheHooksClaims\n[PASS] invariant_routerKeepsNothing\n RouterInvariantTest invariants (runs: 48, calls: 1920, reverts: 3)\n\n╭---------------+----------------+-------+---------+----------╮\n| Contract      | Selector       | Calls | Reverts | Discards |\n+=============================================================+\n| RouterHandler | advance        | 201   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | checkpoint     | 211   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | noteBuy        | 425   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | noteSell       | 243   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | plainBuy       | 220   | 3       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | plainSell      | 206   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | strayCallbacks | 212   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | thesis         | 202   | 0       | 0        |\n╰---------------+----------------+-------+---------+----------╯\n\nLogs:\n  Bound result 1\n  Bound result 428461891782872549115\n  Bound result 0\n  Bound result 1331245605106442717441\n  Bound result 29671\n  Bound result 29\n  Bound result 2\n  Bound result 16690\n  Bound result 2\n  Bound result 5400\n  Bound result 2279\n  Bound result 1\n  Bound result 1969529035837012967424\n  Bound result 50006\n  Bound result 19\n  Bound result 2181094200382159806541\n  Bound result 0\n  Bound result 0\n  Bound result 9848\n  Bound result 1\n  Bound result 4917\n  Bound result 51594\n  Bound result 6\n  Bound result 0\n  Bound result 11720\n  Bound result 47498\n  Bound result 100\n  Bound result 4386\n  Bound result 1731687303715884105728\n  Bound result 1\n  Bound result 0\n  Bound result 997\n  Bound result 45\n  Bound result 62\n  Bound result 1257132168796771975168\n  Bound result 1\n  Bound result 1\n  Bound result 14634\n  Bound result 25200\n  Bound result 24\n  Bound result 12676\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 4600\n  Bound result 3013\n  Bound result 2\n  Bound result 5030\n  Bound result 1\n  Bound result 2\n  Bound result 130\n  Bound result 2\n  Bound result 15090800634051834736996\n  Bound result 1618803804543492746084\n  Bound result 0\n  Bound result 1\n  Bound result 7000\n  Bound result 2\n  Bound result 682\n  Bound result 2\n  Bound result 12\n  Bound result 50099\n  Bound result 80\n  Bound result 311\n  Bound result 2\n  Bound result 659918\n  Bound result 0\n  Bound result 5448\n  Bound result 53701\n  Bound result 25\n  Bound result 1\n  Bound result 2000000000000000000000\n  Bound result 53870\n  Bound result 3\n  Bound result 1\n  Bound result 1\n  Bound result 100000\n  Bound result 54609\n  Bound result 66\n  Bound result 3908891086\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 2884\n  Bound result 50009\n  Bound result 97\n  Bound result 2912\n  Bound result 1\n  Bound result 600107525756177357338\n  Bound result 1119\n  Bound result 61\n  Bound result 2062\n  Bound result 0\n  Bound result 1\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 505.62ms (464.92ms CPU time)\n\nRan 1 test for test/TreasuryInvariant.t.sol:TreasuryInvariantTest\n[PASS]\nTreasuryInvariantTest invariants:\n[PASS] invariant_balanceIsGiftsMinusDrips\n[PASS] invariant_dripNeverExceedsTwoPercent\n[PASS] invariant_holdsNoEth\n[PASS] invariant_hookHoldsExactlyTheDrips\n[PASS] invariant_hookIsPinned\n[PASS] invariant_lastDripDayMatchesTheLastSuccessfulDrip\n TreasuryInvariantTest invariants (runs: 256, calls: 12288, reverts: 0)\n\n╭-----------------+-----------+-------+---------+----------╮\n| Contract        | Selector  | Calls | Reverts | Discards |\n+==========================================================+\n| TreasuryHandler | advance   | 2436  | 0       | 0        |\n|-----------------+-----------+-------+---------+----------|\n| TreasuryHandler | drip      | 2557  | 0       | 0        |\n|-----------------+-----------+-------+---------+----------|\n| TreasuryHandler | gift      | 2336  | 0       | 0        |\n|-----------------+-----------+-------+---------+----------|\n| TreasuryHandler | initAgain | 2538  | 0       | 0        |\n|-----------------+-----------+-------+---------+----------|\n| TreasuryHandler | sendEth   | 2421  | 0       | 0        |\n╰-----------------+-----------+-------+---------+----------╯\n\nLogs:\n  Bound result 7338610221499554906198008321557211\n  Bound result 9485\n  Bound result 59600000000000000000\n  Bound result 1177287777345828436\n  Bound result 8977\n  Bound result 60000\n  Bound result 2566503868\n  Bound result 3485812809\n  Bound result 111856\n  Bound result 80\n  Bound result 5221\n  Bound result 3700\n  Bound result 100\n  Bound result 511\n  Bound result 2233625729\n  Bound result 5000\n  Bound result 2268725315109355359\n  Bound result 7200\n  Bound result 5144\n  Bound result 1461501637330902918203684832716283019655932542974\n  Bound result 5045\n  Bound result 761215472035047097543880\n  Bound result 2220\n  Bound result 835674303940258373226646\n  Bound result 12345\n  Bound result 16777216\n  Bound result 1975\n  Bound result 142271\n  Bound result 495790613316\n  Bound result 2328\n  Bound result 994580754177754836227837\n  Bound result 3288\n  Bound result 86229\n  Bound result 118677\n  Bound result 16383\n  Bound result 12\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.07s (1.07s CPU time)\n\nRan 16 test suites in 1.08s (2.44s CPU time): 165 tests passed, 0 failed, 1 skipped (166 total tests)\n","passed":true},{"durationMs":70,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"Marginalia.approve(address,uint256)\",\"Marginalia.transfer(address,uint256)\",\"Marginalia.transferFrom(address,address,uint256)\",\"MarginaliaHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"MarginaliaHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"MarginaliaHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"MarginaliaHook.claimDeposit(bytes32,bool)\",\"MarginaliaHook.claimLeaderboard(uint32)\",\"MarginaliaHook.claimRefund(bytes32)\",\"MarginaliaHook.drawForJudging(uint32,uint256,bool)\",\"MarginaliaHook.fundPot(uint256)\",\"MarginaliaHook.observe(bytes32)\",\"MarginaliaHook.payJudged(uint32,bytes32[3])\",\"MarginaliaHook.retract(bytes32,string)\",\"MarginaliaHook.sellPotMarg(uint256)\",\"MarginaliaHook.settle(bytes32)\",\"MarginaliaHook.settleThesis(bytes32)\",\"MarginaliaHook.sweep(uint8,uint32)\",\"MarginaliaHook.unlockCallback(bytes)\",\"MarginaliaJudge.abandonRequest(uint32)\",\"MarginaliaJudge.convertForfeits()\",\"MarginaliaJudge.init(address,address,bytes32,address)\",\"MarginaliaJudge.onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"MarginaliaJudge.payJudged(uint32)\",\"MarginaliaJudge.requestJudging(uint32)\",\"MarginaliaRouter.checkpointVenue((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address))\",\"MarginaliaRouter.init(address,address)\",\"MarginaliaRouter.note((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address),uint256,uint256,uint256)\",\"MarginaliaRouter.sellWithNote((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address),uint256,uint256,uint256)\",\"MarginaliaRouter.uniswapV3SwapCallback(int256,int256,bytes)\",\"MarginaliaRouter.unlockCallback(bytes)\",\"MarginaliaTreasury.drip()\",\"MarginaliaTreasury.init(address)\"],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":179,\"README.md\":143,\"SPEC.md\":263,\"dependencies.json\":28,\"foundry.toml\":21,\"helper/.gitignore\":3,\"helper/package-lock.json\":737,\"helper/package.json\":20,\"helper/public/index.html\":82,\"helper/server.js\":90,\"helper/src/app.js\":203,\"jobs/launch-1-hook.json\":43,\"jobs/launch-2-contracts.json\":38,\"jobs/launch-A-implementations.json\":47,\"jobs/launch-A2-implementations.json\":41,\"jobs/launch-hook-v3.json\":43,\"remappings.txt\":4,\"src/HookFlags.sol\":33,\"src/Marginalia.sol\":12,\"src/MarginaliaHook.sol\":927,\"src/MarginaliaImpls.sol\":14,\"src/MarginaliaJudge.sol\":290,\"src/MarginaliaPricer.sol\":304,\"src/MarginaliaRouter.sol\":446,\"src/MarginaliaTreasury.sol\":53,\"src/MarginaliaTypes.sol\":108,\"src/OracleAttestation.sol\":221,\"src/interfaces/IIntake.sol\":15,\"src/interfaces/ILaunchFactory.sol\":49,\"test/AuditFindings.t.sol\":178,\"test/CompanionFailures.t.sol\":941,\"test/HoldRule.t.sol\":237,\"test/Implementations.t.sol\":96,\"test/JudgeOracle.t.sol\":270,\"test/Lifecycle.t.sol\":511,\"test/PotTranche.t.sol\":189,\"test/PriceHistory.t.sol\":233,\"test/Pricer.t.sol\":88,\"test/PricerProperties.t.sol\":567,\"test/RevisionFindings.t.sol\":314,\"test/RouterInvariant.t.sol\":248,\"test/TreasuryInvariant.t.sol\":167,\"test/fork/MainnetLaunch.t.sol\":382,\"test/helpers/Fixture.sol\":278,\"test/mocks/MockERC20.sol\":13},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"9701a2d204b980cc241b83f0abfc2009d89276cf29393c7bf33e450306a36305","verifiedTreeHash":"48d5776e0670ddeb085f5dc191b6c82120c9f879","verifierVersion":"0.1.0+4ba55555"},{"checks":[{"durationMs":94178,"exitCode":0,"name":"build","output":"Compiling 109 files with Solc 0.8.26\nSolc 0.8.26 finished in 93.95s\nCompiler run successful with warnings:\nWarning (8760): This declaration has the same name as another declaration.\n   --> src/MarginaliaHook.sol:383:9:\n    |\n383 |         uint32 week = _week();\n    |         ^^^^^^^^^^^\nNote: The other declaration is here:\n   --> src/MarginaliaHook.sol:706:5:\n    |\n706 |     function week() external view returns (uint32) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:771:9:\n    |\n771 |         uint256 pool = thesisPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:90:5:\n   |\n90 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:792:9:\n    |\n792 |         uint256 pool = leaderboardPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:90:5:\n   |\n90 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2018): Function state mutability can be restricted to pure\n   --> test/helpers/Fixture.sol:114:5:\n    |\n114 |     function priceOf(bytes32, address) external view returns (uint256) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (2018): Function state mutability can be restricted to pure\n  --> test/fork/MainnetLaunch.t.sol:78:5:\n   |\n78 |     function _mine(bytes memory hookCode) internal view returns (bytes32 salt) {\n   |     ^ (Relevant source part starts here and spans across multiple lines).\n\nwarning[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/MarginaliaPricer.sol:85:13\n   │\n85 │             n += 1;\n   │             ━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaPricer.sol:120:33\n    │\n120 │         if (w.startedAt == 0 || block.timestamp > uint256(w.startedAt) + POST_MAX_AGE) {\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:121:34\n    │\n121 │             return T.PriceWindow(uint64(block.timestamp), uint64(block.number), x, x, x, q, q);\n    │                                  ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:121:59\n    │\n121 │             return T.PriceWindow(uint64(block.timestamp), uint64(block.number), x, x, x, q, q);\n    │                                                           ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe 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]: `jobHash` is changed without an event but is used for access control\n    ╭▸ src/MarginaliaRouter.sol:303:16\n    │\n303 │         delete jobHash;\n    │                ━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaPricer.sol:142:20\n    │\n142 │                 || block.timestamp < uint256(w.startedAt) + POST_MIN_SPAN\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/MarginaliaPricer.sol:143:20\n    │\n143 │                 || block.timestamp > uint256(w.startedAt) + POST_MAX_AGE\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:149:69\n    │\n149 │             x = twap(v.kind, v.xIsToken0, w.xStart, w.startedAt, x, uint64(block.timestamp));\n    │                                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:168:55\n    │\n168 │         else if (v.kind == T.VenueKind.UniV3) xRead = uint256(_v3Cumulative(ref));\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/MarginaliaPricer.sol:213:28\n    │\n213 │             int256 delta = int256(c2) - int256(c1);\n    │                            ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:213:41\n    │\n213 │             int256 delta = int256(c2) - int256(c1);\n    │                                         ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:214:35\n    │\n214 │             int256 mean = delta / int256(dt);\n    │                                   ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:215:38\n    │\n215 │             if (delta < 0 && delta % int256(dt) != 0) mean -= 1; // round toward negative infinity, as v3 does\n    │                                      ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:217:57\n    │\n217 │             return fromSqrt(TickMath.getSqrtPriceAtTick(int24(mean)), xIsToken0);\n    │                                                         ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int24' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaPricer.sol:241:37\n    │\n241 │             (uint160 sqrtP,,,,,,) = IUniswapV3PoolOracle(ref).slot0();\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/MarginaliaPricer.sol:245:41\n    │\n245 │             (uint112 r0, uint112 r1,) = IUniswapV2PairOracle(ref).getReserves();\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/MarginaliaPricer.sol:269:33\n    │\n269 │         (int56[] memory cum,) = IUniswapV3PoolOracle(pool).observe(ago);\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:279:24\n    │\n279 │         uint32 nowTs = uint32(block.timestamp);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/MarginaliaHook.sol:75:38\n   │\n75 │     bytes32 public constant ACTION = bytes32(\"oracle.request@oracle-1\");\n   │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes32' is safe 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/MarginaliaHook.sol:193:44\n    │\n193 │     constructor(IPoolManager poolManager_, address token_, address factory_) {\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/MarginaliaRouter.sol:251:13\n    │\n251 │         if (block.timestamp > deadline) revert Expired();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:252:41\n    │\n252 │         if (amountIn == 0 || amountIn > uint256(uint128(type(int128).max))) revert InvalidSwap();\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/MarginaliaRouter.sol:252:49\n    │\n252 │         if (amountIn == 0 || amountIn > uint256(uint128(type(int128).max))) revert InvalidSwap();\n    │                                                 ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:338:9\n    │\n338 │         emit Noted(job.payer, job.sellMarg, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:320:18\n    │\n320 │                 -int256(job.amountIn),\n    │                  ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:328:25\n    │\n328 │         uint256 spent = uint256(uint128(-inputDelta));\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/MarginaliaRouter.sol:328:33\n    │\n328 │         uint256 spent = uint256(uint128(-inputDelta));\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:329:28\n    │\n329 │         uint256 received = uint256(uint128(outputDelta));\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/MarginaliaRouter.sol:329:36\n    │\n329 │         uint256 received = uint256(uint128(outputDelta));\n    │                                    ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:373:9\n    │\n373 │         emit XTraded(payer, X_V4, xIn, xOut, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:355:18\n    │\n355 │                 -int256(x.amountIn),\n    │                  ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:363:25\n    │\n363 │         uint256 spent = uint256(uint128(-inputDelta));\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/MarginaliaRouter.sol:363:33\n    │\n363 │         uint256 spent = uint256(uint128(-inputDelta));\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:364:20\n    │\n364 │         received = uint256(uint128(outputDelta));\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/MarginaliaRouter.sol:364:28\n    │\n364 │         received = uint256(uint128(outputDelta));\n    │                            ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:403:9\n    │\n403 │         emit XTraded(payer, X_V3, xIn, xOut, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:394:13\n    │\n394 │             int256(x.amountIn),\n    │             ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:399:25\n    │\n399 │         uint256 spent = uint256(zeroForOne ? a0 : a1);\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/MarginaliaTreasury.sol:51:9\n   │\n51 │         emit Dripped(day, amount);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/MarginaliaTreasury.sol:43:22\n   │\n43 │         uint32 day = uint32(block.timestamp / 1 days);\n   │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint32' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:409:78\n    │\n409 │         if (amount0Delta > 0) IERC20(pool.token0()).safeTransfer(msg.sender, uint256(amount0Delta));\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/MarginaliaRouter.sol:410:78\n    │\n410 │         if (amount1Delta > 0) IERC20(pool.token1()).safeTransfer(msg.sender, uint256(amount1Delta));\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:438:9\n    │\n438 │         emit XTraded(payer, X_V2, xIn, xOut, actualIn, received);\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/MarginaliaRouter.sol:426:37\n    │\n426 │         (uint112 r0, uint112 r1,) = pair.getReserves();\n    │                                     ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n   ╭▸ src/MarginaliaJudge.sol:96:17\n   │\n96 │             try hook.sellPotMarg(marg) returns (uint256 out) {\n   │                 ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n   ╭▸ src/MarginaliaJudge.sol:96:17\n   │\n96 │             try hook.sellPotMarg(marg) returns (uint256 out) {\n   │                 ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:114:47\n    │\n114 │         for (uint256 i = 0; i < all.length && n < MAX_JUDGED; ++i) {\n    │                                               ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaJudge.sol:115:35\n    │\n115 │             (,,, bool hasChild) = hook.noteMeta(all[i]);\n    │                                   ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaJudge.sol:115:35\n    │\n115 │             (,,, bool hasChild) = hook.noteMeta(all[i]);\n    │                                   ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:170:15\n    │\n170 │             ++n;\n    │               ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaJudge.sol:174:33\n    │\n174 │             out[i - 1] = bytes1(uint8(48 + v % 10));\n    │                                 ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaJudge.sol:186:52\n    │\n186 │         return eligibleTheses(week).length == 0 || block.timestamp >= (uint256(week) + 1) * 7 days + 28 days;\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/MarginaliaJudge.sol:194:32\n    │\n194 │         if (judgedSet[week] || block.timestamp < requestedAt[week] + ANSWER_DEADLINE) {\n    │                                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-no-eth]: external call can be reentered before `requestOf` is updated\n    ╭▸ src/MarginaliaJudge.sol:214:9\n    │\n214 │         hook.drawForJudging(day, price, retry);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `requestOf` is updated\n    ╭▸ src/MarginaliaJudge.sol:217:21\n    │\n217 │           requestId = intake.request(\n    │ ┏━━━━━━━━━━━━━━━━━━━━━┛\n218 │ ┃             action, body, IIntake.Callback(address(this), this.onOracleResult.selector), imd, price\n219 │ ┃         );\n    │ ┗━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaJudge.sol:206:41\n    │\n206 │         if (judgedSet[day] || (retry && block.timestamp < requestedAt[day] + ANSWER_DEADLINE)) {\n    │                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaJudge.sol:225:9\n    │\n225 │         emit Requested(day, requestId, price);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaJudge.sol:223:28\n    │\n223 │         requestedAt[day] = uint64(block.timestamp);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaJudge.sol:255:9\n    │\n255 │ ┏         emit Judged(\n256 │ ┃             day,\n257 │ ┃             [\n258 │ ┃                 count > 0 ? ranked[0] : bytes32(0),\n    ‡ ┃\n262 │ ┃         );\n    │ ┗━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:269:50\n    │\n269 │         for (uint256 i = 0; i < ranked.length && kept < 3; ++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/MarginaliaJudge.sol:276:17\n    │\n276 │             if (dup) continue;\n    │                 ━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaJudge.sol:270:77\n    │\n270 │             (address author, uint32 noteWeek, bool thesis, bool hasChild) = hook.noteMeta(ranked[i]);\n    │                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/MarginaliaJudge.sol:288:9\n    │\n288 │         hook.payJudged(day, top);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:295:21\n    │\n295 │                 if (uint256(-params.amountSpecified) <= STAMP * 2) revert NoteTooSmall();\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/MarginaliaHook.sol:303:17\n    │\n303 │             if (uint256(-params.amountSpecified) <= depositMarg * 2) revert NoteTooSmall();\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/MarginaliaHook.sol:309:30\n    │\n309 │             specifiedTake = (uint256(params.amountSpecified) * bps + (10_000 - bps) - 1) / (10_000 - bps);\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:389:9\n    │\n389 │         emit Accrued(day, 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/MarginaliaHook.sol:463:9\n    │\n463 │ ┏         emit NotePosted(\n464 │ ┃             id,\n465 │ ┃             author,\n466 │ ┃             p.x,\n    ‡ ┃\n475 │ ┃             p.text\n476 │ ┃         );\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/MarginaliaHook.sol:341:13\n    │\n341 │             emit SwapFee(true, author, poolImd, 0, STAMP);\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/MarginaliaHook.sol:357:13\n    │\n357 │             emit SwapFee(false, author, poolImd, fee - STAMP, STAMP);\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/MarginaliaHook.sol:376:9\n    │\n376 │         emit SwapFee(false, tx.origin, poolImd, quietFee, 0);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:326:33\n    │\n326 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\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/MarginaliaHook.sol:326:41\n    │\n326 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\n    │                                         ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:326:63\n    │\n326 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\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/MarginaliaHook.sol:326:71\n    │\n326 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\n    │                                                                       ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:331:29\n    │\n331 │             uint256 netIn = uint256(-params.amountSpecified) - STAMP;\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/MarginaliaHook.sol:333:31\n    │\n333 │             uint256 margOut = uint256(uint128(margDelta));\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/MarginaliaHook.sol:333:39\n    │\n333 │             uint256 margOut = uint256(uint128(margDelta));\n    │                                       ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:366:25\n    │\n366 │             quietFee = (uint256(params.amountSpecified) * bps + (10_000 - bps) - 1) / (10_000 - bps);\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/MarginaliaHook.sol:367:28\n    │\n367 │             if (poolImd != uint256(params.amountSpecified) + quietFee) revert PartialFill();\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:449:17\n    │\n449 │             if (weekTheses[_week()].length >= MAX_WEEK_THESES) revert InvalidNote();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:441:22\n    │\n441 │         n.postedAt = uint64(block.timestamp);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe 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/MarginaliaHook.sol:497:13\n    │\n497 │         if (block.timestamp < end) revert TooEarly();\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/MarginaliaHook.sol:498:13\n    │\n498 │         if (block.timestamp > end + SETTLE_WINDOW) revert TooLate();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:511:9\n    │\n511 │         emit Observed(id, uint64(block.timestamp), xRead, quoteRead, balance);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:503:27\n    │\n503 │             T.Observation(uint64(block.timestamp), uint64(block.number), xRead, quoteRead, balance);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:503:52\n    │\n503 │             T.Observation(uint64(block.timestamp), uint64(block.number), xRead, quoteRead, balance);\n    │                                                    ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:511:27\n    │\n511 │         emit Observed(id, uint64(block.timestamp), xRead, quoteRead, balance);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[return-bomb]: external call with a gas limit may copy unbounded return data\n    ╭▸ src/MarginaliaHook.sol:519:13\n    │\n519 │             x.staticcall{gas: BALANCE_READ_GAS}(abi.encodeWithSelector(IERC20.balanceOf.selector, who));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/return-bomb\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaHook.sol:606:35\n    │\n606 │         emit Settled(id, outcome, settlePrice, scoreDelta, msg.sender);\n    │                                   ━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:556:13\n    │\n556 │         if (block.timestamp <= end + SETTLE_WINDOW) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:676:13\n    │\n676 │             emit ThesisReleased(n.parentId);\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/MarginaliaHook.sol:606:9\n    │\n606 │         emit Settled(id, outcome, settlePrice, scoreDelta, msg.sender);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:588:26\n    │\n588 │             scoreDelta = int256(_difficulty(n));\n    │                          ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:593:27\n    │\n593 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:595:27\n    │\n595 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:599:27\n    │\n599 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:614:13\n    │\n614 │         if (block.timestamp >= horizonEnd(id)) revert TooLate();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:623:9\n    │\n623 │         emit Retracted(id, text);\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/MarginaliaHook.sol:624:9\n    │\n624 │         emit Settled(id, T.Status.Retracted, 0, scoreDelta, address(0));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:616:30\n    │\n616 │         int256 scoreDelta = -int256(_difficulty(n) / 2);\n    │                              ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/MarginaliaHook.sol:632:13\n    │\n632 │         if (block.timestamp <= uint256(n.postedAt) + THESIS_GRACE) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:635:9\n    │\n635 │         emit ThesisForfeited(id);\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/MarginaliaHook.sol:653:9\n    │\n653 │         emit DepositClaimed(id, n.author, asImd, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:695:16\n    │\n695 │         return uint32(block.timestamp / 1 days);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:699:16\n    │\n699 │         return uint32(block.timestamp / 7 days);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:720:38\n    │\n720 │         uint256 prevPos = prev > 0 ? uint256(prev) : 0;\n    │                                      ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:721:38\n    │\n721 │         uint256 nextPos = next > 0 ? uint256(next) : 0;\n    │                                      ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:731:9\n    │\n731 │         emit PotFunded(_today(), amount, msg.sender);\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/MarginaliaHook.sol:743:9\n    │\n743 │         emit PotMargSold(amount, imdOut, _today());\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:763:27\n    │\n763 │         return (n.author, uint32(uint256(n.postedAt) / 7 days), n.targetBps == 0, n.children > 0);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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 `thesisPool` is updated\n    ╭▸ src/MarginaliaHook.sol:862:28\n    │\n862 │         bytes memory out = poolManager.unlock(data);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaHook.sol:862:28\n    │\n862 │         bytes memory out = poolManager.unlock(data);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:785:9\n    │\n785 │         emit JudgedPaid(w, paidAmounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/MarginaliaHook.sol:863:39\n    │\n863 │         if (unlockHash != bytes32(0)) revert InvalidUnlock();\n    │                                       ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:793:47\n    │\n793 │         uint256 share = FullMath.mulDiv(pool, uint256(s), weekTotal[w]);\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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:799:13\n    │\n799 │         if (w >= _week()) revert TooEarly();\n    │             ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:806:9\n    │\n806 │         emit LeaderboardClaimed(w, msg.sender, amount);\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/MarginaliaHook.sol:813:13\n    │\n813 │         if (n.day >= _today()) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:823:9\n    │\n823 │         emit RefundClaimed(id, msg.sender, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:821:30\n    │\n821 │         notesPerDay[n.day] = uint32(count - 1);\n    │                              ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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/MarginaliaHook.sol:832:17\n    │\n832 │             if (block.timestamp < (uint256(epoch) + 1) * 1 days + SWEEP_AFTER) revert TooEarly();\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/MarginaliaHook.sol:836:17\n    │\n836 │             if (block.timestamp < (uint256(epoch) + 1) * 7 days + SWEEP_AFTER) revert TooEarly();\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/MarginaliaHook.sol:840:17\n    │\n840 │             if (block.timestamp < (uint256(epoch) + 1) * 7 days + SWEEP_AFTER) revert TooEarly();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:873:40\n    │\n873 │             address currency = address(uint160(extra));\n    │                                        ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint160' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaHook.sol:882:13\n    │\n882 │             poolManager.settle();\n    │             ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:892:22\n    │\n892 │                     -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/MarginaliaHook.sol:901:17\n    │\n901 │             if (uint256(uint128(-margDelta)) != amount) revert InvalidUnlock();\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/MarginaliaHook.sol:901:25\n    │\n901 │             if (uint256(uint128(-margDelta)) != amount) revert InvalidUnlock();\n    │                         ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:903:30\n    │\n903 │             uint256 imdOut = uint256(uint128(imdDelta));\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/MarginaliaHook.sol:903:38\n    │\n903 │             uint256 imdOut = uint256(uint128(imdDelta));\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[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n   ╭▸ test/AuditFindings.t.sol:19:30\n   │\n19 │         uint256 startBlock = block.number;\n   │                              ━━━━━━━━━━━━\n   ‡\n23 │             vm.roll(startBlock + 25 * (i + 1));\n   │             ────────────────────────────────── `vm.roll` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockNumber()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/AuditFindings.t.sol:20:27\n   │\n20 │         uint256 startTs = block.timestamp;\n   │                           ━━━━━━━━━━━━━━━\n   ‡\n24 │             vm.warp(startTs + 31 minutes * (i + 1));\n   │             ─────────────────────────────────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/AuditFindings.t.sol:18:9\n    │\n 18 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/AuditFindings.t.sol:65:9\n    │\n 65 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/AuditFindings.t.sol:65:17\n   │\n65 │         vm.warp(block.timestamp + 7 days);\n   │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:130:9\n    │\n130 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:131:30\n    │\n131 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n135 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:132:27\n    │\n132 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n136 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:158:9\n    │\n158 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:159:30\n    │\n159 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n163 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:160:27\n    │\n160 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n164 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:182:9\n    │\n182 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:183:30\n    │\n183 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n187 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:184:27\n    │\n184 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n188 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:278:9\n    │\n278 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:278:17\n    │\n278 │         vm.warp(block.timestamp + 7 days);\n    │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:328:9\n    │\n328 │         vm.warp(hook.horizonEnd(a));\n    │         ─────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:329:30\n    │\n329 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n334 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:330:27\n    │\n330 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n335 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:408:9\n    │\n408 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:408:17\n    │\n408 │         vm.warp(block.timestamp + 7 days);\n    │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:475:9\n    │\n475 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:476:30\n    │\n476 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n479 │         vm.roll(startBlock + 25);\n    │         ──────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:477:27\n    │\n477 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n480 │         vm.warp(startTs + 30 minutes);\n    │         ───────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:499:9\n    │\n499 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:500:30\n    │\n500 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n504 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:501:27\n    │\n501 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n505 │             vm.warp(startTs + 10 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/RevisionFindings.t.sol:199:17\n    │\n199 │         vm.warp(block.timestamp + 1 hours);\n    │         ────────━━━━━━━━━━━━━━━─────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/RevisionFindings.t.sol:262:9\n    │\n262 │         vm.warp((uint256(w) + 1) * 7 days + 1);\n    │         ────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/Round3Findings.t.sol:67:17\n   │\n67 │         vm.warp(block.timestamp + 1 hours);\n   │         ────────━━━━━━━━━━━━━━━─────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\n","passed":true},{"durationMs":225,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/fork/MainnetLaunch.t.sol:MainnetLaunchTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 1.86ms (0.00ns CPU time)\n\nRan 7 tests for test/JudgeOracle.t.sol:JudgeOracleTest\n[PASS] testEmptySignedRankingIsAnExecutableNoWinnerResult() (gas: 248153)\n[PASS] testFiveIdsWithEoaSignatureFitStipend() (gas: 554052)\n[PASS] testFullRankingWithEoaSignatureFitsStipend() (gas: 633672)\n[PASS] testProtocolDigestSignatureAndSelectorConformanceOnClone() (gas: 3322442)\n[PASS] testRejectedAnswersDoNotConsumeThePendingRequest() (gas: 892875)\n[PASS] testRequestedHeadIsFilteredAndDeduplicatedWithoutPromotingTheTail() (gas: 250679)\n[PASS] testTimeoutRetryInvalidatesOldIntakeRequest() (gas: 523953)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 2.63ms (5.71ms CPU time)\n\nRan 7 tests for test/Pricer.t.sol:PricerTest\n[PASS] testQuoteLegIsAdverseEvenUnderAV3Twap() (gas: 28455)\n[PASS] testTwapRefusesZeroSpanAndV4() (gas: 17708)\n[PASS] testV2TwapFromWrappingCumulative() (gas: 9503)\n[PASS] testV3TwapOfAConstantTickIsThatTick() (gas: 15459)\n[PASS] testV3TwapRoundsNegativeMeansDown() (gas: 14848)\n[PASS] testV3TwapWeightsByTime() (gas: 14715)\n[PASS] testV4SettlesOnTheAdverseExtreme() (gas: 26636)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 10.11ms (762.38µs CPU time)\n\nRan 8 tests for test/PriceHistory.t.sol:PriceHistoryTest\n[PASS] testBaselineRequiresMatureFreshHistory() (gas: 188472)\n[PASS] testEmptyVenueAndHubCannotBeCheckpointedObservedOrPriced() (gas: 284549)\n[PASS] testFuzzV4BaselineIsNeverFavourableToTheCall(int24,bool) (runs: 256, μ: 106059, ~: 106150)\nLogs:\n  Bound result -86872\n\n[PASS] testHubBaselineUsesOppositeExtremeFromSettlement() (gas: 180334)\n[PASS] testLiveCheckpointCannotEraseHonestExtremesOrRestartTheClock() (gas: 224282)\n[PASS] testV2BaselineIgnoresSameBlockReservesDumpAndPumpBothOrientations() (gas: 467543)\n[PASS] testV3BaselineIgnoresSameBlockTickChangesBothOrientations() (gas: 418025)\n[PASS] testV3BaselineWeightsElapsedTime() (gas: 371037)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 10.10ms (11.45ms CPU time)\n\nRan 3 tests for test/Implementations.t.sol:ImplementationsTest\n[PASS] testClonesInitializeOnceOnlyFromTheirHook() (gas: 4551335)\n[PASS] testFactoryDeploysAllFourWithoutArgumentsOrExternalDependencies() (gas: 34608585)\nLogs:\n  four implementation CREATE2 deployments (gas): 8829579\n\n[PASS] testImplementationsRejectInitialization() (gas: 81376)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 35.70ms (36.36ms CPU time)\n\nRan 26 tests for test/Lifecycle.t.sol:LifecycleTest\n[PASS] testAttestedClassCannotBeSelfDeclared() (gas: 343124)\n[PASS] testCallbackSelectorPinned() (gas: 3361)\n[PASS] testFakeVenueIsRefused() (gas: 382714)\n[PASS] testFlagsAndBinding() (gas: 55923)\n[PASS] testForfeitsConvertToImdForThePot() (gas: 1118696)\n[PASS] testLeaderboardProRataWithCap() (gas: 3247485)\n[PASS] testNoDataRefunds() (gas: 999702)\n[PASS] testNoteTooSmall() (gas: 173034)\n[PASS] testNotedBuyTakesStampAndDeposit() (gas: 798269)\n[PASS] testNotedSellPaysOnePercentPlusStamp() (gas: 1107534)\n[PASS] testObservationsMustSpanAnHour() (gas: 1494821)\n[PASS] testPlainBuyTakesNothing() (gas: 230288)\n[PASS] testQuietSellPaysThreePercent() (gas: 336561)\n[PASS] testQuietThesisPoolSweeps() (gas: 305757)\n[PASS] testRetract() (gas: 951734)\n[PASS] testRightCallReturnsDepositAsImd() (gas: 1804313)\n[PASS] testSellingEarlyBreaksTheCall() (gas: 1772740)\n[PASS] testThesisParentChild() (gas: 1515324)\n[PASS] testThesisWithoutChildForfeits() (gas: 796971)\n[PASS] testTreasuryDrip() (gas: 348158)\n[PASS] testTwoBlockPumpObserveUnwindSettlesWrong() (gas: 1804300)\n[PASS] testUnansweredWeekCanBeRetried() (gas: 2441273)\n[PASS] testUpOnlyIsRefused() (gas: 340732)\n[PASS] testWeeklyThesisJudging() (gas: 3855108)\n[PASS] testWriterRefundCappedAtStamp() (gas: 1717001)\n[PASS] testWrongCallForfeitsWithKeeperReward() (gas: 1562166)\nSuite result: ok. 26 passed; 0 failed; 0 skipped; finished in 71.90ms (29.68ms CPU time)\n\nRan 8 tests for test/AuditFindings.t.sol:AuditFindingsTest\n[PASS] testConversionAfterARealPriceFallNeedsAFreshMatureWindow() (gas: 2244515)\n[PASS] testEmptyV4ObservationIsRefused() (gas: 1028673)\n[PASS] testExpiredBaselineRejectsPostWithoutTakingFunds() (gas: 643517)\n[PASS] testForfeitureConversionRejectsSameBlockDump() (gas: 2224133)\n[PASS] testLongRankingFitsIntakeStipend() (gas: 2192588)\n[PASS] testSameBlockDumpPostUnwindDoesNotWinBuy() (gas: 1916921)\n[PASS] testSameBlockPumpPostUnwindDoesNotWinSell() (gas: 1785783)\n[PASS] testUnpayableRankingRollsTheWholePoolForward() (gas: 2465804)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 91.08ms (11.05ms CPU time)\n\nRan 2 tests for test/PotTranche.t.sol:PotTrancheTest\n[PASS] testForfeitedPotCanStillBeConvertedOnceItOutgrowsOneSale() (gas: 49910278)\nLogs:\n  potMarg: 36877975912613201326\n  imdOut: 10344028156678390861\n\n[PASS] testWhenNoTrancheSellsTheHookReasonSurfaces() (gas: 1266289)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 116.79ms (29.66ms CPU time)\n\nRan 10 tests for test/RevisionFindings.t.sol:RevisionFindingsTest\n[PASS] testABuyBackNoLongerVoidsASellCallItSettlesOnPrice() (gas: 1751715)\n[PASS] testADustPricedV4VenueCannotBePostedOn() (gas: 1635894)\n[PASS] testARevertingBalanceOfVoidsTheCallAsSoldNotAsNoData() (gas: 2639306)\n[PASS] testAStrangersDustTransferDoesNotVoidASellCall() (gas: 1695773)\n[PASS] testAnAttestationAboutAnotherChainIsRefused() (gas: 2324761)\n[PASS] testAnEmptyCanonicalV3PoolIsRefusedAsAVenue() (gas: 567946)\n[PASS] testHonestObserverOverwritesAPumpObserveUnwindInTheNextBlock() (gas: 3785409)\n[PASS] testPricerRefusesAPriceThatRoundsToZeroInBothOrientations() (gas: 58712)\n[PASS] testSweepNeedsTheStaleRequestAbandonedAndALateAnswerIsThenRefused() (gas: 2449618)\n[PASS] testTheHundredAndTwentyFirstThesisOfAWeekIsRefusedBeforePayment() (gas: 55395690)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 118.16ms (42.93ms CPU time)\n\nRan 10 tests for test/Round3Findings.t.sol:Round3FindingsTest\n[PASS] testABuyCallStillBreaksWhenTheAuthorSells() (gas: 1764134)\n[PASS] testAGiftOfAnySizeDoesNotVoidACorrectSellCall() (gas: 1710155)\n[PASS] testAGiftWorthTheDepositDoesNotVoidACorrectSellCall() (gas: 1810035)\n[PASS] testALaunchPoolCallStillScoresAndPaysTheLeaderboard() (gas: 1570750)\n[PASS] testASelfPricedVenueDrawsNothingFromTheLeaderboard() (gas: 2972803)\n[PASS] testAWrongCallOnAnotherVenueStillForfeitsButBooksNoScore() (gas: 2760625)\n[PASS] testAWrongSellCallStillForfeits() (gas: 1495739)\n[PASS] testFuzzSqrtIsTheIntegerFloor(uint256) (runs: 256, μ: 22077, ~: 19781)\n[PASS] testRetractingACallOnAnotherVenueBooksNoScore() (gas: 2004799)\n[PASS] testSqrtFloorsSmallInputs() (gas: 9204519)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 118.13ms (22.65ms CPU time)\n\nRan 10 test suites in 119.15ms (576.47ms CPU time): 81 tests passed, 0 failed, 1 skipped (82 total tests)\n","passed":true},{"durationMs":89,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"Marginalia.approve(address,uint256)\",\"Marginalia.transfer(address,uint256)\",\"Marginalia.transferFrom(address,address,uint256)\",\"MarginaliaHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"MarginaliaHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"MarginaliaHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"MarginaliaHook.claimDeposit(bytes32,bool)\",\"MarginaliaHook.claimLeaderboard(uint32)\",\"MarginaliaHook.claimRefund(bytes32)\",\"MarginaliaHook.drawForJudging(uint32,uint256,bool)\",\"MarginaliaHook.fundPot(uint256)\",\"MarginaliaHook.observe(bytes32)\",\"MarginaliaHook.payJudged(uint32,bytes32[3])\",\"MarginaliaHook.retract(bytes32,string)\",\"MarginaliaHook.sellPotMarg(uint256)\",\"MarginaliaHook.settle(bytes32)\",\"MarginaliaHook.settleThesis(bytes32)\",\"MarginaliaHook.sweep(uint8,uint32)\",\"MarginaliaHook.unlockCallback(bytes)\",\"MarginaliaJudge.abandonRequest(uint32)\",\"MarginaliaJudge.convertForfeits()\",\"MarginaliaJudge.init(address,address,bytes32,address)\",\"MarginaliaJudge.onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"MarginaliaJudge.payJudged(uint32)\",\"MarginaliaJudge.requestJudging(uint32)\",\"MarginaliaRouter.checkpointVenue((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address))\",\"MarginaliaRouter.init(address,address)\",\"MarginaliaRouter.note((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address),uint256,uint256,uint256)\",\"MarginaliaRouter.sellWithNote((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address),uint256,uint256,uint256)\",\"MarginaliaRouter.uniswapV3SwapCallback(int256,int256,bytes)\",\"MarginaliaRouter.unlockCallback(bytes)\",\"MarginaliaTreasury.drip()\",\"MarginaliaTreasury.init(address)\"],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":215,\"README.md\":154,\"SPEC.md\":264,\"dependencies.json\":28,\"foundry.toml\":21,\"helper/.gitignore\":3,\"helper/package-lock.json\":737,\"helper/package.json\":20,\"helper/public/index.html\":82,\"helper/server.js\":90,\"helper/src/app.js\":203,\"jobs/launch-1-hook.json\":43,\"jobs/launch-2-contracts.json\":38,\"jobs/launch-A-implementations.json\":47,\"jobs/launch-A2-implementations.json\":41,\"jobs/launch-hook-v3.json\":43,\"remappings.txt\":4,\"src/HookFlags.sol\":33,\"src/Marginalia.sol\":12,\"src/MarginaliaHook.sol\":925,\"src/MarginaliaImpls.sol\":14,\"src/MarginaliaJudge.sol\":290,\"src/MarginaliaPricer.sol\":305,\"src/MarginaliaRouter.sol\":446,\"src/MarginaliaTreasury.sol\":53,\"src/MarginaliaTypes.sol\":108,\"src/OracleAttestation.sol\":221,\"src/interfaces/IIntake.sol\":15,\"src/interfaces/ILaunchFactory.sol\":49,\"test/AuditFindings.t.sol\":178,\"test/Implementations.t.sol\":96,\"test/JudgeOracle.t.sol\":270,\"test/Lifecycle.t.sol\":511,\"test/PotTranche.t.sol\":189,\"test/PriceHistory.t.sol\":233,\"test/Pricer.t.sol\":88,\"test/RevisionFindings.t.sol\":318,\"test/Round3Findings.t.sol\":214,\"test/fork/MainnetLaunch.t.sol\":382,\"test/helpers/Fixture.sol\":278,\"test/mocks/MockERC20.sol\":13},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":11595,"exitCode":0,"name":"slither","output":"[high/medium] weak-prng at src/MarginaliaPricer.sol:205: MarginaliaPricer.twap(MarginaliaTypes.VenueKind,bool,uint256,uint64,uint256,uint64) (src/MarginaliaPricer.sol#205-229) uses a weak PRNG: \"delta < 0 && delta % int256(dt) != 0 (src/MarginaliaPricer.sol#215)\"\n[high/medium] reentrancy-balance at src/MarginaliaRouter.sol:414: Reentrancy in MarginaliaRouter._tradeV2(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#414-439):\n[high/medium] reentrancy-balance at src/MarginaliaRouter.sol:414: Reentrancy in MarginaliaRouter._tradeV2(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#414-439):\n[high/medium] reentrancy-balance at src/MarginaliaRouter.sol:377: Reentrancy in MarginaliaRouter._tradeV3(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#377-404):\n[high/medium] reentrancy-balance at src/MarginaliaRouter.sol:377: Reentrancy in MarginaliaRouter._tradeV3(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#377-404):\n[high/medium] reentrancy-balance at src/MarginaliaRouter.sol:414: Reentrancy in MarginaliaRouter._tradeV2(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#414-439):\n[high/medium] reentrancy-balance at src/MarginaliaRouter.sol:287: Reentrancy in MarginaliaRouter._pull(address,uint256) (src/MarginaliaRouter.sol#287-292):\n[high/high] uninitialized-state at src/MarginaliaHook.sol:493: MarginaliaHook.observations (src/MarginaliaHook.sol#97) is never initialized. It is used in:\n[medium/high] incorrect-equality at src/MarginaliaPricer.sol:295: MarginaliaPricer.fromSqrt(uint160,bool) (src/MarginaliaPricer.sol#295-304) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaHook.sol:856: MarginaliaHook._unlock(uint8,address,uint256,uint256) (src/MarginaliaHook.sol#856-865) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:377: MarginaliaRouter._tradeV3(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#377-404) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaHook.sol:403: MarginaliaHook._postNote(address,MarginaliaTypes.NoteParams,uint256,uint256,uint256) (src/MarginaliaHook.sol#403-477) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:414: MarginaliaRouter._tradeV2(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#414-439) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaHook.sol:798: MarginaliaHook.claimLeaderboard(uint32) (src/MarginaliaHook.sol#798-807) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:299: MarginaliaRouter.unlockCallback(bytes) (src/MarginaliaRouter.sol#299-340) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:294: MarginaliaRouter._checkSubject(MarginaliaRouter.Job) (src/MarginaliaRouter.sol#294-297) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaPricer.sol:295: MarginaliaPricer.fromSqrt(uint160,bool) (src/MarginaliaPricer.sol#295-304) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaPricer.sol:176: MarginaliaPricer.settlePrice(MarginaliaTypes.Venue,bool,MarginaliaTypes.Observation[]) (src/MarginaliaPricer.sol#176-201) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaHook.sol:528: MarginaliaHook._broken(MarginaliaTypes.Note,uint256) (src/MarginaliaHook.sol#528-531) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:287: MarginaliaRouter._pull(address,uint256) (src/MarginaliaRouter.sol#287-292) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaPricer.sol:205: MarginaliaPricer.twap(MarginaliaTypes.VenueKind,bool,uint256,uint64,uint256,uint64) (src/MarginaliaPricer.sol#205-229) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaTreasury.sol:42: MarginaliaTreasury.drip() (src/MarginaliaTreasury.sol#42-52) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaHook.sol:829: MarginaliaHook.sweep(uint8,uint32) (src/MarginaliaHook.sol#829-848) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaTreasury.sol:42: MarginaliaTreasury.drip() (src/MarginaliaTreasury.sol#42-52) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:414: MarginaliaRouter._tradeV2(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#414-439) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaPricer.sol:135: MarginaliaPricer.postPrice(IPoolManager,MarginaliaTypes.Venue,address,bool,MarginaliaTypes.PriceWindow) (src/MarginaliaPricer.sol#135-155) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaRouter.sol:242: MarginaliaRouter._run(bool,uint256,uint256,uint256,MarginaliaRouter.XTrade,MarginaliaTypes.NoteParams,PoolKey) (src/MarginaliaRouter.sol#242-284) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/MarginaliaPricer.sol:295: MarginaliaPricer.fromSqrt(uint160,bool) (src/MarginaliaPricer.sol#295-304) uses a dangerous strict equality:\n[medium/medium] reentrancy-no-eth at src/MarginaliaHook.sol:767: Reentrancy in MarginaliaHook.payJudged(uint32,bytes32[3]) (src/MarginaliaHook.sol#767-786):\n[medium/medium] reentrancy-no-eth at src/MarginaliaHook.sol:552: Reentrancy in MarginaliaHook.settle(bytes32) (src/MarginaliaHook.sol#552-607):\n[medium/medium] reentrancy-no-eth at src/MarginaliaJudge.sol:203: Reentrancy in MarginaliaJudge.requestJudging(uint32) (src/MarginaliaJudge.sol#203-226):\n[medium/medium] reentrancy-no-eth at src/MarginaliaHook.sol:610: Reentrancy in MarginaliaHook.retract(bytes32,string) (src/MarginaliaHook.sol#610-625):\n[medium/medium] uninitialized-local at src/MarginaliaRouter.sol:179: MarginaliaRouter.sellWithNote(MarginaliaTypes.NoteParams,PoolKey,uint256,uint256,uint256).noX (src/MarginaliaRouter.sol#179) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaJudge.sol:127: MarginaliaJudge.questionBody(uint32).allow (src/MarginaliaJudge.sol#127) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaHook.sol:560: MarginaliaHook.settle(bytes32).settlePrice (src/MarginaliaHook.sol#560) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaRouter.sol:166: MarginaliaRouter.note(MarginaliaTypes.NoteParams,PoolKey,uint256,uint256,uint256).noX (src/MarginaliaRouter.sol#166) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaRouter.sol:257: MarginaliaRouter._run(bool,uint256,uint256,uint256,MarginaliaRouter.XTrade,MarginaliaTypes.NoteParams,PoolKey).job (src/MarginaliaRouter.sol#257) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaJudge.sol:113: MarginaliaJudge.eligibleTheses(uint32).n (src/MarginaliaJudge.sol#113) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaRouter.sol:205: MarginaliaRouter.validateVenue(MarginaliaTypes.NoteParams,PoolKey).t1 (src/MarginaliaRouter.sol#205) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaJudge.sol:272: MarginaliaJudge.judgedOf(uint32).dup (src/MarginaliaJudge.sol#272) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaJudge.sol:268: MarginaliaJudge.judgedOf(uint32).kept (src/MarginaliaJudge.sol#268) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaHook.sol:774: MarginaliaHook.payJudged(uint32,bytes32[3]).paidAmounts (src/MarginaliaHook.sol#774) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaJudge.sol:168: MarginaliaJudge._dec(uint256).n (src/MarginaliaJudge.sol#168) is a local variable never initialized\n[medium/medium] uninitialized-local at src/MarginaliaRouter.sol:204: MarginaliaRouter.validateVenue(MarginaliaTypes.NoteParams,PoolKey).t0 (src/MarginaliaRouter.sol#204) is a local variable never initialized\n[medium/medium] unused-return at src/MarginaliaHook.sol:277: MarginaliaHook.margPriceInImd() (src/MarginaliaHook.sol#277-280) ignores return value by (sqrtP,None,None,None) = poolManager.getSlot0(poolId) (src/MarginaliaHook.sol#278)\n[medium/medium] unused-return at src/MarginaliaPricer.sol:255: MarginaliaPricer._quoteSpot(IPoolManager,address,address) (src/MarginaliaPricer.sol#255-264) ignores return value by (sqrtP,None,None,None) = manager.getSlot0(PoolId.wrap(HUB_POOL_ID)) (src/MarginaliaPricer.sol#260)\n[medium/medium] unused-return at src/MarginaliaPricer.sol:233: MarginaliaPricer._spotInQuote(IPoolManager,MarginaliaTypes.Venue) (src/MarginaliaPricer.sol#233-252) ignores return value by (r0,r1,None) = IUniswapV2PairOracle(ref).getReserves() (src/MarginaliaPricer.sol#245)\n[medium/medium] unused-return at src/MarginaliaHook.sol:867: MarginaliaHook.unlockCallback(bytes) (src/MarginaliaHook.sol#867-913) ignores return value by poolManager.settle() (src/MarginaliaHook.sol#882)\n[medium/medium] unused-return at src/MarginaliaJudge.sol:110: MarginaliaJudge.eligibleTheses(uint32) (src/MarginaliaJudge.sol#110-122) ignores return value by (None,None,None,hasChild) = hook.noteMeta(all[i]) (src/MarginaliaJudge.sol#115)\n[medium/medium] unused-return at src/MarginaliaPricer.sol:233: MarginaliaPricer._spotInQuote(IPoolManager,MarginaliaTypes.Venue) (src/MarginaliaPricer.sol#233-252) ignores return value by (sqrtP_scope_0,None,None,None,None,None,None) = IUniswapV3PoolOracle(ref).slot0() (src/MarginaliaPricer.sol#241)\n[medium/medium] unused-return at src/MarginaliaRouter.sol:414: MarginaliaRouter._tradeV2(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#414-439) ignores return value by (r0,r1,None) = pair.getReserves() (src/MarginaliaRouter.sol#426)\n[medium/medium] unused-return at src/MarginaliaPricer.sol:267: MarginaliaPricer._v3Cumulative(address) (src/MarginaliaPricer.sol#267-271) ignores return value by (cum,None) = IUniswapV3PoolOracle(pool).observe(ago) (src/MarginaliaPricer.sol#269)\n[medium/medium] unused-return at src/MarginaliaPricer.sol:233: MarginaliaPricer._spotInQuote(IPoolManager,MarginaliaTypes.Venue) (src/MarginaliaPricer.sol#233-252) ignores return value by (sqrtP,None,None,None) = manager.getSlot0(PoolId.wrap(v.ref)) (src/MarginaliaPricer.sol#237)\n[low/high] shadowing-local at src/MarginaliaHook.sol:792: MarginaliaHook.leaderboardShare(uint32,address).pool (src/MarginaliaHook.sol#792) shadows:\n[low/high] shadowing-local at src/MarginaliaHook.sol:771: MarginaliaHook.payJudged(uint32,bytes32[3]).pool (src/MarginaliaHook.sol#771) shadows:\n[low/high] shadowing-local at src/MarginaliaHook.sol:706: MarginaliaHook._accrue(uint256).week (src/MarginaliaHook.sol#383) shadows:\n[low/high] shadowing-local at src/MarginaliaJudge.sol:14: IHookJudge.noteMeta(bytes32).week (src/MarginaliaJudge.sol#19) shadows:\n[low/high] shadowing-local at src/MarginaliaJudge.sol:14: IHookJudge.thesesOfWeek(uint32).week (src/MarginaliaJudge.sol#15) shadows:\n[low/high] shadowing-local at src/MarginaliaJudge.sol:14: IHookJudge.thesisPool(uint32).week (src/MarginaliaJudge.sol#12) shadows:\n[low/high] shadowing-local at src/MarginaliaJudge.sol:14: IHookJudge.drawForJudging(uint32,uint256,bool).week (src/MarginaliaJudge.sol#21) shadows:\n[low/medium] calls-loop at src/MarginaliaJudge.sol:110: MarginaliaJudge.eligibleTheses(uint32) (src/MarginaliaJudge.sol#110-122) has external calls inside a loop: (None,None,None,hasChild) = hook.noteMeta(all[i]) (src/MarginaliaJudge.sol#115)\n[low/medium] calls-loop at src/MarginaliaJudge.sol:110: MarginaliaJudge.eligibleTheses(uint32) (src/MarginaliaJudge.sol#110-122) has external calls inside a loop: (None,None,None,hasChild) = hook.noteMeta(all[i]) (src/MarginaliaJudge.sol#115)\n[low/medium] calls-loop at src/MarginaliaJudge.sol:266: MarginaliaJudge.judgedOf(uint32) (src/MarginaliaJudge.sol#266-279) has external calls inside a loop: (author,noteWeek,thesis,hasChild) = hook.noteMeta(ranked[i]) (src/MarginaliaJudge.sol#270)\n[low/medium] calls-loop at src/MarginaliaHook.sol:856: MarginaliaHook._unlock(uint8,address,uint256,uint256) (src/MarginaliaHook.sol#856-865) has external calls inside a loop: out = poolManager.unlock(data) (src/MarginaliaHook.sol#862)\n[low/medium] calls-loop at src/MarginaliaJudge.sol:91: MarginaliaJudge.convertForfeits() (src/MarginaliaJudge.sol#91-106) has external calls inside a loop: out = hook.sellPotMarg(marg) (src/MarginaliaJudge.sol#96-100)\n[low/medium] calls-loop at src/MarginaliaJudge.sol:266: MarginaliaJudge.judgedOf(uint32) (src/MarginaliaJudge.sol#266-279) has external calls inside a loop: (author,noteWeek,thesis,hasChild) = hook.noteMeta(ranked[i]) (src/MarginaliaJudge.sol#270)\n[low/medium] calls-loop at src/MarginaliaJudge.sol:110: MarginaliaJudge.eligibleTheses(uint32) (src/MarginaliaJudge.sol#110-122) has external calls inside a loop: (None,None,None,hasChild) = hook.noteMeta(all[i]) (src/MarginaliaJudge.sol#115)\n[low/medium] calls-loop at src/MarginaliaJudge.sol:110: MarginaliaJudge.eligibleTheses(uint32) (src/MarginaliaJudge.sol#110-122) has external calls inside a loop: (None,None,None,hasChild) = hook.noteMeta(all[i]) (src/MarginaliaJudge.sol#115)\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:552: Reentrancy in MarginaliaHook.settle(bytes32) (src/MarginaliaHook.sol#552-607):\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:735: Reentrancy in MarginaliaHook.sellPotMarg(uint256) (src/MarginaliaHook.sol#735-744):\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:726: Reentrancy in MarginaliaHook.fundPot(uint256) (src/MarginaliaHook.sol#726-732):\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:314: Reentrancy in MarginaliaHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/MarginaliaHook.sol#314-378):\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:314: Reentrancy in MarginaliaHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/MarginaliaHook.sol#314-378):\n[low/medium] reentrancy-benign at src/MarginaliaRouter.sol:377: Reentrancy in MarginaliaRouter._tradeV3(address,MarginaliaRouter.XTrade) (src/MarginaliaRouter.sol#377-404):\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:314: Reentrancy in MarginaliaHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/MarginaliaHook.sol#314-378):\n[low/medium] reentrancy-benign at src/MarginaliaHook.sol:661: Reentrancy in MarginaliaHook._forfeit(MarginaliaTypes.Note,address) (src/MarginaliaHook.sol#661-668):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:735: Reentrancy in MarginaliaHook.sellPotMarg(uint256) (src/MarginaliaHook.sol#735-744):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:610: Reentrancy in MarginaliaHook.retract(bytes32,string) (src/MarginaliaHook.sol#610-625):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:552: Reentrancy in MarginaliaHook.settle(bytes32) (src/MarginaliaHook.sol#552-607):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:628: Reentrancy in MarginaliaHook.settleThesis(bytes32) (src/MarginaliaHook.sol#628-636):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:314: Reentrancy in MarginaliaHook.afterSwap(address,PoolKey,SwapParams,BalanceDelta,bytes) (src/MarginaliaHook.sol#314-378):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:798: Reentrancy in MarginaliaHook.claimLeaderboard(uint32) (src/MarginaliaHook.sol#798-807):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:767: Reentrancy in MarginaliaHook.payJudged(uint32,bytes32[3]) (src/MarginaliaHook.sol#767-786):\n[low/medium] reentrancy-events at src/MarginaliaHook.sol:639: Reentrancy in MarginaliaHook.claimDeposit(bytes32,bool) (src/MarginaliaHook.sol#639-654):\n[low/medium] reentrancy-events at s","passed":true},{"durationMs":902,"exitCode":0,"name":"aderyn","output":"[high] eth-send-unchecked-address at src/MarginaliaHook.sol:726: ETH transferred without address checks (3 places)\n[high] reentrancy-state-change at src/MarginaliaHook.sol:207: Reentrancy: State change after external call (14 places)\n[high] storage-array-memory-edit at src/MarginaliaHook.sol:506: Storage Array Edited with Memory\n[low] costly-loop at src/MarginaliaHook.sol:776: Costly operations inside loop (2 places)\n[low] internal-function-used-once at src/HookFlags.sol:26: Internal Function Used Only Once (2 places)\n[low] large-numeric-literal at src/Marginalia.sol:10: Large Numeric Literal (23 places)\n[low] literal-instead-of-constant at src/MarginaliaHook.sol:302: Literal Instead of Constant (64 places)\n[low] local-variable-shadowing at src/MarginaliaHook.sol:771: Local Variable Shadows State Variable (2 places)\n[low] require-revert-in-loop at src/MarginaliaHook.sol:776: Loop Contains `require`/`revert`\n[low] state-change-without-event at src/MarginaliaHook.sol:282: State Change Without Event (7 places)\n[low] state-no-address-check at src/MarginaliaRouter.sol:135: Address State Variable Set Without Checks\n[low] unchecked-return at src/MarginaliaHook.sol:649: Unchecked Return (8 places)\n[low] uninitialized-local-variable at src/MarginaliaJudge.sol:168: Uninitialized Local Variable (2 places)","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"9d54985cca138cfd5a84a536c1f18ce09ca520d6e4eb972ab4cbc90a8aac7a78","verifiedTreeHash":"93f02176ce99dcb30cfb5b6062e6f1f5ba35e80d","verifierVersion":"0.1.0+4ba55555"},{"checks":[{"durationMs":75973,"exitCode":0,"name":"build","output":"Compiling 108 files with Solc 0.8.26\nSolc 0.8.26 finished in 75.75s\nCompiler run successful with warnings:\nWarning (8760): This declaration has the same name as another declaration.\n   --> src/MarginaliaHook.sol:386:9:\n    |\n386 |         uint32 week = _week();\n    |         ^^^^^^^^^^^\nNote: The other declaration is here:\n   --> src/MarginaliaHook.sol:708:5:\n    |\n708 |     function week() external view returns (uint32) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:773:9:\n    |\n773 |         uint256 pool = thesisPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:93:5:\n   |\n93 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:794:9:\n    |\n794 |         uint256 pool = leaderboardPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:93:5:\n   |\n93 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2018): Function state mutability can be restricted to pure\n   --> test/helpers/Fixture.sol:114:5:\n    |\n114 |     function priceOf(bytes32, address) external view returns (uint256) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (2018): Function state mutability can be restricted to pure\n  --> test/fork/MainnetLaunch.t.sol:78:5:\n   |\n78 |     function _mine(bytes memory hookCode) internal view returns (bytes32 salt) {\n   |     ^ (Relevant source part starts here and spans across multiple lines).\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/MarginaliaTreasury.sol:51:9\n   │\n51 │         emit Dripped(day, amount);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/MarginaliaTreasury.sol:43:22\n   │\n43 │         uint32 day = uint32(block.timestamp / 1 days);\n   │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint32' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/MarginaliaPricer.sol:85:13\n   │\n85 │             n += 1;\n   │             ━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[missing-events-access-control]: `jobHash` is changed without an event but is used for access control\n    ╭▸ src/MarginaliaRouter.sol:303:16\n    │\n303 │         delete jobHash;\n    │                ━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaPricer.sol:119:33\n    │\n119 │         if (w.startedAt == 0 || block.timestamp > uint256(w.startedAt) + POST_MAX_AGE) {\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n   ╭▸ src/MarginaliaJudge.sol:96:17\n   │\n96 │             try hook.sellPotMarg(marg) returns (uint256 out) {\n   │                 ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:120:34\n    │\n120 │             return T.PriceWindow(uint64(block.timestamp), uint64(block.number), x, x, x, q, q);\n    │                                  ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:120:59\n    │\n120 │             return T.PriceWindow(uint64(block.timestamp), uint64(block.number), x, x, x, q, q);\n    │                                                           ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[calls-loop]: external call inside a loop\n   ╭▸ src/MarginaliaJudge.sol:96:17\n   │\n96 │             try hook.sellPotMarg(marg) returns (uint256 out) {\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/MarginaliaPricer.sol:141:20\n    │\n141 │                 || block.timestamp < uint256(w.startedAt) + POST_MIN_SPAN\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/MarginaliaPricer.sol:142:20\n    │\n142 │                 || block.timestamp > uint256(w.startedAt) + POST_MAX_AGE\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:114:47\n    │\n114 │         for (uint256 i = 0; i < all.length && n < MAX_JUDGED; ++i) {\n    │                                               ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaJudge.sol:115:35\n    │\n115 │             (,,, bool hasChild) = hook.noteMeta(all[i]);\n    │                                   ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:148:69\n    │\n148 │             x = twap(v.kind, v.xIsToken0, w.xStart, w.startedAt, x, uint64(block.timestamp));\n    │                                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaJudge.sol:115:35\n    │\n115 │             (,,, bool hasChild) = hook.noteMeta(all[i]);\n    │                                   ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:167:55\n    │\n167 │         else if (v.kind == T.VenueKind.UniV3) xRead = uint256(_v3Cumulative(ref));\n    │                                                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:170:15\n    │\n170 │             ++n;\n    │               ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaJudge.sol:174:33\n    │\n174 │             out[i - 1] = bytes1(uint8(48 + v % 10));\n    │                                 ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:212:28\n    │\n212 │             int256 delta = int256(c2) - int256(c1);\n    │                            ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:212:41\n    │\n212 │             int256 delta = int256(c2) - int256(c1);\n    │                                         ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:213:35\n    │\n213 │             int256 mean = delta / int256(dt);\n    │                                   ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:214:38\n    │\n214 │             if (delta < 0 && delta % int256(dt) != 0) mean -= 1; // round toward negative infinity, as v3 does\n    │                                      ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:216:57\n    │\n216 │             return fromSqrt(TickMath.getSqrtPriceAtTick(int24(mean)), xIsToken0);\n    │                                                         ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int24' is safe 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/MarginaliaJudge.sol:186:52\n    │\n186 │         return eligibleTheses(week).length == 0 || block.timestamp >= (uint256(week) + 1) * 7 days + 28 days;\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/MarginaliaPricer.sol:240:37\n    │\n240 │             (uint160 sqrtP,,,,,,) = IUniswapV3PoolOracle(ref).slot0();\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/MarginaliaPricer.sol:244:41\n    │\n244 │             (uint112 r0, uint112 r1,) = IUniswapV2PairOracle(ref).getReserves();\n    │                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/MarginaliaHook.sol:78:38\n   │\n78 │     bytes32 public constant ACTION = bytes32(\"oracle.request@oracle-1\");\n   │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes32' is safe 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/MarginaliaJudge.sol:194:32\n    │\n194 │         if (judgedSet[week] || block.timestamp < requestedAt[week] + ANSWER_DEADLINE) {\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/MarginaliaPricer.sol:268:33\n    │\n268 │         (int56[] memory cum,) = IUniswapV3PoolOracle(pool).observe(ago);\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:278:24\n    │\n278 │         uint32 nowTs = uint32(block.timestamp);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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/MarginaliaHook.sol:196:44\n    │\n196 │     constructor(IPoolManager poolManager_, address token_, address factory_) {\n    │                                            ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[reentrancy-no-eth]: external call can be reentered before `requestOf` is updated\n    ╭▸ src/MarginaliaJudge.sol:214:9\n    │\n214 │         hook.drawForJudging(day, price, retry);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `requestOf` is updated\n    ╭▸ src/MarginaliaJudge.sol:217:21\n    │\n217 │           requestId = intake.request(\n    │ ┏━━━━━━━━━━━━━━━━━━━━━┛\n218 │ ┃             action, body, IIntake.Callback(address(this), this.onOracleResult.selector), imd, price\n219 │ ┃         );\n    │ ┗━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaJudge.sol:206:41\n    │\n206 │         if (judgedSet[day] || (retry && block.timestamp < requestedAt[day] + ANSWER_DEADLINE)) {\n    │                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaJudge.sol:225:9\n    │\n225 │         emit Requested(day, requestId, price);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaJudge.sol:223:28\n    │\n223 │         requestedAt[day] = uint64(block.timestamp);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaJudge.sol:255:9\n    │\n255 │ ┏         emit Judged(\n256 │ ┃             day,\n257 │ ┃             [\n258 │ ┃                 count > 0 ? ranked[0] : bytes32(0),\n    ‡ ┃\n262 │ ┃         );\n    │ ┗━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:269:50\n    │\n269 │         for (uint256 i = 0; i < ranked.length && kept < 3; ++i) {\n    │                                                  ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaRouter.sol:251:13\n    │\n251 │         if (block.timestamp > deadline) revert Expired();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:276:17\n    │\n276 │             if (dup) continue;\n    │                 ━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaJudge.sol:270:77\n    │\n270 │             (address author, uint32 noteWeek, bool thesis, bool hasChild) = hook.noteMeta(ranked[i]);\n    │                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:252:41\n    │\n252 │         if (amountIn == 0 || amountIn > uint256(uint128(type(int128).max))) revert InvalidSwap();\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/MarginaliaRouter.sol:252:49\n    │\n252 │         if (amountIn == 0 || amountIn > uint256(uint128(type(int128).max))) revert InvalidSwap();\n    │                                                 ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/MarginaliaJudge.sol:288:9\n    │\n288 │         hook.payJudged(day, top);\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/MarginaliaRouter.sol:338:9\n    │\n338 │         emit Noted(job.payer, job.sellMarg, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:320:18\n    │\n320 │                 -int256(job.amountIn),\n    │                  ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:328:25\n    │\n328 │         uint256 spent = uint256(uint128(-inputDelta));\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/MarginaliaRouter.sol:328:33\n    │\n328 │         uint256 spent = uint256(uint128(-inputDelta));\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:329:28\n    │\n329 │         uint256 received = uint256(uint128(outputDelta));\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/MarginaliaRouter.sol:329:36\n    │\n329 │         uint256 received = uint256(uint128(outputDelta));\n    │                                    ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:373:9\n    │\n373 │         emit XTraded(payer, X_V4, xIn, xOut, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:355:18\n    │\n355 │                 -int256(x.amountIn),\n    │                  ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:363:25\n    │\n363 │         uint256 spent = uint256(uint128(-inputDelta));\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/MarginaliaRouter.sol:363:33\n    │\n363 │         uint256 spent = uint256(uint128(-inputDelta));\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:364:20\n    │\n364 │         received = uint256(uint128(outputDelta));\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/MarginaliaRouter.sol:364:28\n    │\n364 │         received = uint256(uint128(outputDelta));\n    │                            ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:403:9\n    │\n403 │         emit XTraded(payer, X_V3, xIn, xOut, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:394:13\n    │\n394 │             int256(x.amountIn),\n    │             ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:399:25\n    │\n399 │         uint256 spent = uint256(zeroForOne ? a0 : a1);\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/MarginaliaRouter.sol:409:78\n    │\n409 │         if (amount0Delta > 0) IERC20(pool.token0()).safeTransfer(msg.sender, uint256(amount0Delta));\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/MarginaliaRouter.sol:410:78\n    │\n410 │         if (amount1Delta > 0) IERC20(pool.token1()).safeTransfer(msg.sender, uint256(amount1Delta));\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:438:9\n    │\n438 │         emit XTraded(payer, X_V2, xIn, xOut, actualIn, received);\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/MarginaliaRouter.sol:426:37\n    │\n426 │         (uint112 r0, uint112 r1,) = pair.getReserves();\n    │                                     ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:298:21\n    │\n298 │                 if (uint256(-params.amountSpecified) <= STAMP * 2) revert NoteTooSmall();\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/MarginaliaHook.sol:306:17\n    │\n306 │             if (uint256(-params.amountSpecified) <= depositMarg * 2) revert NoteTooSmall();\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/MarginaliaHook.sol:312:30\n    │\n312 │             specifiedTake = (uint256(params.amountSpecified) * bps + (10_000 - bps) - 1) / (10_000 - bps);\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:392:9\n    │\n392 │         emit Accrued(day, 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/MarginaliaHook.sol:466:9\n    │\n466 │ ┏         emit NotePosted(\n467 │ ┃             id,\n468 │ ┃             author,\n469 │ ┃             p.x,\n    ‡ ┃\n478 │ ┃             p.text\n479 │ ┃         );\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/MarginaliaHook.sol:344:13\n    │\n344 │             emit SwapFee(true, author, poolImd, 0, STAMP);\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/MarginaliaHook.sol:360:13\n    │\n360 │             emit SwapFee(false, author, poolImd, fee - STAMP, STAMP);\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/MarginaliaHook.sol:379:9\n    │\n379 │         emit SwapFee(false, tx.origin, poolImd, quietFee, 0);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:329:33\n    │\n329 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\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/MarginaliaHook.sol:329:41\n    │\n329 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\n    │                                         ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:329:63\n    │\n329 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\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/MarginaliaHook.sol:329:71\n    │\n329 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\n    │                                                                       ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:334:29\n    │\n334 │             uint256 netIn = uint256(-params.amountSpecified) - STAMP;\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/MarginaliaHook.sol:336:31\n    │\n336 │             uint256 margOut = uint256(uint128(margDelta));\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/MarginaliaHook.sol:336:39\n    │\n336 │             uint256 margOut = uint256(uint128(margDelta));\n    │                                       ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:369:25\n    │\n369 │             quietFee = (uint256(params.amountSpecified) * bps + (10_000 - bps) - 1) / (10_000 - bps);\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/MarginaliaHook.sol:370:28\n    │\n370 │             if (poolImd != uint256(params.amountSpecified) + quietFee) revert PartialFill();\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:452:17\n    │\n452 │             if (weekTheses[_week()].length >= MAX_WEEK_THESES) revert InvalidNote();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:444:22\n    │\n444 │         n.postedAt = uint64(block.timestamp);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe 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/MarginaliaHook.sol:500:13\n    │\n500 │         if (block.timestamp < end) revert TooEarly();\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/MarginaliaHook.sol:501:13\n    │\n501 │         if (block.timestamp > end + SETTLE_WINDOW) revert TooLate();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:514:9\n    │\n514 │         emit Observed(id, uint64(block.timestamp), xRead, quoteRead, balance);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:506:27\n    │\n506 │             T.Observation(uint64(block.timestamp), uint64(block.number), xRead, quoteRead, balance);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:506:52\n    │\n506 │             T.Observation(uint64(block.timestamp), uint64(block.number), xRead, quoteRead, balance);\n    │                                                    ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:514:27\n    │\n514 │         emit Observed(id, uint64(block.timestamp), xRead, quoteRead, balance);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[return-bomb]: external call with a gas limit may copy unbounded return data\n    ╭▸ src/MarginaliaHook.sol:522:13\n    │\n522 │             x.staticcall{gas: BALANCE_READ_GAS}(abi.encodeWithSelector(IERC20.balanceOf.selector, who));\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/return-bomb\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaHook.sol:612:35\n    │\n612 │         emit Settled(id, outcome, settlePrice, scoreDelta, msg.sender);\n    │                                   ━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:562:13\n    │\n562 │         if (block.timestamp <= end + SETTLE_WINDOW) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:682:13\n    │\n682 │             emit ThesisReleased(n.parentId);\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/MarginaliaHook.sol:612:9\n    │\n612 │         emit Settled(id, outcome, settlePrice, scoreDelta, msg.sender);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:594:26\n    │\n594 │             scoreDelta = int256(_difficulty(n));\n    │                          ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:599:27\n    │\n599 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:601:27\n    │\n601 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:605:27\n    │\n605 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:620:13\n    │\n620 │         if (block.timestamp >= horizonEnd(id)) revert TooLate();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:629:9\n    │\n629 │         emit Retracted(id, text);\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/MarginaliaHook.sol:630:9\n    │\n630 │         emit Settled(id, T.Status.Retracted, 0, scoreDelta, address(0));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:622:30\n    │\n622 │         int256 scoreDelta = -int256(_difficulty(n) / 2);\n    │                              ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/MarginaliaHook.sol:638:13\n    │\n638 │         if (block.timestamp <= uint256(n.postedAt) + THESIS_GRACE) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:641:9\n    │\n641 │         emit ThesisForfeited(id);\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/MarginaliaHook.sol:659:9\n    │\n659 │         emit DepositClaimed(id, n.author, asImd, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:697:16\n    │\n697 │         return uint32(block.timestamp / 1 days);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:701:16\n    │\n701 │         return uint32(block.timestamp / 7 days);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:722:38\n    │\n722 │         uint256 prevPos = prev > 0 ? uint256(prev) : 0;\n    │                                      ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:723:38\n    │\n723 │         uint256 nextPos = next > 0 ? uint256(next) : 0;\n    │                                      ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:733:9\n    │\n733 │         emit PotFunded(_today(), amount, msg.sender);\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/MarginaliaHook.sol:745:9\n    │\n745 │         emit PotMargSold(amount, imdOut, _today());\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:765:27\n    │\n765 │         return (n.author, uint32(uint256(n.postedAt) / 7 days), n.targetBps == 0, n.children > 0);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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 `thesisPool` is updated\n    ╭▸ src/MarginaliaHook.sol:864:28\n    │\n864 │         bytes memory out = poolManager.unlock(data);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaHook.sol:864:28\n    │\n864 │         bytes memory out = poolManager.unlock(data);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:787:9\n    │\n787 │         emit JudgedPaid(w, paidAmounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/MarginaliaHook.sol:865:39\n    │\n865 │         if (unlockHash != bytes32(0)) revert InvalidUnlock();\n    │                                       ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:795:47\n    │\n795 │         uint256 share = FullMath.mulDiv(pool, uint256(s), weekTotal[w]);\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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:801:13\n    │\n801 │         if (w >= _week()) revert TooEarly();\n    │             ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:808:9\n    │\n808 │         emit LeaderboardClaimed(w, msg.sender, amount);\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/MarginaliaHook.sol:815:13\n    │\n815 │         if (n.day >= _today()) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:825:9\n    │\n825 │         emit RefundClaimed(id, msg.sender, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:823:30\n    │\n823 │         notesPerDay[n.day] = uint32(count - 1);\n    │                              ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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/MarginaliaHook.sol:834:17\n    │\n834 │             if (block.timestamp < (uint256(epoch) + 1) * 1 days + SWEEP_AFTER) revert TooEarly();\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/MarginaliaHook.sol:838:17\n    │\n838 │             if (block.timestamp < (uint256(epoch) + 1) * 7 days + SWEEP_AFTER) revert TooEarly();\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/MarginaliaHook.sol:842:17\n    │\n842 │             if (block.timestamp < (uint256(epoch) + 1) * 7 days + SWEEP_AFTER) revert TooEarly();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:875:40\n    │\n875 │             address currency = address(uint160(extra));\n    │                                        ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint160' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaHook.sol:884:13\n    │\n884 │             poolManager.settle();\n    │             ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:894:22\n    │\n894 │                     -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/MarginaliaHook.sol:903:17\n    │\n903 │             if (uint256(uint128(-margDelta)) != amount) revert InvalidUnlock();\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/MarginaliaHook.sol:903:25\n    │\n903 │             if (uint256(uint128(-margDelta)) != amount) revert InvalidUnlock();\n    │                         ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:905:30\n    │\n905 │             uint256 imdOut = uint256(uint128(imdDelta));\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/MarginaliaHook.sol:905:38\n    │\n905 │             uint256 imdOut = uint256(uint128(imdDelta));\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[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n   ╭▸ test/AuditFindings.t.sol:19:30\n   │\n19 │         uint256 startBlock = block.number;\n   │                              ━━━━━━━━━━━━\n   ‡\n23 │             vm.roll(startBlock + 25 * (i + 1));\n   │             ────────────────────────────────── `vm.roll` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockNumber()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/AuditFindings.t.sol:20:27\n   │\n20 │         uint256 startTs = block.timestamp;\n   │                           ━━━━━━━━━━━━━━━\n   ‡\n24 │             vm.warp(startTs + 31 minutes * (i + 1));\n   │             ─────────────────────────────────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/AuditFindings.t.sol:18:9\n    │\n 18 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/AuditFindings.t.sol:65:9\n    │\n 65 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/AuditFindings.t.sol:65:17\n   │\n65 │         vm.warp(block.timestamp + 7 days);\n   │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:130:9\n    │\n130 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:131:30\n    │\n131 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n135 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:132:27\n    │\n132 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n136 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:158:9\n    │\n158 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:159:30\n    │\n159 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n163 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:160:27\n    │\n160 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n164 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:182:9\n    │\n182 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:183:30\n    │\n183 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n187 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:184:27\n    │\n184 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n188 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:278:9\n    │\n278 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:278:17\n    │\n278 │         vm.warp(block.timestamp + 7 days);\n    │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:328:9\n    │\n328 │         vm.warp(hook.horizonEnd(a));\n    │         ─────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:329:30\n    │\n329 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n334 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:330:27\n    │\n330 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n335 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:408:9\n    │\n408 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:408:17\n    │\n408 │         vm.warp(block.timestamp + 7 days);\n    │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:475:9\n    │\n475 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:476:30\n    │\n476 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n479 │         vm.roll(startBlock + 25);\n    │         ──────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:477:27\n    │\n477 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n480 │         vm.warp(startTs + 30 minutes);\n    │         ───────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:499:9\n    │\n499 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:500:30\n    │\n500 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n504 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:501:27\n    │\n501 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n505 │             vm.warp(startTs + 10 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/RevisionFindings.t.sol:197:17\n    │\n197 │         vm.warp(block.timestamp + 1 hours);\n    │         ────────━━━━━━━━━━━━━━━─────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/RevisionFindings.t.sol:258:9\n    │\n258 │         vm.warp((uint256(w) + 1) * 7 days + 1);\n    │         ────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\n","passed":true},{"durationMs":157,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/fork/MainnetLaunch.t.sol:MainnetLaunchTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 537.72µs (0.00ns CPU time)\n\nRan 7 tests for test/JudgeOracle.t.sol:JudgeOracleTest\n[PASS] testEmptySignedRankingIsAnExecutableNoWinnerResult() (gas: 248153)\n[PASS] testFiveIdsWithEoaSignatureFitStipend() (gas: 554052)\n[PASS] testFullRankingWithEoaSignatureFitsStipend() (gas: 633672)\n[PASS] testProtocolDigestSignatureAndSelectorConformanceOnClone() (gas: 3322442)\n[PASS] testRejectedAnswersDoNotConsumeThePendingRequest() (gas: 892875)\n[PASS] testRequestedHeadIsFilteredAndDeduplicatedWithoutPromotingTheTail() (gas: 250679)\n[PASS] testTimeoutRetryInvalidatesOldIntakeRequest() (gas: 523953)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 6.54ms (4.77ms CPU time)\n\nRan 8 tests for test/PriceHistory.t.sol:PriceHistoryTest\n[PASS] testBaselineRequiresMatureFreshHistory() (gas: 188472)\n[PASS] testEmptyVenueAndHubCannotBeCheckpointedObservedOrPriced() (gas: 284549)\n[PASS] testFuzzV4BaselineIsNeverFavourableToTheCall(int24,bool) (runs: 256, μ: 105993, ~: 106163)\nLogs:\n  Bound result 19998\n\n[PASS] testHubBaselineUsesOppositeExtremeFromSettlement() (gas: 180334)\n[PASS] testLiveCheckpointCannotEraseHonestExtremesOrRestartTheClock() (gas: 224282)\n[PASS] testV2BaselineIgnoresSameBlockReservesDumpAndPumpBothOrientations() (gas: 467543)\n[PASS] testV3BaselineIgnoresSameBlockTickChangesBothOrientations() (gas: 418025)\n[PASS] testV3BaselineWeightsElapsedTime() (gas: 371037)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 9.18ms (10.19ms CPU time)\n\nRan 7 tests for test/Pricer.t.sol:PricerTest\n[PASS] testQuoteLegIsAdverseEvenUnderAV3Twap() (gas: 28455)\n[PASS] testTwapRefusesZeroSpanAndV4() (gas: 17708)\n[PASS] testV2TwapFromWrappingCumulative() (gas: 9503)\n[PASS] testV3TwapOfAConstantTickIsThatTick() (gas: 15459)\n[PASS] testV3TwapRoundsNegativeMeansDown() (gas: 14848)\n[PASS] testV3TwapWeightsByTime() (gas: 14715)\n[PASS] testV4SettlesOnTheAdverseExtreme() (gas: 26636)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 9.22ms (696.42µs CPU time)\n\nRan 8 tests for test/AuditFindings.t.sol:AuditFindingsTest\n[PASS] testConversionAfterARealPriceFallNeedsAFreshMatureWindow() (gas: 2239771)\n[PASS] testEmptyV4ObservationIsRefused() (gas: 1022543)\n[PASS] testExpiredBaselineRejectsPostWithoutTakingFunds() (gas: 643715)\n[PASS] testForfeitureConversionRejectsSameBlockDump() (gas: 2218773)\n[PASS] testLongRankingFitsIntakeStipend() (gas: 2193239)\n[PASS] testSameBlockDumpPostUnwindDoesNotWinBuy() (gas: 1914995)\n[PASS] testSameBlockPumpPostUnwindDoesNotWinSell() (gas: 1787168)\n[PASS] testUnpayableRankingRollsTheWholePoolForward() (gas: 2466565)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 19.94ms (9.43ms CPU time)\n\nRan 3 tests for test/Implementations.t.sol:ImplementationsTest\n[PASS] testClonesInitializeOnceOnlyFromTheirHook() (gas: 4551335)\n[PASS] testFactoryDeploysAllFourWithoutArgumentsOrExternalDependencies() (gas: 34594277)\nLogs:\n  four implementation CREATE2 deployments (gas): 8826312\n\n[PASS] testImplementationsRejectInitialization() (gas: 81376)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 38.25ms (39.24ms CPU time)\n\nRan 2 tests for test/PotTranche.t.sol:PotTrancheTest\n[PASS] testForfeitedPotCanStillBeConvertedOnceItOutgrowsOneSale() (gas: 49410352)\nLogs:\n  potMarg: 36877975912613201326\n  imdOut: 10344028156678390861\n\n[PASS] testWhenNoTrancheSellsTheHookReasonSurfaces() (gas: 1260643)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 45.09ms (30.64ms CPU time)\n\nRan 10 tests for test/RevisionFindings.t.sol:RevisionFindingsTest\n[PASS] testADustPricedV4VenueCannotBePostedOn() (gas: 1636136)\n[PASS] testARealBuyBackStillVoidsASellCall() (gas: 1791662)\n[PASS] testARevertingBalanceOfVoidsTheCallAsSoldNotAsNoData() (gas: 2678007)\n[PASS] testAStrangersDustTransferDoesNotVoidASellCall() (gas: 1697092)\n[PASS] testAnAttestationAboutAnotherChainIsRefused() (gas: 2325368)\n[PASS] testAnEmptyCanonicalV3PoolIsRefusedAsAVenue() (gas: 567990)\n[PASS] testHonestObserverOverwritesAPumpObserveUnwindInTheNextBlock() (gas: 3783793)\n[PASS] testPricerRefusesAPriceThatRoundsToZeroInBothOrientations() (gas: 58727)\n[PASS] testSweepNeedsTheStaleRequestAbandonedAndALateAnswerIsThenRefused() (gas: 2450533)\n[PASS] testTheHundredAndTwentyFirstThesisOfAWeekIsRefusedBeforePayment() (gas: 55411706)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 45.94ms (38.43ms CPU time)\n\nRan 26 tests for test/Lifecycle.t.sol:LifecycleTest\n[PASS] testAttestedClassCannotBeSelfDeclared() (gas: 343256)\n[PASS] testCallbackSelectorPinned() (gas: 3361)\n[PASS] testFakeVenueIsRefused() (gas: 382780)\n[PASS] testFlagsAndBinding() (gas: 55989)\n[PASS] testForfeitsConvertToImdForThePot() (gas: 1112852)\n[PASS] testLeaderboardProRataWithCap() (gas: 3243602)\n[PASS] testNoDataRefunds() (gas: 993629)\n[PASS] testNoteTooSmall() (gas: 173144)\n[PASS] testNotedBuyTakesStampAndDeposit() (gas: 798665)\n[PASS] testNotedSellPaysOnePercentPlusStamp() (gas: 1108348)\n[PASS] testObservationsMustSpanAnHour() (gas: 1488779)\n[PASS] testPlainBuyTakesNothing() (gas: 230618)\n[PASS] testQuietSellPaysThreePercent() (gas: 336869)\n[PASS] testQuietThesisPoolSweeps() (gas: 306043)\n[PASS] testRetract() (gas: 945582)\n[PASS] testRightCallReturnsDepositAsImd() (gas: 1802343)\n[PASS] testSellingEarlyBreaksTheCall() (gas: 1770726)\n[PASS] testThesisParentChild() (gas: 1509361)\n[PASS] testThesisWithoutChildForfeits() (gas: 797205)\n[PASS] testTreasuryDrip() (gas: 348364)\n[PASS] testTwoBlockPumpObserveUnwindSettlesWrong() (gas: 1802286)\n[PASS] testUnansweredWeekCanBeRetried() (gas: 2442021)\n[PASS] testUpOnlyIsRefused() (gas: 340864)\n[PASS] testWeeklyThesisJudging() (gas: 3856451)\n[PASS] testWriterRefundCappedAtStamp() (gas: 1711148)\n[PASS] testWrongCallForfeitsWithKeeperReward() (gas: 1560130)\nSuite result: ok. 26 passed; 0 failed; 0 skipped; finished in 46.67ms (26.33ms CPU time)\n\nRan 9 test suites in 47.72ms (221.36ms CPU time): 71 tests passed, 0 failed, 1 skipped (72 total tests)\n","passed":true},{"durationMs":79,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"Marginalia.approve(address,uint256)\",\"Marginalia.transfer(address,uint256)\",\"Marginalia.transferFrom(address,address,uint256)\",\"MarginaliaHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"MarginaliaHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"MarginaliaHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"MarginaliaHook.claimDeposit(bytes32,bool)\",\"MarginaliaHook.claimLeaderboard(uint32)\",\"MarginaliaHook.claimRefund(bytes32)\",\"MarginaliaHook.drawForJudging(uint32,uint256,bool)\",\"MarginaliaHook.fundPot(uint256)\",\"MarginaliaHook.observe(bytes32)\",\"MarginaliaHook.payJudged(uint32,bytes32[3])\",\"MarginaliaHook.retract(bytes32,string)\",\"MarginaliaHook.sellPotMarg(uint256)\",\"MarginaliaHook.settle(bytes32)\",\"MarginaliaHook.settleThesis(bytes32)\",\"MarginaliaHook.sweep(uint8,uint32)\",\"MarginaliaHook.unlockCallback(bytes)\",\"MarginaliaJudge.abandonRequest(uint32)\",\"MarginaliaJudge.convertForfeits()\",\"MarginaliaJudge.init(address,address,bytes32,address)\",\"MarginaliaJudge.onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"MarginaliaJudge.payJudged(uint32)\",\"MarginaliaJudge.requestJudging(uint32)\",\"MarginaliaRouter.checkpointVenue((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address))\",\"MarginaliaRouter.init(address,address)\",\"MarginaliaRouter.note((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address),uint256,uint256,uint256)\",\"MarginaliaRouter.sellWithNote((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address),uint256,uint256,uint256)\",\"MarginaliaRouter.uniswapV3SwapCallback(int256,int256,bytes)\",\"MarginaliaRouter.unlockCallback(bytes)\",\"MarginaliaTreasury.drip()\",\"MarginaliaTreasury.init(address)\"],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":179,\"README.md\":143,\"SPEC.md\":263,\"dependencies.json\":28,\"foundry.toml\":21,\"helper/.gitignore\":3,\"helper/package-lock.json\":737,\"helper/package.json\":20,\"helper/public/index.html\":82,\"helper/server.js\":90,\"helper/src/app.js\":203,\"jobs/launch-1-hook.json\":43,\"jobs/launch-2-contracts.json\":38,\"jobs/launch-A-implementations.json\":47,\"jobs/launch-A2-implementations.json\":41,\"jobs/launch-hook-v3.json\":43,\"launch.json\":22,\"remappings.txt\":4,\"src/HookFlags.sol\":33,\"src/Marginalia.sol\":12,\"src/MarginaliaHook.sol\":927,\"src/MarginaliaImpls.sol\":14,\"src/MarginaliaJudge.sol\":290,\"src/MarginaliaPricer.sol\":304,\"src/MarginaliaRouter.sol\":446,\"src/MarginaliaTreasury.sol\":53,\"src/MarginaliaTypes.sol\":108,\"src/OracleAttestation.sol\":221,\"src/interfaces/IIntake.sol\":15,\"src/interfaces/ILaunchFactory.sol\":49,\"test/AuditFindings.t.sol\":178,\"test/Implementations.t.sol\":96,\"test/JudgeOracle.t.sol\":270,\"test/Lifecycle.t.sol\":511,\"test/PotTranche.t.sol\":189,\"test/PriceHistory.t.sol\":233,\"test/Pricer.t.sol\":88,\"test/RevisionFindings.t.sol\":314,\"test/fork/MainnetLaunch.t.sol\":382,\"test/helpers/Fixture.sol\":278,\"test/mocks/MockERC20.sol\":13},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"ad6f2e3202e7b8bb97969756fb5cecfcdc6a15460dd71d026278dabb9bd5ba1d","verifiedTreeHash":"857399856f49659569b57a37c064334396728c1f","verifierVersion":"0.1.0+fdeb4d4a"},{"checks":[{"durationMs":60079,"exitCode":0,"name":"build","output":"Compiling 106 files with Solc 0.8.26\nSolc 0.8.26 finished in 59.81s\nCompiler run successful with warnings:\nWarning (8760): This declaration has the same name as another declaration.\n   --> src/MarginaliaHook.sol:379:9:\n    |\n379 |         uint32 week = _week();\n    |         ^^^^^^^^^^^\nNote: The other declaration is here:\n   --> src/MarginaliaHook.sol:644:5:\n    |\n644 |     function week() external view returns (uint32) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:709:9:\n    |\n709 |         uint256 pool = thesisPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:86:5:\n   |\n86 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:730:9:\n    |\n730 |         uint256 pool = leaderboardPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:86:5:\n   |\n86 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2018): Function state mutability can be restricted to pure\n   --> test/helpers/Fixture.sol:114:5:\n    |\n114 |     function priceOf(bytes32, address) external view returns (uint256) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (2018): Function state mutability can be restricted to pure\n  --> test/fork/MainnetLaunch.t.sol:78:5:\n   |\n78 |     function _mine(bytes memory hookCode) internal view returns (bytes32 salt) {\n   |     ^ (Relevant source part starts here and spans across multiple lines).\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/MarginaliaTreasury.sol:51:9\n   │\n51 │         emit Dripped(day, amount);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/MarginaliaTreasury.sol:43:22\n   │\n43 │         uint32 day = uint32(block.timestamp / 1 days);\n   │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint32' is safe 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]: `jobHash` is changed without an event but is used for access control\n    ╭▸ src/MarginaliaRouter.sol:301:16\n    │\n301 │         delete jobHash;\n    │                ━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/MarginaliaHook.sol:71:38\n   │\n71 │     bytes32 public constant ACTION = bytes32(\"oracle.request@oracle-1\");\n   │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes32' is safe 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/MarginaliaHook.sol:189:44\n    │\n189 │     constructor(IPoolManager poolManager_, address token_, address factory_) {\n    │                                            ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n   ╭▸ src/MarginaliaJudge.sol:87:18\n   │\n87 │         imdOut = hook.sellPotMarg(marg);\n   │                  ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/MarginaliaJudge.sol:96:47\n   │\n96 │         for (uint256 i = 0; i < all.length && n < MAX_JUDGED; ++i) {\n   │                                               ━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n   ╭▸ src/MarginaliaJudge.sol:97:35\n   │\n97 │             (,,, bool hasChild) = hook.noteMeta(all[i]);\n   │                                   ━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[unused-return]: return value of an external call is not used\n   ╭▸ src/MarginaliaJudge.sol:97:35\n   │\n97 │             (,,, bool hasChild) = hook.noteMeta(all[i]);\n   │                                   ━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:152:15\n    │\n152 │             ++n;\n    │               ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaJudge.sol:156:33\n    │\n156 │             out[i - 1] = bytes1(uint8(48 + v % 10));\n    │                                 ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaJudge.sol:166:46\n    │\n166 │         if (requestOf[week] != bytes32(0) && block.timestamp < requestedAt[week] + ANSWER_DEADLINE) {\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/MarginaliaJudge.sol:169:52\n    │\n169 │         return eligibleTheses(week).length == 0 || block.timestamp >= (uint256(week) + 1) * 7 days + 28 days;\n    │                                                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/MarginaliaPricer.sol:85:13\n   │\n85 │             n += 1;\n   │             ━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaRouter.sol:249:13\n    │\n249 │         if (block.timestamp > deadline) revert Expired();\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/MarginaliaPricer.sol:119:33\n    │\n119 │         if (w.startedAt == 0 || block.timestamp > uint256(w.startedAt) + POST_MAX_AGE) {\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:250:41\n    │\n250 │         if (amountIn == 0 || amountIn > uint256(uint128(type(int128).max))) revert InvalidSwap();\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/MarginaliaRouter.sol:250:49\n    │\n250 │         if (amountIn == 0 || amountIn > uint256(uint128(type(int128).max))) revert InvalidSwap();\n    │                                                 ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:120:34\n    │\n120 │             return T.PriceWindow(uint64(block.timestamp), uint64(block.number), x, x, x, q, q);\n    │                                  ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:120:59\n    │\n120 │             return T.PriceWindow(uint64(block.timestamp), uint64(block.number), x, x, x, q, q);\n    │                                                           ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe 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/MarginaliaPricer.sol:141:20\n    │\n141 │                 || block.timestamp < uint256(w.startedAt) + POST_MIN_SPAN\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/MarginaliaPricer.sol:142:20\n    │\n142 │                 || block.timestamp > uint256(w.startedAt) + POST_MAX_AGE\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:148:69\n    │\n148 │             x = twap(v.kind, v.xIsToken0, w.xStart, w.startedAt, x, uint64(block.timestamp));\n    │                                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:165:55\n    │\n165 │         else if (v.kind == T.VenueKind.UniV3) xRead = uint256(_v3Cumulative(ref));\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/MarginaliaPricer.sol:208:28\n    │\n208 │             int256 delta = int256(c2) - int256(c1);\n    │                            ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:208:41\n    │\n208 │             int256 delta = int256(c2) - int256(c1);\n    │                                         ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:209:35\n    │\n209 │             int256 mean = delta / int256(dt);\n    │                                   ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:210:38\n    │\n210 │             if (delta < 0 && delta % int256(dt) != 0) mean -= 1; // round toward negative infinity, as v3 does\n    │                                      ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:212:57\n    │\n212 │             return fromSqrt(TickMath.getSqrtPriceAtTick(int24(mean)), xIsToken0);\n    │                                                         ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int24' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaPricer.sol:234:37\n    │\n234 │             (uint160 sqrtP,,,,,,) = IUniswapV3PoolOracle(ref).slot0();\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/MarginaliaPricer.sol:238:41\n    │\n238 │             (uint112 r0, uint112 r1,) = IUniswapV2PairOracle(ref).getReserves();\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/MarginaliaPricer.sol:260:33\n    │\n260 │         (int56[] memory cum,) = IUniswapV3PoolOracle(pool).observe(ago);\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:270:24\n    │\n270 │         uint32 nowTs = uint32(block.timestamp);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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 `requestOf` is updated\n    ╭▸ src/MarginaliaJudge.sol:185:9\n    │\n185 │         hook.drawForJudging(day, price, retry);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `requestOf` is updated\n    ╭▸ src/MarginaliaJudge.sol:188:21\n    │\n188 │           requestId = intake.request(\n    │ ┏━━━━━━━━━━━━━━━━━━━━━┛\n189 │ ┃             action, body, IIntake.Callback(address(this), this.onOracleResult.selector), imd, price\n190 │ ┃         );\n    │ ┗━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaJudge.sol:177:41\n    │\n177 │         if (judgedSet[day] || (retry && block.timestamp < requestedAt[day] + ANSWER_DEADLINE)) {\n    │                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaJudge.sol:196:9\n    │\n196 │         emit Requested(day, requestId, price);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaJudge.sol:194:28\n    │\n194 │         requestedAt[day] = uint64(block.timestamp);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:336:9\n    │\n336 │         emit Noted(job.payer, job.sellMarg, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:318:18\n    │\n318 │                 -int256(job.amountIn),\n    │                  ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:326:25\n    │\n326 │         uint256 spent = uint256(uint128(-inputDelta));\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/MarginaliaRouter.sol:326:33\n    │\n326 │         uint256 spent = uint256(uint128(-inputDelta));\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:327:28\n    │\n327 │         uint256 received = uint256(uint128(outputDelta));\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/MarginaliaRouter.sol:327:36\n    │\n327 │         uint256 received = uint256(uint128(outputDelta));\n    │                                    ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaJudge.sol:224:9\n    │\n224 │ ┏         emit Judged(\n225 │ ┃             day,\n226 │ ┃             [\n227 │ ┃                 count > 0 ? ranked[0] : bytes32(0),\n    ‡ ┃\n231 │ ┃         );\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/MarginaliaRouter.sol:371:9\n    │\n371 │         emit XTraded(payer, X_V4, xIn, xOut, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:353:18\n    │\n353 │                 -int256(x.amountIn),\n    │                  ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:361:25\n    │\n361 │         uint256 spent = uint256(uint128(-inputDelta));\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/MarginaliaRouter.sol:361:33\n    │\n361 │         uint256 spent = uint256(uint128(-inputDelta));\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[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:245:17\n    │\n245 │             if (dup) continue;\n    │                 ━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:238:50\n    │\n238 │         for (uint256 i = 0; i < ranked.length && kept < 3; ++i) {\n    │                                                  ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:362:20\n    │\n362 │         received = uint256(uint128(outputDelta));\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/MarginaliaRouter.sol:362:28\n    │\n362 │         received = uint256(uint128(outputDelta));\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[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaJudge.sol:239:77\n    │\n239 │             (address author, uint32 noteWeek, bool thesis, bool hasChild) = hook.noteMeta(ranked[i]);\n    │                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:401:9\n    │\n401 │         emit XTraded(payer, X_V3, xIn, xOut, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/MarginaliaJudge.sol:257:9\n    │\n257 │         hook.payJudged(day, top);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:392:13\n    │\n392 │             int256(x.amountIn),\n    │             ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:397:25\n    │\n397 │         uint256 spent = uint256(zeroForOne ? a0 : a1);\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/MarginaliaRouter.sol:407:78\n    │\n407 │         if (amount0Delta > 0) IERC20(pool.token0()).safeTransfer(msg.sender, uint256(amount0Delta));\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/MarginaliaRouter.sol:408:78\n    │\n408 │         if (amount1Delta > 0) IERC20(pool.token1()).safeTransfer(msg.sender, uint256(amount1Delta));\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:436:9\n    │\n436 │         emit XTraded(payer, X_V2, xIn, xOut, actualIn, received);\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/MarginaliaRouter.sol:424:37\n    │\n424 │         (uint112 r0, uint112 r1,) = pair.getReserves();\n    │                                     ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:291:21\n    │\n291 │                 if (uint256(-params.amountSpecified) <= STAMP * 2) revert NoteTooSmall();\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/MarginaliaHook.sol:299:17\n    │\n299 │             if (uint256(-params.amountSpecified) <= depositMarg * 2) revert NoteTooSmall();\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/MarginaliaHook.sol:305:30\n    │\n305 │             specifiedTake = (uint256(params.amountSpecified) * bps + (10_000 - bps) - 1) / (10_000 - bps);\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:385:9\n    │\n385 │         emit Accrued(day, 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/MarginaliaHook.sol:457:9\n    │\n457 │ ┏         emit NotePosted(\n458 │ ┃             id,\n459 │ ┃             author,\n460 │ ┃             p.x,\n    ‡ ┃\n469 │ ┃             p.text\n470 │ ┃         );\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/MarginaliaHook.sol:337:13\n    │\n337 │             emit SwapFee(true, author, poolImd, 0, STAMP);\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/MarginaliaHook.sol:353:13\n    │\n353 │             emit SwapFee(false, author, poolImd, fee - STAMP, STAMP);\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/MarginaliaHook.sol:372:9\n    │\n372 │         emit SwapFee(false, tx.origin, poolImd, quietFee, 0);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:322:33\n    │\n322 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\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/MarginaliaHook.sol:322:41\n    │\n322 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\n    │                                         ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:322:63\n    │\n322 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\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/MarginaliaHook.sol:322:71\n    │\n322 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\n    │                                                                       ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:327:29\n    │\n327 │             uint256 netIn = uint256(-params.amountSpecified) - STAMP;\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/MarginaliaHook.sol:329:31\n    │\n329 │             uint256 margOut = uint256(uint128(margDelta));\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/MarginaliaHook.sol:329:39\n    │\n329 │             uint256 margOut = uint256(uint128(margDelta));\n    │                                       ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:362:25\n    │\n362 │             quietFee = (uint256(params.amountSpecified) * bps + (10_000 - bps) - 1) / (10_000 - bps);\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/MarginaliaHook.sol:363:28\n    │\n363 │             if (poolImd != uint256(params.amountSpecified) + quietFee) revert PartialFill();\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:445:17\n    │\n445 │             if (weekTheses[_week()].length < MAX_DAY_NOTES) weekTheses[_week()].push(id);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:437:22\n    │\n437 │         n.postedAt = uint64(block.timestamp);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe 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/MarginaliaHook.sol:489:13\n    │\n489 │         if (block.timestamp < end) revert TooEarly();\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/MarginaliaHook.sol:490:13\n    │\n490 │         if (block.timestamp > end + SETTLE_WINDOW) revert TooLate();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:498:32\n    │\n498 │         obs.push(T.Observation(uint64(block.timestamp), uint64(block.number), xRead, quoteRead, balance));\n    │                                ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:498:57\n    │\n498 │         obs.push(T.Observation(uint64(block.timestamp), uint64(block.number), xRead, quoteRead, balance));\n    │                                                         ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:499:27\n    │\n499 │         emit Observed(id, uint64(block.timestamp), xRead, quoteRead, balance);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaHook.sol:548:35\n    │\n548 │         emit Settled(id, outcome, settlePrice, scoreDelta, msg.sender);\n    │                                   ━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:507:13\n    │\n507 │         if (block.timestamp <= end + SETTLE_WINDOW) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:618:13\n    │\n618 │             emit ThesisReleased(n.parentId);\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/MarginaliaHook.sol:548:9\n    │\n548 │         emit Settled(id, outcome, settlePrice, scoreDelta, msg.sender);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:534:26\n    │\n534 │             scoreDelta = int256(_difficulty(n));\n    │                          ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:537:27\n    │\n537 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:541:27\n    │\n541 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:556:13\n    │\n556 │         if (block.timestamp >= horizonEnd(id)) revert TooLate();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:565:9\n    │\n565 │         emit Retracted(id, text);\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/MarginaliaHook.sol:566:9\n    │\n566 │         emit Settled(id, T.Status.Retracted, 0, scoreDelta, address(0));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:558:30\n    │\n558 │         int256 scoreDelta = -int256(_difficulty(n) / 2);\n    │                              ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/MarginaliaHook.sol:574:13\n    │\n574 │         if (block.timestamp <= uint256(n.postedAt) + THESIS_GRACE) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:577:9\n    │\n577 │         emit ThesisForfeited(id);\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/MarginaliaHook.sol:595:9\n    │\n595 │         emit DepositClaimed(id, n.author, asImd, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:633:16\n    │\n633 │         return uint32(block.timestamp / 1 days);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:637:16\n    │\n637 │         return uint32(block.timestamp / 7 days);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:658:38\n    │\n658 │         uint256 prevPos = prev > 0 ? uint256(prev) : 0;\n    │                                      ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:659:38\n    │\n659 │         uint256 nextPos = next > 0 ? uint256(next) : 0;\n    │                                      ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:669:9\n    │\n669 │         emit PotFunded(_today(), amount, msg.sender);\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/MarginaliaHook.sol:681:9\n    │\n681 │         emit PotMargSold(amount, imdOut, _today());\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:701:27\n    │\n701 │         return (n.author, uint32(uint256(n.postedAt) / 7 days), n.targetBps == 0, n.children > 0);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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 `thesisPool` is updated\n    ╭▸ src/MarginaliaHook.sol:800:28\n    │\n800 │         bytes memory out = poolManager.unlock(data);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaHook.sol:800:28\n    │\n800 │         bytes memory out = poolManager.unlock(data);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:723:9\n    │\n723 │         emit JudgedPaid(w, paidAmounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/MarginaliaHook.sol:801:39\n    │\n801 │         if (unlockHash != bytes32(0)) revert InvalidUnlock();\n    │                                       ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:731:47\n    │\n731 │         uint256 share = FullMath.mulDiv(pool, uint256(s), weekTotal[w]);\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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:737:13\n    │\n737 │         if (w >= _week()) revert TooEarly();\n    │             ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:744:9\n    │\n744 │         emit LeaderboardClaimed(w, msg.sender, amount);\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/MarginaliaHook.sol:751:13\n    │\n751 │         if (n.day >= _today()) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:761:9\n    │\n761 │         emit RefundClaimed(id, msg.sender, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:759:30\n    │\n759 │         notesPerDay[n.day] = uint32(count - 1);\n    │                              ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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/MarginaliaHook.sol:770:17\n    │\n770 │             if (block.timestamp < (uint256(epoch) + 1) * 1 days + SWEEP_AFTER) revert TooEarly();\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/MarginaliaHook.sol:774:17\n    │\n774 │             if (block.timestamp < (uint256(epoch) + 1) * 7 days + SWEEP_AFTER) revert TooEarly();\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/MarginaliaHook.sol:778:17\n    │\n778 │             if (block.timestamp < (uint256(epoch) + 1) * 7 days + SWEEP_AFTER) revert TooEarly();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:811:40\n    │\n811 │             address currency = address(uint160(extra));\n    │                                        ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint160' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaHook.sol:820:13\n    │\n820 │             poolManager.settle();\n    │             ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:830:22\n    │\n830 │                     -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/MarginaliaHook.sol:839:17\n    │\n839 │             if (uint256(uint128(-margDelta)) != amount) revert InvalidUnlock();\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/MarginaliaHook.sol:839:25\n    │\n839 │             if (uint256(uint128(-margDelta)) != amount) revert InvalidUnlock();\n    │                         ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:841:30\n    │\n841 │             uint256 imdOut = uint256(uint128(imdDelta));\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/MarginaliaHook.sol:841:38\n    │\n841 │             uint256 imdOut = uint256(uint128(imdDelta));\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[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n   ╭▸ test/AuditFindings.t.sol:19:30\n   │\n19 │         uint256 startBlock = block.number;\n   │                              ━━━━━━━━━━━━\n   ‡\n23 │             vm.roll(startBlock + 25 * (i + 1));\n   │             ────────────────────────────────── `vm.roll` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockNumber()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/AuditFindings.t.sol:20:27\n   │\n20 │         uint256 startTs = block.timestamp;\n   │                           ━━━━━━━━━━━━━━━\n   ‡\n24 │             vm.warp(startTs + 31 minutes * (i + 1));\n   │             ─────────────────────────────────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/AuditFindings.t.sol:18:9\n    │\n 18 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/AuditFindings.t.sol:65:9\n    │\n 65 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/AuditFindings.t.sol:65:17\n   │\n65 │         vm.warp(block.timestamp + 7 days);\n   │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:126:9\n    │\n126 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:127:30\n    │\n127 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n131 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:128:27\n    │\n128 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n132 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:154:9\n    │\n154 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:155:30\n    │\n155 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n159 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:156:27\n    │\n156 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n160 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:178:9\n    │\n178 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:179:30\n    │\n179 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n183 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:180:27\n    │\n180 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n184 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:270:9\n    │\n270 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:270:17\n    │\n270 │         vm.warp(block.timestamp + 7 days);\n    │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:320:9\n    │\n320 │         vm.warp(hook.horizonEnd(a));\n    │         ─────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:321:30\n    │\n321 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n326 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:322:27\n    │\n322 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n327 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:400:9\n    │\n400 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:400:17\n    │\n400 │         vm.warp(block.timestamp + 7 days);\n    │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:466:9\n    │\n466 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:467:30\n    │\n467 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n470 │         vm.roll(startBlock + 25);\n    │         ──────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:468:27\n    │\n468 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n471 │         vm.warp(startTs + 30 minutes);\n    │         ───────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:490:9\n    │\n490 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:491:30\n    │\n491 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n495 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:492:27\n    │\n492 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n496 │             vm.warp(startTs + 10 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\n","passed":true},{"durationMs":145,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/fork/MainnetLaunch.t.sol:MainnetLaunchTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 585.70µs (0.00ns CPU time)\n\nRan 7 tests for test/Pricer.t.sol:PricerTest\n[PASS] testQuoteLegIsAdverseEvenUnderAV3Twap() (gas: 28379)\n[PASS] testTwapRefusesZeroSpanAndV4() (gas: 17708)\n[PASS] testV2TwapFromWrappingCumulative() (gas: 9484)\n[PASS] testV3TwapOfAConstantTickIsThatTick() (gas: 15421)\n[PASS] testV3TwapRoundsNegativeMeansDown() (gas: 14810)\n[PASS] testV3TwapWeightsByTime() (gas: 14677)\n[PASS] testV4SettlesOnTheAdverseExtreme() (gas: 26598)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 615.71µs (680.61µs CPU time)\n\nRan 7 tests for test/JudgeOracle.t.sol:JudgeOracleTest\n[PASS] testEmptySignedRankingIsAnExecutableNoWinnerResult() (gas: 247978)\n[PASS] testFiveIdsWithEoaSignatureFitStipend() (gas: 553767)\n[PASS] testFullRankingWithEoaSignatureFitsStipend() (gas: 633387)\n[PASS] testProtocolDigestSignatureAndSelectorConformanceOnClone() (gas: 3237905)\n[PASS] testRejectedAnswersDoNotConsumeThePendingRequest() (gas: 892198)\n[PASS] testRequestedHeadIsFilteredAndDeduplicatedWithoutPromotingTheTail() (gas: 250548)\n[PASS] testTimeoutRetryInvalidatesOldIntakeRequest() (gas: 523778)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 2.74ms (6.03ms CPU time)\n\nRan 8 tests for test/PriceHistory.t.sol:PriceHistoryTest\n[PASS] testBaselineRequiresMatureFreshHistory() (gas: 188329)\n[PASS] testEmptyVenueAndHubCannotBeCheckpointedObservedOrPriced() (gas: 284473)\n[PASS] testFuzzV4BaselineIsNeverFavourableToTheCall(int24,bool) (runs: 256, μ: 105965, ~: 106038)\nLogs:\n  Bound result 1\n\n[PASS] testHubBaselineUsesOppositeExtremeFromSettlement() (gas: 180188)\n[PASS] testLiveCheckpointCannotEraseHonestExtremesOrRestartTheClock() (gas: 224136)\n[PASS] testV2BaselineIgnoresSameBlockReservesDumpAndPumpBothOrientations() (gas: 467438)\n[PASS] testV3BaselineIgnoresSameBlockTickChangesBothOrientations() (gas: 417955)\n[PASS] testV3BaselineWeightsElapsedTime() (gas: 370983)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 10.83ms (9.46ms CPU time)\n\nRan 8 tests for test/AuditFindings.t.sol:AuditFindingsTest\n[PASS] testConversionAfterARealPriceFallNeedsAFreshMatureWindow() (gas: 1574034)\n[PASS] testEmptyV4ObservationIsRefused() (gas: 966273)\n[PASS] testExpiredBaselineRejectsPostWithoutTakingFunds() (gas: 643275)\n[PASS] testForfeitureConversionRejectsSameBlockDump() (gas: 1234412)\n[PASS] testLongRankingFitsIntakeStipend() (gas: 2191552)\n[PASS] testSameBlockDumpPostUnwindDoesNotWinBuy() (gas: 1911932)\n[PASS] testSameBlockPumpPostUnwindDoesNotWinSell() (gas: 1783360)\n[PASS] testUnpayableRankingRollsTheWholePoolForward() (gas: 2464505)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 21.51ms (10.80ms CPU time)\n\nRan 26 tests for test/Lifecycle.t.sol:LifecycleTest\n[PASS] testAttestedClassCannotBeSelfDeclared() (gas: 342970)\n[PASS] testCallbackSelectorPinned() (gas: 3361)\n[PASS] testFakeVenueIsRefused() (gas: 382643)\n[PASS] testFlagsAndBinding() (gas: 55816)\n[PASS] testForfeitsConvertToImdForThePot() (gas: 1111031)\n[PASS] testLeaderboardProRataWithCap() (gas: 3237594)\n[PASS] testNoDataRefunds() (gas: 921203)\n[PASS] testNoteTooSmall() (gas: 172902)\n[PASS] testNotedBuyTakesStampAndDeposit() (gas: 797709)\n[PASS] testNotedSellPaysOnePercentPlusStamp() (gas: 1106493)\n[PASS] testObservationsMustSpanAnHour() (gas: 1429115)\n[PASS] testPlainBuyTakesNothing() (gas: 229914)\n[PASS] testQuietSellPaysThreePercent() (gas: 336209)\n[PASS] testQuietThesisPoolSweeps() (gas: 305287)\n[PASS] testRetract() (gas: 944843)\n[PASS] testRightCallReturnsDepositAsImd() (gas: 1799432)\n[PASS] testSellingEarlyBreaksTheCall() (gas: 1767952)\n[PASS] testThesisParentChild() (gas: 1450566)\n[PASS] testThesisWithoutChildForfeits() (gas: 796691)\n[PASS] testTreasuryDrip() (gas: 347870)\n[PASS] testTwoBlockPumpObserveUnwindSettlesWrong() (gas: 1799481)\n[PASS] testUnansweredWeekCanBeRetried() (gas: 2439911)\n[PASS] testUpOnlyIsRefused() (gas: 340578)\n[PASS] testWeeklyThesisJudging() (gas: 3852889)\n[PASS] testWriterRefundCappedAtStamp() (gas: 1709522)\n[PASS] testWrongCallForfeitsWithKeeperReward() (gas: 1557388)\nSuite result: ok. 26 passed; 0 failed; 0 skipped; finished in 22.02ms (27.50ms CPU time)\n\nRan 3 tests for test/Implementations.t.sol:ImplementationsTest\n[PASS] testClonesInitializeOnceOnlyFromTheirHook() (gas: 4551159)\n[PASS] testFactoryDeploysAllFourWithoutArgumentsOrExternalDependencies() (gas: 34030325)\nLogs:\n  four implementation CREATE2 deployments (gas): 8694125\n\n[PASS] testImplementationsRejectInitialization() (gas: 81332)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 37.06ms (37.53ms CPU time)\n\nRan 7 test suites in 37.85ms (95.37ms CPU time): 59 tests passed, 0 failed, 1 skipped (60 total tests)\n","passed":true},{"durationMs":64,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"Marginalia.approve(address,uint256)\",\"Marginalia.transfer(address,uint256)\",\"Marginalia.transferFrom(address,address,uint256)\",\"MarginaliaHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"MarginaliaHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"MarginaliaHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"MarginaliaHook.claimDeposit(bytes32,bool)\",\"MarginaliaHook.claimLeaderboard(uint32)\",\"MarginaliaHook.claimRefund(bytes32)\",\"MarginaliaHook.drawForJudging(uint32,uint256,bool)\",\"MarginaliaHook.fundPot(uint256)\",\"MarginaliaHook.observe(bytes32)\",\"MarginaliaHook.payJudged(uint32,bytes32[3])\",\"MarginaliaHook.retract(bytes32,string)\",\"MarginaliaHook.sellPotMarg(uint256)\",\"MarginaliaHook.settle(bytes32)\",\"MarginaliaHook.settleThesis(bytes32)\",\"MarginaliaHook.sweep(uint8,uint32)\",\"MarginaliaHook.unlockCallback(bytes)\",\"MarginaliaJudge.convertForfeits()\",\"MarginaliaJudge.init(address,address,bytes32,address)\",\"MarginaliaJudge.onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"MarginaliaJudge.payJudged(uint32)\",\"MarginaliaJudge.requestJudging(uint32)\",\"MarginaliaRouter.checkpointVenue((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address))\",\"MarginaliaRouter.init(address,address)\",\"MarginaliaRouter.note((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address),uint256,uint256,uint256)\",\"MarginaliaRouter.sellWithNote((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address),uint256,uint256,uint256)\",\"MarginaliaRouter.uniswapV3SwapCallback(int256,int256,bytes)\",\"MarginaliaRouter.unlockCallback(bytes)\",\"MarginaliaTreasury.drip()\",\"MarginaliaTreasury.init(address)\"],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":141,\"README.md\":123,\"SPEC.md\":263,\"dependencies.json\":28,\"foundry.toml\":21,\"helper/.gitignore\":3,\"helper/package-lock.json\":737,\"helper/package.json\":20,\"helper/public/index.html\":82,\"helper/server.js\":90,\"helper/src/app.js\":203,\"jobs/launch-1-hook.json\":43,\"jobs/launch-2-contracts.json\":38,\"jobs/launch-A-implementations.json\":47,\"jobs/launch-A2-implementations.json\":41,\"jobs/launch-hook-v3.json\":43,\"launch.json\":22,\"remappings.txt\":4,\"src/HookFlags.sol\":33,\"src/Marginalia.sol\":12,\"src/MarginaliaHook.sol\":863,\"src/MarginaliaImpls.sol\":14,\"src/MarginaliaJudge.sol\":259,\"src/MarginaliaPricer.sol\":292,\"src/MarginaliaRouter.sol\":444,\"src/MarginaliaTreasury.sol\":53,\"src/MarginaliaTypes.sol\":108,\"src/OracleAttestation.sol\":221,\"src/interfaces/IIntake.sol\":15,\"src/interfaces/ILaunchFactory.sol\":49,\"test/AuditFindings.t.sol\":178,\"test/Implementations.t.sol\":96,\"test/JudgeOracle.t.sol\":270,\"test/Lifecycle.t.sol\":502,\"test/PriceHistory.t.sol\":233,\"test/Pricer.t.sol\":88,\"test/fork/MainnetLaunch.t.sol\":382,\"test/helpers/Fixture.sol\":278,\"test/mocks/MockERC20.sol\":13},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"b403073f12774acd8e2f118e93c55d3f6da12ce10d2c9b375faad3784f9cb349","verifiedTreeHash":"becc8828f8274d70b86cc1320e48cdb06a1efe9b","verifierVersion":"0.1.0+fdeb4d4a"},{"checks":[{"durationMs":90591,"exitCode":0,"name":"build","output":"Compiling 110 files with Solc 0.8.26\nSolc 0.8.26 finished in 90.38s\nCompiler run successful with warnings:\nWarning (8760): This declaration has the same name as another declaration.\n   --> src/MarginaliaHook.sol:379:9:\n    |\n379 |         uint32 week = _week();\n    |         ^^^^^^^^^^^\nNote: The other declaration is here:\n   --> src/MarginaliaHook.sol:644:5:\n    |\n644 |     function week() external view returns (uint32) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:709:9:\n    |\n709 |         uint256 pool = thesisPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:86:5:\n   |\n86 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2519): This declaration shadows an existing declaration.\n   --> src/MarginaliaHook.sol:730:9:\n    |\n730 |         uint256 pool = leaderboardPool[w];\n    |         ^^^^^^^^^^^^\nNote: The shadowed declaration is here:\n  --> src/MarginaliaHook.sol:86:5:\n   |\n86 |     PoolKey private pool;\n   |     ^^^^^^^^^^^^^^^^^^^^\n\nWarning (2018): Function state mutability can be restricted to pure\n   --> test/helpers/Fixture.sol:114:5:\n    |\n114 |     function priceOf(bytes32, address) external view returns (uint256) {\n    |     ^ (Relevant source part starts here and spans across multiple lines).\n\nWarning (2018): Function state mutability can be restricted to pure\n  --> test/fork/MainnetLaunch.t.sol:78:5:\n   |\n78 |     function _mine(bytes memory hookCode) internal view returns (bytes32 salt) {\n   |     ^ (Relevant source part starts here and spans across multiple lines).\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/MarginaliaTreasury.sol:51:9\n   │\n51 │         emit Dripped(day, amount);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/MarginaliaTreasury.sol:43:22\n   │\n43 │         uint32 day = uint32(block.timestamp / 1 days);\n   │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'uint32' is safe 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 `_status` is updated\n   ╭▸ src/MarginaliaJudge.sol:87:18\n   │\n87 │         imdOut = hook.sellPotMarg(marg);\n   │                  ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/MarginaliaJudge.sol:96:47\n   │\n96 │         for (uint256 i = 0; i < all.length && n < MAX_JUDGED; ++i) {\n   │                                               ━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n   ╭▸ src/MarginaliaJudge.sol:97:35\n   │\n97 │             (,,, bool hasChild) = hook.noteMeta(all[i]);\n   │                                   ━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[unused-return]: return value of an external call is not used\n   ╭▸ src/MarginaliaJudge.sol:97:35\n   │\n97 │             (,,, bool hasChild) = hook.noteMeta(all[i]);\n   │                                   ━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:152:15\n    │\n152 │             ++n;\n    │               ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaJudge.sol:156:33\n    │\n156 │             out[i - 1] = bytes1(uint8(48 + v % 10));\n    │                                 ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint8' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaJudge.sol:166:46\n    │\n166 │         if (requestOf[week] != bytes32(0) && block.timestamp < requestedAt[week] + ANSWER_DEADLINE) {\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/MarginaliaJudge.sol:169:52\n    │\n169 │         return eligibleTheses(week).length == 0 || block.timestamp >= (uint256(week) + 1) * 7 days + 28 days;\n    │                                                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[missing-events-access-control]: `jobHash` is changed without an event but is used for access control\n    ╭▸ src/MarginaliaRouter.sol:301:16\n    │\n301 │         delete jobHash;\n    │                ━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-events-access-control\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/MarginaliaHook.sol:71:38\n   │\n71 │     bytes32 public constant ACTION = bytes32(\"oracle.request@oracle-1\");\n   │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes32' is safe 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/MarginaliaHook.sol:189:44\n    │\n189 │     constructor(IPoolManager poolManager_, address token_, address factory_) {\n    │                                            ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[reentrancy-no-eth]: external call can be reentered before `requestOf` is updated\n    ╭▸ src/MarginaliaJudge.sol:185:9\n    │\n185 │         hook.drawForJudging(day, price, retry);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[reentrancy-no-eth]: external call can be reentered before `requestOf` is updated\n    ╭▸ src/MarginaliaJudge.sol:188:21\n    │\n188 │           requestId = intake.request(\n    │ ┏━━━━━━━━━━━━━━━━━━━━━┛\n189 │ ┃             action, body, IIntake.Callback(address(this), this.onOracleResult.selector), imd, price\n190 │ ┃         );\n    │ ┗━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaJudge.sol:177:41\n    │\n177 │         if (judgedSet[day] || (retry && block.timestamp < requestedAt[day] + ANSWER_DEADLINE)) {\n    │                                         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaJudge.sol:196:9\n    │\n196 │         emit Requested(day, requestId, price);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaJudge.sol:194:28\n    │\n194 │         requestedAt[day] = uint64(block.timestamp);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaJudge.sol:224:9\n    │\n224 │ ┏         emit Judged(\n225 │ ┃             day,\n226 │ ┃             [\n227 │ ┃                 count > 0 ? ranked[0] : bytes32(0),\n    ‡ ┃\n231 │ ┃         );\n    │ ┗━━━━━━━━━━┛\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:245:17\n    │\n245 │             if (dup) continue;\n    │                 ━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaJudge.sol:238:50\n    │\n238 │         for (uint256 i = 0; i < ranked.length && kept < 3; ++i) {\n    │                                                  ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaJudge.sol:239:77\n    │\n239 │             (address author, uint32 noteWeek, bool thesis, bool hasChild) = hook.noteMeta(ranked[i]);\n    │                                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_status` is updated\n    ╭▸ src/MarginaliaJudge.sol:257:9\n    │\n257 │         hook.payJudged(day, top);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/MarginaliaPricer.sol:85:13\n   │\n85 │             n += 1;\n   │             ━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaPricer.sol:119:33\n    │\n119 │         if (w.startedAt == 0 || block.timestamp > uint256(w.startedAt) + POST_MAX_AGE) {\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:120:34\n    │\n120 │             return T.PriceWindow(uint64(block.timestamp), uint64(block.number), x, x, x, q, q);\n    │                                  ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:120:59\n    │\n120 │             return T.PriceWindow(uint64(block.timestamp), uint64(block.number), x, x, x, q, q);\n    │                                                           ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe 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/MarginaliaPricer.sol:141:20\n    │\n141 │                 || block.timestamp < uint256(w.startedAt) + POST_MIN_SPAN\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/MarginaliaPricer.sol:142:20\n    │\n142 │                 || block.timestamp > uint256(w.startedAt) + POST_MAX_AGE\n    │                    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:148:69\n    │\n148 │             x = twap(v.kind, v.xIsToken0, w.xStart, w.startedAt, x, uint64(block.timestamp));\n    │                                                                     ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:165:55\n    │\n165 │         else if (v.kind == T.VenueKind.UniV3) xRead = uint256(_v3Cumulative(ref));\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/MarginaliaPricer.sol:208:28\n    │\n208 │             int256 delta = int256(c2) - int256(c1);\n    │                            ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:208:41\n    │\n208 │             int256 delta = int256(c2) - int256(c1);\n    │                                         ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:209:35\n    │\n209 │             int256 mean = delta / int256(dt);\n    │                                   ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:210:38\n    │\n210 │             if (delta < 0 && delta % int256(dt) != 0) mean -= 1; // round toward negative infinity, as v3 does\n    │                                      ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:212:57\n    │\n212 │             return fromSqrt(TickMath.getSqrtPriceAtTick(int24(mean)), xIsToken0);\n    │                                                         ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int24' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaPricer.sol:234:37\n    │\n234 │             (uint160 sqrtP,,,,,,) = IUniswapV3PoolOracle(ref).slot0();\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/MarginaliaPricer.sol:238:41\n    │\n238 │             (uint112 r0, uint112 r1,) = IUniswapV2PairOracle(ref).getReserves();\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/MarginaliaPricer.sol:260:33\n    │\n260 │         (int56[] memory cum,) = IUniswapV3PoolOracle(pool).observe(ago);\n    │                                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaPricer.sol:270:24\n    │\n270 │         uint32 nowTs = uint32(block.timestamp);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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/MarginaliaRouter.sol:249:13\n    │\n249 │         if (block.timestamp > deadline) revert Expired();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:250:41\n    │\n250 │         if (amountIn == 0 || amountIn > uint256(uint128(type(int128).max))) revert InvalidSwap();\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/MarginaliaRouter.sol:250:49\n    │\n250 │         if (amountIn == 0 || amountIn > uint256(uint128(type(int128).max))) revert InvalidSwap();\n    │                                                 ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:336:9\n    │\n336 │         emit Noted(job.payer, job.sellMarg, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:318:18\n    │\n318 │                 -int256(job.amountIn),\n    │                  ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:326:25\n    │\n326 │         uint256 spent = uint256(uint128(-inputDelta));\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/MarginaliaRouter.sol:326:33\n    │\n326 │         uint256 spent = uint256(uint128(-inputDelta));\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:327:28\n    │\n327 │         uint256 received = uint256(uint128(outputDelta));\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/MarginaliaRouter.sol:327:36\n    │\n327 │         uint256 received = uint256(uint128(outputDelta));\n    │                                    ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:371:9\n    │\n371 │         emit XTraded(payer, X_V4, xIn, xOut, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:353:18\n    │\n353 │                 -int256(x.amountIn),\n    │                  ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:361:25\n    │\n361 │         uint256 spent = uint256(uint128(-inputDelta));\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/MarginaliaRouter.sol:361:33\n    │\n361 │         uint256 spent = uint256(uint128(-inputDelta));\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:362:20\n    │\n362 │         received = uint256(uint128(outputDelta));\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/MarginaliaRouter.sol:362:28\n    │\n362 │         received = uint256(uint128(outputDelta));\n    │                            ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:401:9\n    │\n401 │         emit XTraded(payer, X_V3, xIn, xOut, spent, received);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:392:13\n    │\n392 │             int256(x.amountIn),\n    │             ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaRouter.sol:397:25\n    │\n397 │         uint256 spent = uint256(zeroForOne ? a0 : a1);\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/MarginaliaRouter.sol:407:78\n    │\n407 │         if (amount0Delta > 0) IERC20(pool.token0()).safeTransfer(msg.sender, uint256(amount0Delta));\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/MarginaliaRouter.sol:408:78\n    │\n408 │         if (amount1Delta > 0) IERC20(pool.token1()).safeTransfer(msg.sender, uint256(amount1Delta));\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaRouter.sol:436:9\n    │\n436 │         emit XTraded(payer, X_V2, xIn, xOut, actualIn, received);\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/MarginaliaRouter.sol:424:37\n    │\n424 │         (uint112 r0, uint112 r1,) = pair.getReserves();\n    │                                     ━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:291:21\n    │\n291 │                 if (uint256(-params.amountSpecified) <= STAMP * 2) revert NoteTooSmall();\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/MarginaliaHook.sol:299:17\n    │\n299 │             if (uint256(-params.amountSpecified) <= depositMarg * 2) revert NoteTooSmall();\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/MarginaliaHook.sol:305:30\n    │\n305 │             specifiedTake = (uint256(params.amountSpecified) * bps + (10_000 - bps) - 1) / (10_000 - bps);\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-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:385:9\n    │\n385 │         emit Accrued(day, 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/MarginaliaHook.sol:457:9\n    │\n457 │ ┏         emit NotePosted(\n458 │ ┃             id,\n459 │ ┃             author,\n460 │ ┃             p.x,\n    ‡ ┃\n469 │ ┃             p.text\n470 │ ┃         );\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/MarginaliaHook.sol:337:13\n    │\n337 │             emit SwapFee(true, author, poolImd, 0, STAMP);\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/MarginaliaHook.sol:353:13\n    │\n353 │             emit SwapFee(false, author, poolImd, fee - STAMP, STAMP);\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/MarginaliaHook.sol:372:9\n    │\n372 │         emit SwapFee(false, tx.origin, poolImd, quietFee, 0);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:322:33\n    │\n322 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\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/MarginaliaHook.sol:322:41\n    │\n322 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\n    │                                         ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:322:63\n    │\n322 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\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/MarginaliaHook.sol:322:71\n    │\n322 │         uint256 poolImd = buy ? uint256(uint128(-imdDelta)) : uint256(uint128(imdDelta));\n    │                                                                       ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:327:29\n    │\n327 │             uint256 netIn = uint256(-params.amountSpecified) - STAMP;\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/MarginaliaHook.sol:329:31\n    │\n329 │             uint256 margOut = uint256(uint128(margDelta));\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/MarginaliaHook.sol:329:39\n    │\n329 │             uint256 margOut = uint256(uint128(margDelta));\n    │                                       ━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:362:25\n    │\n362 │             quietFee = (uint256(params.amountSpecified) * bps + (10_000 - bps) - 1) / (10_000 - bps);\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/MarginaliaHook.sol:363:28\n    │\n363 │             if (poolImd != uint256(params.amountSpecified) + quietFee) revert PartialFill();\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:445:17\n    │\n445 │             if (weekTheses[_week()].length < MAX_DAY_NOTES) weekTheses[_week()].push(id);\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:437:22\n    │\n437 │         n.postedAt = uint64(block.timestamp);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe 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/MarginaliaHook.sol:489:13\n    │\n489 │         if (block.timestamp < end) revert TooEarly();\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/MarginaliaHook.sol:490:13\n    │\n490 │         if (block.timestamp > end + SETTLE_WINDOW) revert TooLate();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:498:32\n    │\n498 │         obs.push(T.Observation(uint64(block.timestamp), uint64(block.number), xRead, quoteRead, balance));\n    │                                ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:498:57\n    │\n498 │         obs.push(T.Observation(uint64(block.timestamp), uint64(block.number), xRead, quoteRead, balance));\n    │                                                         ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:499:27\n    │\n499 │         emit Observed(id, uint64(block.timestamp), xRead, quoteRead, balance);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/MarginaliaHook.sol:548:35\n    │\n548 │         emit Settled(id, outcome, settlePrice, scoreDelta, msg.sender);\n    │                                   ━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:507:13\n    │\n507 │         if (block.timestamp <= end + SETTLE_WINDOW) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:618:13\n    │\n618 │             emit ThesisReleased(n.parentId);\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/MarginaliaHook.sol:548:9\n    │\n548 │         emit Settled(id, outcome, settlePrice, scoreDelta, msg.sender);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:534:26\n    │\n534 │             scoreDelta = int256(_difficulty(n));\n    │                          ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:537:27\n    │\n537 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:541:27\n    │\n541 │             scoreDelta = -int256(_difficulty(n));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:556:13\n    │\n556 │         if (block.timestamp >= horizonEnd(id)) revert TooLate();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:565:9\n    │\n565 │         emit Retracted(id, text);\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/MarginaliaHook.sol:566:9\n    │\n566 │         emit Settled(id, T.Status.Retracted, 0, scoreDelta, address(0));\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:558:30\n    │\n558 │         int256 scoreDelta = -int256(_difficulty(n) / 2);\n    │                              ━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/MarginaliaHook.sol:574:13\n    │\n574 │         if (block.timestamp <= uint256(n.postedAt) + THESIS_GRACE) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:577:9\n    │\n577 │         emit ThesisForfeited(id);\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/MarginaliaHook.sol:595:9\n    │\n595 │         emit DepositClaimed(id, n.author, asImd, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:633:16\n    │\n633 │         return uint32(block.timestamp / 1 days);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:637:16\n    │\n637 │         return uint32(block.timestamp / 7 days);\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:658:38\n    │\n658 │         uint256 prevPos = prev > 0 ? uint256(prev) : 0;\n    │                                      ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:659:38\n    │\n659 │         uint256 nextPos = next > 0 ? uint256(next) : 0;\n    │                                      ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:669:9\n    │\n669 │         emit PotFunded(_today(), amount, msg.sender);\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/MarginaliaHook.sol:681:9\n    │\n681 │         emit PotMargSold(amount, imdOut, _today());\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:701:27\n    │\n701 │         return (n.author, uint32(uint256(n.postedAt) / 7 days), n.targetBps == 0, n.children > 0);\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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 `thesisPool` is updated\n    ╭▸ src/MarginaliaHook.sol:800:28\n    │\n800 │         bytes memory out = poolManager.unlock(data);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/MarginaliaHook.sol:800:28\n    │\n800 │         bytes memory out = poolManager.unlock(data);\n    │                            ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:723:9\n    │\n723 │         emit JudgedPaid(w, paidAmounts);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/MarginaliaHook.sol:801:39\n    │\n801 │         if (unlockHash != bytes32(0)) revert InvalidUnlock();\n    │                                       ━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:731:47\n    │\n731 │         uint256 share = FullMath.mulDiv(pool, uint256(s), weekTotal[w]);\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[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/MarginaliaHook.sol:737:13\n    │\n737 │         if (w >= _week()) revert TooEarly();\n    │             ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:744:9\n    │\n744 │         emit LeaderboardClaimed(w, msg.sender, amount);\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/MarginaliaHook.sol:751:13\n    │\n751 │         if (n.day >= _today()) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/MarginaliaHook.sol:761:9\n    │\n761 │         emit RefundClaimed(id, msg.sender, amount);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:759:30\n    │\n759 │         notesPerDay[n.day] = uint32(count - 1);\n    │                              ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint32' is safe 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/MarginaliaHook.sol:770:17\n    │\n770 │             if (block.timestamp < (uint256(epoch) + 1) * 1 days + SWEEP_AFTER) revert TooEarly();\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/MarginaliaHook.sol:774:17\n    │\n774 │             if (block.timestamp < (uint256(epoch) + 1) * 7 days + SWEEP_AFTER) revert TooEarly();\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/MarginaliaHook.sol:778:17\n    │\n778 │             if (block.timestamp < (uint256(epoch) + 1) * 7 days + SWEEP_AFTER) revert TooEarly();\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:811:40\n    │\n811 │             address currency = address(uint160(extra));\n    │                                        ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint160' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/MarginaliaHook.sol:820:13\n    │\n820 │             poolManager.settle();\n    │             ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:830:22\n    │\n830 │                     -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/MarginaliaHook.sol:839:17\n    │\n839 │             if (uint256(uint128(-margDelta)) != amount) revert InvalidUnlock();\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/MarginaliaHook.sol:839:25\n    │\n839 │             if (uint256(uint128(-margDelta)) != amount) revert InvalidUnlock();\n    │                         ━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/MarginaliaHook.sol:841:30\n    │\n841 │             uint256 imdOut = uint256(uint128(imdDelta));\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/MarginaliaHook.sol:841:38\n    │\n841 │             uint256 imdOut = uint256(uint128(imdDelta));\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[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n   ╭▸ test/AuditFindings.t.sol:19:30\n   │\n19 │         uint256 startBlock = block.number;\n   │                              ━━━━━━━━━━━━\n   ‡\n23 │             vm.roll(startBlock + 25 * (i + 1));\n   │             ────────────────────────────────── `vm.roll` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockNumber()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/AuditFindings.t.sol:20:27\n   │\n20 │         uint256 startTs = block.timestamp;\n   │                           ━━━━━━━━━━━━━━━\n   ‡\n24 │             vm.warp(startTs + 31 minutes * (i + 1));\n   │             ─────────────────────────────────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/AuditFindings.t.sol:18:9\n    │\n 18 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/AuditFindings.t.sol:65:9\n    │\n 65 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n   ╭▸ test/AuditFindings.t.sol:65:17\n   │\n65 │         vm.warp(block.timestamp + 7 days);\n   │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n   │\n   ├ help: capture it with `vm.getBlockTimestamp()` instead\n   ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:126:9\n    │\n126 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:127:30\n    │\n127 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n131 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:128:27\n    │\n128 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n132 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:154:9\n    │\n154 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:155:30\n    │\n155 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n159 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:156:27\n    │\n156 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n160 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:178:9\n    │\n178 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:179:30\n    │\n179 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n183 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:180:27\n    │\n180 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n184 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:270:9\n    │\n270 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:270:17\n    │\n270 │         vm.warp(block.timestamp + 7 days);\n    │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:320:9\n    │\n320 │         vm.warp(hook.horizonEnd(a));\n    │         ─────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:321:30\n    │\n321 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n326 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:322:27\n    │\n322 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n327 │             vm.warp(startTs + 30 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:400:9\n    │\n400 │         vm.warp(block.timestamp + 7 days);\n    │         ───────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:400:17\n    │\n400 │         vm.warp(block.timestamp + 7 days);\n    │         ────────━━━━━━━━━━━━━━━────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:466:9\n    │\n466 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:467:30\n    │\n467 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n470 │         vm.roll(startBlock + 25);\n    │         ──────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:468:27\n    │\n468 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n471 │         vm.warp(startTs + 30 minutes);\n    │         ───────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/helpers/Fixture.sol:259:50\n    │\n259 │         received = router.note(p, key, imdIn, 1, block.timestamp + 1);\n    │                                                  ━━━━━━━━━━━━━━━\n    │\n    ⸬  test/Lifecycle.t.sol:490:9\n    │\n490 │         vm.warp(hook.horizonEnd(id));\n    │         ──────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.number` may be reused across `vm.roll`\n    ╭▸ test/Lifecycle.t.sol:491:30\n    │\n491 │         uint256 startBlock = block.number;\n    │                              ━━━━━━━━━━━━\n    ‡\n495 │             vm.roll(startBlock + 25 * (i + 1));\n    │             ────────────────────────────────── `vm.roll` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockNumber()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/Lifecycle.t.sol:492:27\n    │\n492 │         uint256 startTs = block.timestamp;\n    │                           ━━━━━━━━━━━━━━━\n    ‡\n496 │             vm.warp(startTs + 10 minutes * (i + 1));\n    │             ─────────────────────────────────────── `vm.warp` changes this environment here\n    │\n    ├ help: capture it with `vm.getBlockTimestamp()` instead\n    ╰ help: https://getfoundry.sh/forge/linting/environment-read-across-mutation\n\n","passed":true},{"durationMs":1134,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/fork/MainnetLaunch.t.sol:MainnetLaunchTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 521.47µs (0.00ns CPU time)\n\nRan 7 tests for test/JudgeOracle.t.sol:JudgeOracleTest\n[PASS] testEmptySignedRankingIsAnExecutableNoWinnerResult() (gas: 247978)\n[PASS] testFiveIdsWithEoaSignatureFitStipend() (gas: 553767)\n[PASS] testFullRankingWithEoaSignatureFitsStipend() (gas: 633387)\n[PASS] testProtocolDigestSignatureAndSelectorConformanceOnClone() (gas: 3237905)\n[PASS] testRejectedAnswersDoNotConsumeThePendingRequest() (gas: 892198)\n[PASS] testRequestedHeadIsFilteredAndDeduplicatedWithoutPromotingTheTail() (gas: 250548)\n[PASS] testTimeoutRetryInvalidatesOldIntakeRequest() (gas: 523778)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 7.39ms (6.32ms CPU time)\n\nRan 7 tests for test/Pricer.t.sol:PricerTest\n[PASS] testQuoteLegIsAdverseEvenUnderAV3Twap() (gas: 28379)\n[PASS] testTwapRefusesZeroSpanAndV4() (gas: 17708)\n[PASS] testV2TwapFromWrappingCumulative() (gas: 9484)\n[PASS] testV3TwapOfAConstantTickIsThatTick() (gas: 15421)\n[PASS] testV3TwapRoundsNegativeMeansDown() (gas: 14810)\n[PASS] testV3TwapWeightsByTime() (gas: 14677)\n[PASS] testV4SettlesOnTheAdverseExtreme() (gas: 26598)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 9.31ms (690.90µs CPU time)\n\nRan 8 tests for test/AuditFindings.t.sol:AuditFindingsTest\n[PASS] testConversionAfterARealPriceFallNeedsAFreshMatureWindow() (gas: 1574034)\n[PASS] testEmptyV4ObservationIsRefused() (gas: 966273)\n[PASS] testExpiredBaselineRejectsPostWithoutTakingFunds() (gas: 643275)\n[PASS] testForfeitureConversionRejectsSameBlockDump() (gas: 1234412)\n[PASS] testLongRankingFitsIntakeStipend() (gas: 2191552)\n[PASS] testSameBlockDumpPostUnwindDoesNotWinBuy() (gas: 1911932)\n[PASS] testSameBlockPumpPostUnwindDoesNotWinSell() (gas: 1783360)\n[PASS] testUnpayableRankingRollsTheWholePoolForward() (gas: 2464505)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 30.61ms (6.20ms CPU time)\n\nRan 14 tests for test/CompanionFailures.t.sol:RouterFailuresTest\n[PASS] testExpiredDeadlineTakesNothing() (gas: 736205)\n[PASS] testExpiredWindowRefusesPostsUntilAFreshCheckpointMatures() (gas: 1907379)\n[PASS] testInitRequiresAManagerWithCode() (gas: 4129373)\n[PASS] testSlippageFloorRefundsEverything() (gas: 707995)\n[PASS] testStrangersCannotEnterTheCallbacks() (gas: 133302)\n[PASS] testTradeAndNoteRefusesNoTradeZeroTradeAndNativeInput() (gas: 290709)\n[PASS] testTradedNoteMustBeAboutTheTokenTraded() (gas: 1058816)\n[PASS] testTradedV4LegUnderAForeignHookOrEmptyPoolIsRefused() (gas: 396225)\n[PASS] testUnapprovedOrUnfundedAuthorIsRefused() (gas: 224289)\n[PASS] testV4VenueUnderAForeignHookIsRefused() (gas: 69781)\n[PASS] testV4VenueWithoutLiquidityIsRefused() (gas: 134983)\n[PASS] testVenueFieldsAreDerivedFromThePoolNotTheCaller() (gas: 48643)\n[PASS] testVenueKindNoneIsRefusedForAPricedCall() (gas: 116291)\n[PASS] testZeroAndOversizedAmountsAreRefused() (gas: 138629)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 34.92ms (6.75ms CPU time)\n\nRan 26 tests for test/Lifecycle.t.sol:LifecycleTest\n[PASS] testAttestedClassCannotBeSelfDeclared() (gas: 342970)\n[PASS] testCallbackSelectorPinned() (gas: 3361)\n[PASS] testFakeVenueIsRefused() (gas: 382643)\n[PASS] testFlagsAndBinding() (gas: 55816)\n[PASS] testForfeitsConvertToImdForThePot() (gas: 1111031)\n[PASS] testLeaderboardProRataWithCap() (gas: 3237594)\n[PASS] testNoDataRefunds() (gas: 921203)\n[PASS] testNoteTooSmall() (gas: 172902)\n[PASS] testNotedBuyTakesStampAndDeposit() (gas: 797709)\n[PASS] testNotedSellPaysOnePercentPlusStamp() (gas: 1106493)\n[PASS] testObservationsMustSpanAnHour() (gas: 1429115)\n[PASS] testPlainBuyTakesNothing() (gas: 229914)\n[PASS] testQuietSellPaysThreePercent() (gas: 336209)\n[PASS] testQuietThesisPoolSweeps() (gas: 305287)\n[PASS] testRetract() (gas: 944843)\n[PASS] testRightCallReturnsDepositAsImd() (gas: 1799432)\n[PASS] testSellingEarlyBreaksTheCall() (gas: 1767952)\n[PASS] testThesisParentChild() (gas: 1450566)\n[PASS] testThesisWithoutChildForfeits() (gas: 796691)\n[PASS] testTreasuryDrip() (gas: 347870)\n[PASS] testTwoBlockPumpObserveUnwindSettlesWrong() (gas: 1799481)\n[PASS] testUnansweredWeekCanBeRetried() (gas: 2439911)\n[PASS] testUpOnlyIsRefused() (gas: 340578)\n[PASS] testWeeklyThesisJudging() (gas: 3852889)\n[PASS] testWriterRefundCappedAtStamp() (gas: 1709522)\n[PASS] testWrongCallForfeitsWithKeeperReward() (gas: 1557388)\nSuite result: ok. 26 passed; 0 failed; 0 skipped; finished in 49.13ms (17.33ms CPU time)\n\nRan 22 tests for test/CompanionFailures.t.sol:JudgeFailuresTest\n[PASS] testAnswerAtTheExactExpiryStillCountsAndOneSecondLaterDoesNot() (gas: 1256849)\n[PASS] testAnswerForAWeekAlreadyJudgedIsRefused() (gas: 1320372)\n[PASS] testAnswerSignedByAnotherKeyIsRefused() (gas: 1069257)\n[PASS] testAnswerSignedForAnotherConsumerIsRefused() (gas: 3867964)\n[PASS] testConvertForfeitsWithAnEmptyPotIsANoOp() (gas: 234416)\n[PASS] testCurrentAndFutureWeeksCannotBeRequested() (gas: 128441)\n[PASS] testEligibleThesesAreCappedAtTheJudgedMaximum() (gas: 14217130)\n[PASS] testImplementationHasAPlaceholderSignerAndCannotBeConfigured() (gas: 2641967)\n[PASS] testInitRequiresEveryConfigurationValue() (gas: 2868474)\n[PASS] testIntakeReturningAnIdAlreadyPendingIsRefused() (gas: 1598901)\n[PASS] testJudgedOfFiltersWrongWeekShortFormAndChildlessIds() (gas: 1439606)\n[PASS] testJudgedWeekCannotBeRequestedAgainEvenAfterTheDeadline() (gas: 1242321)\n[PASS] testMalformedAnswerBytesAreRefused() (gas: 1067201)\n[PASS] testOnlyTheHeadOfThreeIsStoredAndTheTailNeverPromotes() (gas: 1221615)\n[PASS] testPayBeforeAnAnswerReverts() (gas: 1064098)\n[PASS] testPayIsPermissionlessAndOnce() (gas: 1438334)\n[PASS] testQuestionBodyNamesTheConsumerChainAndEligibleIdsOnly() (gas: 2516124)\n[PASS] testRepeatRequestBeforeTheDeadlineIsRefused() (gas: 1418751)\n[PASS] testRequestDrawsExactlyThePriceAndKeepsNothing() (gas: 1028030)\n[PASS] testWeekClosedStates() (gas: 1447170)\n[PASS] testWeekWithoutEligibleThesesCannotBeRequested() (gas: 244511)\n[PASS] testZeroAndExcessiveOraclePricesAreRefused() (gas: 1345655)\nSuite result: ok. 22 passed; 0 failed; 0 skipped; finished in 52.80ms (22.70ms CPU time)\n\nRan 3 tests for test/Implementations.t.sol:ImplementationsTest\n[PASS] testClonesInitializeOnceOnlyFromTheirHook() (gas: 4551159)\n[PASS] testFactoryDeploysAllFourWithoutArgumentsOrExternalDependencies() (gas: 34030325)\nLogs:\n  four implementation CREATE2 deployments (gas): 8694125\n\n[PASS] testImplementationsRejectInitialization() (gas: 81332)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 61.70ms (48.21ms CPU time)\n\nRan 8 tests for test/PriceHistory.t.sol:PriceHistoryTest\n[PASS] testBaselineRequiresMatureFreshHistory() (gas: 188329)\n[PASS] testEmptyVenueAndHubCannotBeCheckpointedObservedOrPriced() (gas: 284473)\n[PASS] testFuzzV4BaselineIsNeverFavourableToTheCall(int24,bool) (runs: 256, μ: 105917, ~: 106038)\nLogs:\n  Bound result 12475\n\n[PASS] testHubBaselineUsesOppositeExtremeFromSettlement() (gas: 180188)\n[PASS] testLiveCheckpointCannotEraseHonestExtremesOrRestartTheClock() (gas: 224136)\n[PASS] testV2BaselineIgnoresSameBlockReservesDumpAndPumpBothOrientations() (gas: 467438)\n[PASS] testV3BaselineIgnoresSameBlockTickChangesBothOrientations() (gas: 417955)\n[PASS] testV3BaselineWeightsElapsedTime() (gas: 370983)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 67.71ms (55.42ms CPU time)\n\nRan 9 tests for test/CompanionFailures.t.sol:TreasuryFailuresTest\n[PASS] testDripFailsWhenTheHookCannotTakeTheFunds() (gas: 673929)\n[PASS] testDripIsPermissionlessAndCompounds() (gas: 518661)\n[PASS] testDripOfDustRoundsToZeroAndReverts() (gas: 258318)\n[PASS] testDripWithNothingHeldReverts() (gas: 54033)\n[PASS] testInitOnlyByTheNamedHookAndOnlyOnce() (gas: 623926)\n[PASS] testInitRefusesTheZeroHook() (gas: 556415)\n[PASS] testNoWithdrawOrAdminSurface() (gas: 274868)\n[PASS] testSecondDripOnTheSameDayRevertsAndTheNextDayWorks() (gas: 372660)\n[PASS] testTreasuryRefusesEth() (gas: 71164)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 67.77ms (2.02ms CPU time)\n\nRan 26 tests for test/PricerProperties.t.sol:PricerPropertiesTest\n[PASS] testDifficultyAnchors() (gas: 56223)\n[PASS] testDifficultyRefusesAZeroHorizon() (gas: 10041)\n[PASS] testDifficultyTiersStepExactlyAtTheThresholds() (gas: 79054)\n[PASS] testEmptyPoolsAreRefusedOnBothLegs() (gas: 161684)\n[PASS] testEthQuoteIsOnlyPriceableOnMainnet() (gas: 40834)\n[PASS] testFromSqrtRefusesAnEmptyOrUnpriceableReading() (gas: 53718)\n[PASS] testFuzzAppendingAnObservationNeverHelpsTheCall(uint256[16],uint256[16],uint8) (runs: 1000, μ: 129396, ~: 113433)\nLogs:\n  Bound result 6\n  Bound result 599854350762790934852094103760\n  Bound result 847865178913917604669539008950\n  Bound result 13\n  Bound result 412235525507923599471462222593\n  Bound result 240\n  Bound result 172659785746308767912853866237\n  Bound result 594362257156117521877131830374\n  Bound result 570259129129331598331926008267\n  Bound result 777367778929329344497265724044\n  Bound result 13692214168611488135\n  Bound result 39288996011183821751806058084\n  Bound result 932267908217225693503364702615\n\n[PASS] testFuzzBuyDifficultyGrowsWithTheTarget(uint32,uint32,uint16,uint256) (runs: 1000, μ: 36825, ~: 36913)\nLogs:\n  Bound result 3621425\n  Bound result 9723399\n  Bound result 3\n  Bound result 666867414538923414944393330544\n\n[PASS] testFuzzCheckpointKeepsStartAndWidensExtremes(uint160,uint160,uint256) (runs: 512, μ: 141421, ~: 141733)\nLogs:\n  Bound result 1266412660188944036550059384067\n  Bound result 1266412660188944021221873969608\n  Bound result 21409\n\n[PASS] testFuzzDifficultyFallsWithTheHorizon(uint32,uint16,uint16,uint256) (runs: 1000, μ: 36615, ~: 36764)\nLogs:\n  Bound result 753413\n  Bound result 18\n  Bound result 3\n  Bound result 666867414538923414944393330544\n\n[PASS] testFuzzFromSqrtIsMonotoneAndInverts(uint160,uint160) (runs: 1000, μ: 23115, ~: 21173)\nLogs:\n  Bound result 1461446703485210103287273052203988822374509850544\n  Bound result 1461446703485210103287273052203988822374428865562\n\n[PASS] testFuzzLog2IsBracketedAndMonotone(uint256,uint256) (runs: 1000, μ: 39306, ~: 38505)\nLogs:\n  Bound result 10002\n  Bound result 5814743190357286182231728440137275494294\n\n[PASS] testFuzzLog2IsExactAtPowersOfTwo(uint8) (runs: 512, μ: 16016, ~: 14429)\nLogs:\n  Bound result 0\n\n[PASS] testFuzzPostPriceWindowBoundaries(uint256,bool) (runs: 512, μ: 54198, ~: 51968)\nLogs:\n  Bound result 4551\n\n[PASS] testFuzzSellDifficultyGrowsAsTheTargetFalls(uint32,uint32,uint16,uint256) (runs: 1000, μ: 36304, ~: 36283)\nLogs:\n  Bound result 2426\n  Bound result 2400\n  Bound result 3\n  Bound result 666867414538923414944393330544\n\n[PASS] testFuzzSqrtIsTheIntegerFloor(uint256) (runs: 1000, μ: 22326, ~: 19705)\nLogs:\n  Bound result 16714321517831147353034354968001673451182657334\n\n[PASS] testFuzzV2TwapOfAConstantRatioIsThatRatio(uint112,uint112,uint32,bool) (runs: 512, μ: 21228, ~: 21130)\nLogs:\n  Bound result 13496\n  Bound result 5192296858534827628530496329220095\n  Bound result 6171\n\n[PASS] testFuzzV3SettlementIgnoresMiddleReadings(int24,uint256[16],uint8,bool) (runs: 512, μ: 63354, ~: 58121)\nLogs:\n  Bound result -4667\n  Bound result 5\n\n[PASS] testFuzzV4SettlesOnTheExtremeOfEveryObservation(uint256[16],uint256[16],uint8) (runs: 1000, μ: 99778, ~: 89718)\nLogs:\n  Bound result 1\n  Bound result 503055086477857490365086929598\n  Bound result 949625925136\n\n[PASS] testObserveRefusesUnknownVenuesAndUnpriceableQuotes() (gas: 150312)\n[PASS] testPostPriceRefusesAnEmptyWindow() (gas: 15273)\n[PASS] testSellDifficultyRefusesAZeroTarget() (gas: 9408)\n[PASS] testSettlementRefusesAnEmptyOrUnspannedSeries() (gas: 38963)\n[PASS] testSqrtPins() (gas: 37798)\n[PASS] testTwapRefusesTimeRunningBackwards() (gas: 9110)\n[PASS] testV3TwapRefusesAMeanTickOutsideTheRange() (gas: 27126)\nSuite result: ok. 26 passed; 0 failed; 0 skipped; finished in 67.90ms (723.88ms CPU time)\n\nRan 1 test for test/RouterInvariant.t.sol:RouterInvariantTest\n[PASS]\nRouterInvariantTest invariants:\n[PASS] invariant_bindingsPinned\n[PASS] invariant_everyNoteCameThroughTheRouter\n[PASS] invariant_managerBacksTheHooksClaims\n[PASS] invariant_routerKeepsNothing\n RouterInvariantTest invariants (runs: 48, calls: 1920, reverts: 4)\n\n╭---------------+----------------+-------+---------+----------╮\n| Contract      | Selector       | Calls | Reverts | Discards |\n+=============================================================+\n| RouterHandler | advance        | 203   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | checkpoint     | 204   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | noteBuy        | 429   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | noteSell       | 220   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | plainBuy       | 238   | 4       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | plainSell      | 209   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | strayCallbacks | 203   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| RouterHandler | thesis         | 214   | 0       | 0        |\n╰---------------+----------------+-------+---------+----------╯\n\nLogs:\n  Bound result 2\n  Bound result 18265710719703266193221\n  Bound result 2\n  Bound result 115788164\n  Bound result 50033\n  Bound result 83\n  Bound result 0\n  Bound result 2159\n  Bound result 14001\n  Bound result 7\n  Bound result 1\n  Bound result 10\n  Bound result 10\n  Bound result 3\n  Bound result 0\n  Bound result 2739854339\n  Bound result 6098\n  Bound result 62\n  Bound result 2222\n  Bound result 360\n  Bound result 0\n  Bound result 1\n  Bound result 827628530496329220096\n  Bound result 57801\n  Bound result 37\n  Bound result 798106468151483350530\n  Bound result 0\n  Bound result 3508\n  Bound result 999\n  Bound result 2378\n  Bound result 56\n  Bound result 1\n  Bound result 0\n  Bound result 1119\n  Bound result 0\n  Bound result 3405\n  Bound result 1\n  Bound result 11794\n  Bound result 2\n  Bound result 993838967003777088094\n  Bound result 29628\n  Bound result 30\n  Bound result 1\n  Bound result 14299\n  Bound result 8891\n  Bound result 37\n  Bound result 1860\n  Bound result 3031\n  Bound result 2\n  Bound result 1789\n  Bound result 1\n  Bound result 1552500370490921697168\n  Bound result 45866\n  Bound result 11\n  Bound result 100\n  Bound result 1\n  Bound result 2\n  Bound result 1515528835\n  Bound result 10001\n  Bound result 6\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 31396\n  Bound result 56\n  Bound result 0\n  Bound result 242\n  Bound result 11610\n  Bound result 23\n  Bound result 1357\n  Bound result 1\n  Bound result 1114\n  Bound result 49993\n  Bound result 64\n  Bound result 1\n  Bound result 25\n  Bound result 1\n  Bound result 2000000000000000000\n  Bound result 1097\n  Bound result 84\n  Bound result 0\n  Bound result 3567\n  Bound result 1\n  Bound result 9921\n  Bound result 0\n  Bound result 2\n  Bound result 1172\n  Bound result 2\n  Bound result 2048\n  Bound result 54889\n  Bound result 1\n  Bound result 1\n  Bound result 428461891782872549115\n  Bound result 0\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 460.98ms (430.52ms CPU time)\n\nRan 1 test for test/TreasuryInvariant.t.sol:TreasuryInvariantTest\n[PASS]\nTreasuryInvariantTest invariants:\n[PASS] invariant_balanceIsGiftsMinusDrips\n[PASS] invariant_dripNeverExceedsTwoPercent\n[PASS] invariant_holdsNoEth\n[PASS] invariant_hookHoldsExactlyTheDrips\n[PASS] invariant_hookIsPinned\n[PASS] invariant_lastDripDayMatchesTheLastSuccessfulDrip\n TreasuryInvariantTest invariants (runs: 256, calls: 12288, reverts: 0)\n\n╭-----------------+-----------+-------+---------+----------╮\n| Contract        | Selector  | Calls | Reverts | Discards |\n+==========================================================+\n| TreasuryHandler | advance   | 2506  | 0       | 0        |\n|-----------------+-----------+-------+---------+----------|\n| TreasuryHandler | drip      | 2483  | 0       | 0        |\n|-----------------+-----------+-------+---------+----------|\n| TreasuryHandler | gift      | 2471  | 0       | 0        |\n|-----------------+-----------+-------+---------+----------|\n| TreasuryHandler | initAgain | 2392  | 0       | 0        |\n|-----------------+-----------+-------+---------+----------|\n| TreasuryHandler | sendEth   | 2436  | 0       | 0        |\n╰-----------------+-----------+-------+---------+----------╯\n\nLogs:\n  Bound result 1666\n  Bound result 906\n  Bound result 3715\n  Bound result 161\n  Bound result 6141\n  Bound result 13\n  Bound result 6530\n  Bound result 16939\n  Bound result 988721907082770934\n  Bound result 7238\n  Bound result 255\n  Bound result 2827\n  Bound result 2\n  Bound result 162285\n  Bound result 3869\n  Bound result 4600\n  Bound result 7000\n  Bound result 5058\n  Bound result 2142152642777907\n  Bound result 2299\n  Bound result 6138\n  Bound result 6931\n  Bound result 2125\n  Bound result 16384\n  Bound result 18\n  Bound result 26\n  Bound result 214912\n  Bound result 250000000000000000\n  Bound result 1928028032\n  Bound result 1461501637330902918203684832716283019655932542972\n  Bound result 54772\n  Bound result 42958401350560071\n  Bound result 922\n  Bound result 123884292579666271830\n  Bound result 207369\n  Bound result 1725540769\n  Bound result 4485075077090550908\n  Bound result 1100000000000000000\n  Bound result 1734\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.02s (1.02s CPU time)\n\nRan 13 test suites in 1.02s (1.93s CPU time): 132 tests passed, 0 failed, 1 skipped (133 total tests)\n","passed":true},{"durationMs":84,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"Marginalia.approve(address,uint256)\",\"Marginalia.transfer(address,uint256)\",\"Marginalia.transferFrom(address,address,uint256)\",\"MarginaliaHook.afterSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),int256,bytes)\",\"MarginaliaHook.beforeInitialize(address,(address,address,uint24,int24,address),uint160)\",\"MarginaliaHook.beforeSwap(address,(address,address,uint24,int24,address),(bool,int256,uint160),bytes)\",\"MarginaliaHook.claimDeposit(bytes32,bool)\",\"MarginaliaHook.claimLeaderboard(uint32)\",\"MarginaliaHook.claimRefund(bytes32)\",\"MarginaliaHook.drawForJudging(uint32,uint256,bool)\",\"MarginaliaHook.fundPot(uint256)\",\"MarginaliaHook.observe(bytes32)\",\"MarginaliaHook.payJudged(uint32,bytes32[3])\",\"MarginaliaHook.retract(bytes32,string)\",\"MarginaliaHook.sellPotMarg(uint256)\",\"MarginaliaHook.settle(bytes32)\",\"MarginaliaHook.settleThesis(bytes32)\",\"MarginaliaHook.sweep(uint8,uint32)\",\"MarginaliaHook.unlockCallback(bytes)\",\"MarginaliaJudge.convertForfeits()\",\"MarginaliaJudge.init(address,address,bytes32,address)\",\"MarginaliaJudge.onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"MarginaliaJudge.payJudged(uint32)\",\"MarginaliaJudge.requestJudging(uint32)\",\"MarginaliaRouter.checkpointVenue((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address))\",\"MarginaliaRouter.init(address,address)\",\"MarginaliaRouter.note((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address),uint256,uint256,uint256)\",\"MarginaliaRouter.sellWithNote((address,(uint8,bytes32,address,bool),uint8,uint32,uint16,bytes32,uint8,string),(address,address,uint24,int24,address),uint256,uint256,uint256)\",\"MarginaliaRouter.uniswapV3SwapCallback(int256,int256,bytes)\",\"MarginaliaRouter.unlockCallback(bytes)\",\"MarginaliaTreasury.drip()\",\"MarginaliaTreasury.init(address)\"],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":141,\"README.md\":123,\"SPEC.md\":263,\"dependencies.json\":28,\"foundry.toml\":21,\"helper/.gitignore\":3,\"helper/package-lock.json\":737,\"helper/package.json\":20,\"helper/public/index.html\":82,\"helper/server.js\":90,\"helper/src/app.js\":203,\"jobs/launch-1-hook.json\":43,\"jobs/launch-2-contracts.json\":38,\"jobs/launch-A-implementations.json\":47,\"jobs/launch-A2-implementations.json\":41,\"jobs/launch-hook-v3.json\":43,\"remappings.txt\":4,\"src/HookFlags.sol\":33,\"src/Marginalia.sol\":12,\"src/MarginaliaHook.sol\":863,\"src/MarginaliaImpls.sol\":14,\"src/MarginaliaJudge.sol\":259,\"src/MarginaliaPricer.sol\":292,\"src/MarginaliaRouter.sol\":444,\"src/MarginaliaTreasury.sol\":53,\"src/MarginaliaTypes.sol\":108,\"src/OracleAttestation.sol\":221,\"src/interfaces/IIntake.sol\":15,\"src/interfaces/ILaunchFactory.sol\":49,\"test/AuditFindings.t.sol\":178,\"test/CompanionFailures.t.sol\":833,\"test/Implementations.t.sol\":96,\"test/JudgeOracle.t.sol\":270,\"test/Lifecycle.t.sol\":502,\"test/PriceHistory.t.sol\":233,\"test/Pricer.t.sol\":88,\"test/PricerProperties.t.sol\":424,\"test/RouterInvariant.t.sol\":248,\"test/TreasuryInvariant.t.sol\":167,\"test/fork/MainnetLaunch.t.sol\":382,\"test/helpers/Fixture.sol\":278,\"test/mocks/MockERC20.sol\":13},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"ce115551bba054a361ea3a3beac7718db0c2443e4ff37553a6621b38474eb997","verifiedTreeHash":"8c20ac4b35027dcbca430d52362cb46985430cf9","verifierVersion":"0.1.0+fdeb4d4a"}]}