{"assessments":[],"deployments":[],"fuzz":[],"identity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"interpretation":"Records acceptance and evidence. Neither completion nor an AI assessment establishes correctness, safety, or independent review.","jobId":"9cd98310-b905-4697-b7c3-a653ac25836c","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"e229981aa30bfa372196c1a66e936dbf4f107c17150803cf361fa9b572ab8969","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":null,"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":"working"},{"acceptedSubmissionHash":null,"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":"working"},{"acceptedSubmissionHash":"524f08d73dc9d64a701f8fc7aeac9c3eb295c1434dda9590fd83ace712861378","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":null,"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":"waiting"},{"acceptedSubmissionHash":null,"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":"working"},{"acceptedSubmissionHash":null,"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":"working"},{"acceptedSubmissionHash":null,"dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"failed"},{"acceptedSubmissionHash":null,"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":"working"}],"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). (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, 142 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":"67d0f68375221f0a5d45e65b000d360a092c237bb344ec3abc4c67c6f7d2c5f8","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"9cd98310-b905-4697-b7c3-a653ac25836c","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-1381-larpburner-larp-imdnames-larplinks"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"52250","feedbackHash":"a3662ad715baaacc93977f83b9447ec7289f753fe87e767116bb74699825dd7d","nodeKey":"adapt_contract_project","submissionHash":"e229981aa30bfa372196c1a66e936dbf4f107c17150803cf361fa9b572ab8969","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51494","feedbackHash":"76961abbfc7afbc1707d4911cd868f828c95bca10a7053de698b24e29ac7c90a","nodeKey":"audit_imported_code","submissionHash":"524f08d73dc9d64a701f8fc7aeac9c3eb295c1434dda9590fd83ace712861378","tag1":"review:submission","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"a04d0c2f7652b9f4254f4db7ef2761e580d2faf239302629d464a2817e3d7541","state":"blocked","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"3a40eaafbd83a6bc","findings":[{"citation":"resolved","description":"AUDIT.md L-01 says a route that fails with no more than 1/63 of its gas left reverts the call, so a caller cannot skip POOL4 (or the IMD6900 buy) by starving the swap. The check only holds when the frame that runs out of gas is the one the try calls (test_ASwapOutOfGasReverts uses a PoolManager whose unlock itself loops). In the real path the out-of-gas happens in PoolManager.swap or in the pool's hook, three or four frames below the burner's try: every intermediate frame keeps 1/64 of its own gas and hands it back when it reverts, so after a failure d frames deep roughly d/64 of gasBefore is left, which is above gasBefore/63 for any d >= 2. The route is then treated as a normal failure: the ETH falls to the next route or parks, and in _burnImd the 6.9% IMD6900 buy is skipped and sent to DEAD as $IMD. Exploitability today depends on how much gas the POOL4 hook and the pair hook consume (the remainder after a deep failure is about 6% of the gas given), so the impact is a weakened guarantee rather than a loss. Fix: treat a failure as out-of-gas when gasleft() is below a larger fraction (for example gasBefore / 8, well above any real revert's leftover), or give the unlock an explicit gas stipend and require that stipend to be available before trying the route.","line":234,"path":"src/LARPBurner.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {LARPBurner, PoolKey, SwapParams} from \"src/LARPBurner.sol\";\n\n/// @dev A PoolManager that calls the burner back (as the real one does) and whose swap burns all the gas it is given,\n/// as a heavy hook would: the out-of-gas happens two calls below the burner's try, not one.\ncontract NestedHogPoolManager {\n    uint256 public swaps;\n\n    function unlock(bytes calldata data) external returns (bytes memory) {\n        return LARPBurner(payable(msg.sender)).unlockCallback(data);\n    }\n\n    function swap(PoolKey memory, SwapParams memory, bytes calldata) external returns (int256) {\n        while (true) {}\n        return 0;\n    }\n}\n\ncontract NestedGasTest is Test {\n    event Parked(uint256 eth);\n\n    function test_ANestedOutOfGasIsNotCaught() public {\n        NestedHogPoolManager pm = new NestedHogPoolManager();\n        LARPBurner burner = new LARPBurner(\n            address(pm), address(0x1111), 10_000, 60, address(0), 10_000, 200, address(0x6900), 0, 60, address(0)\n        );\n        vm.deal(address(this), 1 ether);\n        // The same probe as test_ASwapOutOfGasReverts, one level deeper: the fix expects TooLittleGas.\n        (bool ok, bytes memory err) =\n            address(burner).call{value: 0.05 ether, gas: 3_000_000}(abi.encodeCall(burner.burn, (0)));\n        emit log_named_bytes(\"error\", err);\n        emit log_named_uint(\"burner balance (parked)\", address(burner).balance);\n        assertFalse(ok, \"a swap that ran out of gas should revert the burn (TooLittleGas), not park the ETH\");\n        assertEq(bytes4(err), LARPBurner.TooLittleGas.selector);\n    }\n}","reproduction":"State: a PoolManager that calls msg.sender.unlockCallback(data) in unlock (as the real one does) and whose swap burns all the gas it is given. Call: burner.burn{value: 0.05 ether, gas: 3_000_000}(0). Expected (per L-01 and test_ASwapOutOfGasReverts): revert TooLittleGas. Actual: the call succeeds, both routes are reported failed, Parked(0.05 ether) is emitted and burn returns 0. Trace: route 0 consumed 2,860,440 gas and left about 140k (> 3,000,000/63 = 47.6k), route 1 consumed 131k and left about 6k (> 131k/63 = 2k). The attached test fails on this code and passes once a failure that ate the gas is reverted.","severity":"low","snippet":"            if (gasleft() <= gasBefore / 63) revert TooLittleGas();","title":"L-01 fix is depth-1 only: an out-of-gas two or more frames below the try is not detected, so a swap that runs out of gas still skips its route"},{"citation":"resolved","description":"propose accepts next == prices (_checkStep allows to == from, test_TheOracleMustBePaid relies on it) and the swarm will approve it, since the current prices meet the guidelines by construction. execute of that no-op bumps epoch and sets lastChange, so every other approved proposal in the old epoch reverts Stale and nothing can execute for COOLDOWN (7 days). An attacker who wants the ETH prices to stay where they are (for example while ETH/USD moves so that names drift outside the $1-5 guideline) repeats this weekly: propose the current prices (0.5 IMD), get the verdict, and win the execute race at the cooldown's expiry with a higher priority fee. Honest proposers pay the same 0.5 IMD per attempt and never land. Fix: refuse next == prices in propose, do not bump epoch or lastChange when prices did not change, or let execute accept a proposal whose next still passes _checkStep against the current prices instead of requiring epoch equality.","line":201,"path":"src/SwarmPrices.sol","reproduction":"1. Alice: propose({0.005,0.0012,0.0005,0.0005}, 0.5e18) -> id A; intake delivers an approving verdict -> Approved. 2. Mallory: propose({0.0069,0.00169,0.00069,0.00069} (the current prices), 0.5e18) -> id B; verdict approving -> Approved. 3. Mallory: execute(B): succeeds, epoch 0 -> 1, lastChange = now, prices unchanged. 4. Anyone: execute(A) -> reverts Stale (expected: A, a swarm-approved change, applies). Re-proposing A and getting it approved gives an id C that reverts Cooling until lastChange + 7 days; Mallory repeats steps 2-3 at that instant. Expected: a proposal that changes nothing cannot void an approved change; actual: it does, at 0.5 IMD per week.","severity":"low","snippet":"        if (p.epoch != epoch) revert Stale();","title":"Any approved proposal, including one that changes nothing, resets the cooldown and stales every other approved proposal: price governance can be frozen for 0.5 IMD a week"},{"citation":"resolved","description":"The oracle-consumer reference requires the intake, action id, asset/price and signer to be constructor inputs and settable, never constants, so that a new action version (oracle-2), a moved Intake or a rotated signer does not need a redeploy. SwarmPrices hardcodes ACTION and makes INTAKE and ORACLE_SIGNER immutable, and the protocol has no owner by design. The fee being a call argument covers only a price move. AUDIT.md accepts 'if IMD stops answering, prices stay' but the consequence is stronger: once the Intake stops selling oracle-1 (ActionNotSold) every propose reverts for everyone, and once the signer key rotates every verdict reverts BadVerdictSignature, leaving proposals Pending forever with their 0.5 IMD spent. Names and crews then stay priced in ETH at the last values while ETH/USD moves, so the $1-5 guideline the swarm enforces can no longer be met. Without adding an owner, the swarm's own verdict mechanism could ratify a new (intake, action, signer) triple the same way it ratifies prices; or the adapter should state the freeze as an accepted outcome in the launch notes.","line":81,"path":"src/SwarmPrices.sol","reproduction":"State: IMD's Intake at 0xa43e... no longer sells bytes32('oracle.request@oracle-1') (or the signer is no longer 0x5598...). Call: propose(validNext, 0.5e18) -> reverts inside Intake.requestWithFailure (ActionNotSold); or, with a rotated key, the Intake's callback onVerdict(id, a, sig) reverts BadVerdictSignature and the Intake records the delivery as failed, not retried. Expected (per the oracle reference): a settable intake/action/signer; actual: no function on IMDNames can change any of them, prices stay fixed forever.","severity":"low","snippet":"    bytes32 public constant ACTION = bytes32(\"oracle.request@oracle-1\");","title":"Price governance has no path for a new Intake, action id or oracle signer: when IMD retires oracle-1, Intake v2 or rotates the signer key, prices are frozen forever"},{"citation":"resolved","description":"royaltyInfo names LARPBurner as the royalty receiver for every sale. Marketplaces pay the royalty in the sale currency; accepted offers (OpenSea, Blur bids) settle in WETH, so a 6.9% WETH royalty lands in the burner. The burner handles only native ETH (burn) and $IMD (burnImd/_imdHeld); it has no function that reads, swaps or unwraps any other token, so that value is stranded rather than burned, contradicting 'every fee burns'. Fix: a permissionless path that unwraps a WETH balance to ETH (WETH is immutable and well known on Ethereum) before burn runs, or document that only ETH-settled sales burn their royalty.","line":294,"path":"src/IMDNames.sol","reproduction":"State: name X owned by Alice; a WETH bid of 1 WETH accepted on a royalty-honouring market. The market transfers 0.069 WETH to BURNER. Then: burner.burn(0) spends only address(this).balance (ETH) and burnImd reads only IMD.balanceOf(burner). Expected: the 0.069 ETH-equivalent is burned; actual: WETH.balanceOf(BURNER) == 0.069e18 forever, no function can move it. Any ERC-20 sent to the burner behaves the same.","severity":"low","snippet":"        return (BURNER, salePrice * ROYALTY_BPS / 10_000);","title":"Royalties paid in an ERC-20 (WETH offers on marketplaces) are sent to the burner and can never be burned or moved"},{"citation":"resolved","description":"bytes4(keccak256('onVerdict(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)')) is 0x8bf09c1b; 0x510379c7 is the selector of the reference example's onOracleResult with the same parameters. Because propose passes this.onVerdict.selector in the Callback struct, the Intake calls the right function; only the document is wrong. The struct shape is correct: the protocol vector's signature verifies (I deployed IMDNames at 0x2748 on chain 11155111 with the vector signer and delivered the vector attestation with VECTOR_SIGNATURE: accepted, status Rejected because its answer type is a list; a bool true signed by the vector key: Approved). The repository has no such conformance test; its tests sign with their own key only, which the oracle reference warns proves nothing about the protocol's digest. Adding the vector test is recommended.","line":120,"path":"AUDIT.md","reproduction":"forge: assertEq(IMDNames.onVerdict.selector, bytes4(0x510379c7)) fails with 0x8bf09c1b != 0x510379c7; cast sig 'onOracleResult(bytes32,(bytes32,uint256,bytes32,uint8,bytes,uint256,uint64,uint64,bytes32,bytes32,uint16,uint16,uint16,uint64,uint64),bytes)' = 0x510379c7.","severity":"info","snippet":"    selector `0x510379c7` matches IMD's docs.","title":"AUDIT.md cites the wrong callback selector: 0x510379c7 is the reference's onOracleResult, onVerdict's is 0x8bf09c1b (harmless: the selector is passed at request time)"},{"citation":"resolved","description":"Contracts read in full: src/LARPBurner.sol, src/LARP.sol (+ILARP.sol), src/IMDNames.sol (+IIMDNames.sol) with src/SwarmPrices.sol, src/LARPLinks.sol, src/Labels.sol, src/SafeReads.sol; AUDIT.md, README.md, test/Base.sol, test/Mocks.sol, test/SwarmPrices.t.sol, test/LARPBurner.t.sol, test/Launch.t.sol; vendored solady ERC721/Base64 and v4-core FullMath only as used. Baseline: forge test --offline: 140 passed, 11 fork tests skipped (no network). Not reachable (offline): the live PoolManager 0x0000...4444, $IMD 0xD34a..., POOL4 hook 0xc6C9..., IMD6900 0x0000198C... and its pair hook 0x667f..., IMD's launcher 0xfF03... and its distributors, the Intake 0xa43e... and identity.md 0x0000eC93...; their ABIs (distributorOf(uint64)=0x6c637492, roundOf(uint256)=0xc7c38091, claimed(uint256,address)=0x120aa877, token()=0xfc0c546a, burn(uint256), requestWithFailure) were checked as selectors only; the fork tests that exercise them did not run here. Launch constraints re-checked locally: constructors store only (test_DeploysOnAFreshChain), opcode scan clean (test_PassesTheAdmissionScan), one transaction (test_FitsOneTransaction). Constructor arguments in the brief match README/Launch.t.sol: Intake is version 2 (requestWithFailure), signer and action id match the oracle reference. Oracle conformance: I ran the reference's protocol vector (chain 11155111, consumer 0x2748, VECTOR_DIGEST/VECTOR_SIGNATURE) against IMDNames.onVerdict: the protocol's signature verifies and a fresh bool-true signed by the vector key approves (no finding; the repo lacks this test, see info).\n\nEntry points, all 138 answered (verdict in brackets):\nConstructors: LARPBurner [stores immutables, zero checks, no calls], LARP [stores IDENTITY], IMDNames [stores, SwarmPrices bounds check pure, artist may be 0 by design], LARPLinks [stores, zero checks].\nLARPBurner: receive [accepts ETH, ok]; 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 [immutable/constant getters, ok]; burn [tload lock, MAX_BURN cap, route fallthrough, minImd; finding: nested OOG evades TooLittleGas (low)]; burnImd [locked, ok]; quoteImd [slot math matches v4 StateLibrary (pools slot 6, liquidity +3), max of two spots, reverts without both; spot manipulation acknowledged L-07, cost check holds at stated depth]; unlockCallback [only PoolManager, exact-fill checks on both legs, sync/settle/take order correct, IMD6900 burn atomic with the swap].\nLARP: IDENTITY, SLOTS, DOMAIN_SEPARATOR, nonces [ok]; setAgent [owner only, bumps nonce]; setAgentBySig [deadline, live holder, nonce, low-s, 1271 fallback; replay impossible]; resignAgent [agent only]; agentOf, identityOfAgent, canAct [liveness bound to holder]; setFace, equip [canAct, NotAMask, ownership/copies checks, two-way _placed kept]; clearFace, unequip [placer or controller]; faceOf, itemOf, wearerOf, faceURI, avatarOf, itemURI [staticcall reads, gas forwarded as documented I-07]; supportsInterface [ok].\nIMDNames: 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 [getters, ok]; propose [bounds+step, pulls fee from caller, approves intake, body valid JSON within limits; finding: identical-price proposals allowed, see low]; onVerdict [intake only, own pending id only, protocol digest verified against the reference vector, panel/quorum/expiry checks; fits 200k gas]; onNoVerdict [intake only, closes]; execute [approved, window, epoch, cooldown; finding: cooldown/epoch reset griefing (low)]; artist, renderer, rendererLocked [ok]; priceOf [BadName on invalid], crewPrice, tollOf [ok]; register [price exact, _mint before burn, no receiver hook]; registerWithImd [quote then transferFrom to burner then burnImd]; link [toll exact, state before burn]; linkWithImd [same]; unlink [controller or owner]; setPrimary [owner ","line":3,"path":"AUDIT.md","reproduction":"Not a defect. Commands run: forge test --offline (140 passed, 11 skipped fork tests); forge test --match-path test/scratch/Conformance.t.sol (protocol vector accepted); forge test --match-path test/scratch/NestedGas.t.sol (fails on this code: see the low finding on LARPBurner.sol:234).","severity":"info","snippet":"Scope: `src/` at this commit: `LARPBurner`, `LARP` / `ILARP`, `IMDNames` / `IIMDNames` with `SwarmPrices`,","title":"Scope, reachability and entry-point coverage of this review"}],"hash":"524f08d73dc9d64a701f8fc7aeac9c3eb295c1434dda9590fd83ace712861378","nodeId":"514e118c-ffb4-46f3-98e1-ffe0c8f933af","outcome":"completed","summary":"Review complete. No tracked file was changed; the output is `.imd-findings.json` (6 entries) plus the two scratch tests under `test/scratch/`.\n\n**Result: no critical, high or medium defects.** The baseline suite passes offline (140 tests, 11 fork tests skipped), the launch constraints hold, and the constructor arguments in the brief match the repository. The oracle integration is sound: I ran the protocol's own attestation vector from the oracle reference against `IMDNames.onVerdict` and the protocol's signature verifies, so struct, type string and domain match what the oracle signs. The repository itself lacks that test; its tests only self-sign.\n\n**Findings recorded**\n\n- **Low, with proof.** The L-01 gas fix in `LARPBurner._tryUnlock` only catches an out-of-gas in the frame the try calls. The real failure sits three or four frames deep, and each intermediate frame returns its reserved 1/64, leaving far more than 1/63. A PoolManager whose swap burns all gas makes `burn` succeed and park the ETH where `TooLittleGas` is expected. The scratch test fails on the current code.\n- **Low.** A proposal with unchanged prices passes the guardrails and the swarm approves it. Executing it bumps the epoch and resets the 7 day cooldown, staling every other approved proposal. Governance can be frozen for 0.5 IMD a week.\n- **Low.** The action id is a constant and the Intake and signer are immutable with no owner. The oracle reference requires these to be changeable. If IMD retires oracle-1, Intake v2 or rotates the signer, prices freeze forever.\n- **Low.** Royalties paid in WETH or any ERC-20 land in the burner, which can only burn ETH and $IMD. That value is stranded.\n- **Info.** AUDIT.md cites callback selector 0x510379c7, which is the reference example's `onOracleResult`. `onVerdict` is 0x8bf09c1b. Harmless, since the selector is passed at request time.\n- **Info.** Scope and coverage: all 138 entry points answered, per contract, with the list of contracts read and the live mainnet contracts that could not be reached offline (PoolManager, $IMD, both hooks, IMD6900, launcher and distributors, Intake, identity.md), whose ABIs were checked as selectors only.\n\nAcknowledged items in AUDIT.md were re-checked and hold at the stated pool depths, including the spot-price quote for $IMD payments and the two-way name link bookkeeping across sales.","treeHash":null,"usage":{"cachedInputTokens":2077102,"inputTokens":450,"model":"claude-fable-5-1","outputTokens":56789,"runtime":"claude","turns":32,"wallClockMs":1154086}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"759c614fdc84ff66","findings":[],"hash":"9223163c87d8f9c633f581f2e27999573877791db38481230a94236839e737a9","nodeId":"697c166b-2f5e-429f-9f39-21e4ac61f31d","outcome":"failed","summary":"needs input: The accepted LARPBurner constructor takes three int24 tick-spacing arguments (pool4Spacing, backupSpacing, pairSpacing at positions 3, 6 and 9). The evm_contracts manifest refuses signed-integer constructor types ('unsupported constructor type int24 at 3'), so no launch.json can deploy the contract as it stands. Fixing it needs a source change to LARPBurner, which this manifest-only task may not make. — May a builder change LARPBurner's constructor so the three tick spacings are passed as uint24 (or as other unsigned types) and cast to int24 inside the constructor, keeping the same values (60, 200, 60), argument order and public int24 getters? Or would you rather hard-code the spacings as constants and drop those three arguments?","treeHash":null,"usage":{"cachedInputTokens":320869,"inputTokens":22,"model":"claude-opus-5-5","outputTokens":5878,"runtime":"claude","turns":12,"wallClockMs":457676}},{"artifacts":[],"attempt":1,"bundleHash":"de989e1993eb0d8555fa25ab7697351b171dea16b8b9d47ee78320e51d9bccf8","device":"fc87c05048aca47d","findings":[],"hash":"e229981aa30bfa372196c1a66e936dbf4f107c17150803cf361fa9b572ab8969","nodeId":"a1aff12d-cf62-42f4-afa3-d1b7dd5307d8","outcome":"completed","summary":"Done. The project arrived already launch-ready, so no launch rule forced a change; the work was reproducing and fixing the imported audit.\n\n**What I verified first**\n- Build and the 140 offline tests passed on arrival. Constructors call nothing, the opcode scan is clean, four creations fit one transaction, all sizes are under EIP-170.\n- The brief's launch order and constructor arguments match README and `test/Launch.t.sol`. The artist is the launch owner's static address. Interfaces, constructor arguments and the 138 entry points are untouched.\n\n**Audit findings that reproduced, now fixed and tested**\n- **Nested out-of-gas (L-01 depth-1).** The supplied proof failed on the arriving code. `_tryUnlock` in `src/LARPBurner.sol` now treats a failure that leaves no more than a quarter of the gas as out-of-gas, which covers 16 frames of depth instead of one. Test: `test_ANestedSwapOutOfGasReverts`, plus the proof itself passes.\n- **No-op proposal griefing.** Proposing the current prices, approving and executing did stale a waiting approved change. `propose` now refuses an unchanged price set with `NoChange` before any payment. One existing test that relied on a no-op proposal was moved to a real change. Tests: `test_AProposalMustChangeAPrice`, `test_AnApprovedChangeCantBeStaledByANoOp`.\n- **Stranded WETH royalties.** `burn` now unwraps any WETH9 the burner holds, best effort, with no call at deployment and no new entry point. Three tests cover unwrap, the per-call cap, and a refusing WETH.\n- **Wrong selector in AUDIT.md.** Corrected to 0x8bf09c1b in AUDIT.md and the source comment, and the protocol's oracle conformance vector was added as `test/OracleConformance.t.sol`: IMDNames accepts the protocol's real signature and approves a fresh true from the vector key.\n\n**Not changed, stated in ADAPTATION.md and AUDIT.md**\n- No rotation path for the Intake, action id or signer: the brief keeps no owner and fixed interfaces, so the freeze is recorded as an accepted outcome.\n- A one-wei \"change\" can still reset the cooldown; that is inherent to one change a week with open execution, and only works while current prices still meet the guidelines.\n\n**Final state**\n\n| check | result |\n|---|---|\n| forge build --offline | clean |\n| forge test --offline | 149 passed, 0 failed, 11 fork tests skipped |\n\nChanged files: `src/LARPBurner.sol`, `src/SwarmPrices.sol`, `test/LARPBurner.t.sol`, `test/SwarmPrices.t.sol`, new `test/OracleConformance.t.sol`, `AUDIT.md`, `README.md`, new `ADAPTATION.md`. No launch.json was written, nothing was installed, and the working tree is left uncommitted for the submission step.","treeHash":"da1ed514f07eb5d865614c5d108667d8e465c3be","usage":{"cachedInputTokens":4285893,"inputTokens":1058,"model":"claude-fable-5-1","outputTokens":40960,"runtime":"claude","turns":49,"wallClockMs":1057664}}],"verification":[{"checks":[{"durationMs":60947,"exitCode":0,"name":"build","output":"Compiling 93 files with Solc 0.8.26\nSolc 0.8.26 finished in 60.78s\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/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[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/SwarmPrices.sol:82:38\n   │\n82 │     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[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[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[boolean-cst]: misuse of a boolean constant\n    ╭▸ src/LARPBurner.sol:243:21\n    │\n243 │             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:246:21\n    │\n246 │             return (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[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/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/LARPBurner.sol:107:9\n    │\n107 │         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:101:9\n    │\n101 │         address pool4Hook,\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[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/SwarmPrices.sol:174:9\n    │\n174 │         emit Proposed(requestId, number, msg.sender, next);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[calls-loop]: external call inside a loop\n    ╭▸ src/LARPBurner.sol:242:13\n    │\n242 │         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:157:21\n    │\n157 │                     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:161:27\n    │\n161 │             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:231:9\n    │\n231 │         emit Burned(rest, share, burned6900);\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:109:9\n    │\n109 │         LARPBurner(payable(BURNER)).burn{value: price}(minImd);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/LARPBurner.sol:245:55\n    │\n245 │             if (gasleft() <= gasBefore / OOG_DIVISOR) 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: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/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/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[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[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[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/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: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:193:43\n    │\n193 │                 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:196:27\n    │\n196 │                 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:196:49\n    │\n196 │                 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:196:67\n    │\n196 │                 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:196:82\n    │\n196 │                 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:197:30\n    │\n197 │             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[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[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[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/LARPBurner.sol:197:37\n    │\n197 │             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:200:13\n    │\n200 │             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:201:27\n    │\n201 │             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/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:209:61\n    │\n209 │         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:210:27\n    │\n210 │         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:211:25\n    │\n211 │         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:212:26\n    │\n212 │         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:212:33\n    │\n212 │         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:213:9\n    │\n213 │         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:214:47\n    │\n214 │         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:215:27\n    │\n215 │         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:215:35\n    │\n215 │         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:231:34\n    │\n231 │         emit Burned(rest, share, burned6900);\n    │                                  ━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/SwarmPrices.sol:187:16\n    │\n187 │             && 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:190:9\n    │\n190 │         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:187:83\n    │\n187 │             && 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:189:23\n    │\n189 │         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: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:207:44\n    │\n207 │         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:209:32\n    │\n209 │         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:213:22\n    │\n213 │         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:309:36\n    │\n309 │             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:325:15\n    │\n325 │             ++digits;\n    │               ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/SwarmPrices.sol:329:36\n    │\n329 │             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":27250,"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 829.53µs (822.80µs CPU time)\n\nRan 3 tests for test/OracleConformance.t.sol:OracleConformanceTest\n[PASS] test_acceptsAFreshSignatureFromTheVectorKey() (gas: 2190922)\n[PASS] test_acceptsTheProtocolSignatureAsDelivered() (gas: 2253067)\n[PASS] test_callbackSelectorIsCanonical() (gas: 4107)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 5.62ms (1.61ms CPU time)\n\nRan 24 tests for test/LARP.t.sol:LARPFaceTest\n[PASS] testFuzz_OnlyTheHolderOfBothSetsAFace(address,uint256,uint256) (runs: 256, μ: 55821, ~: 56413)\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 6.64ms (10.29ms 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: 955418)\n[PASS] test_Card() (gas: 1629478)\n[PASS] test_CrewFoundingRules() (gas: 909037)\n[PASS] test_Disband() (gas: 1536439)\n[PASS] test_FoundACrewWithImd() (gas: 1176613)\n[PASS] test_FoundingACrewBurnsIMD() (gas: 741665)\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: 1681391)\n[PASS] test_PassTheCaptaincy() (gas: 940496)\n[PASS] test_ProveAnAllocation() (gas: 1534389)\n[PASS] test_RanksAcrossLaunches() (gas: 5184173)\n[PASS] test_TheCaptaincyPassesWithTheIdentity() (gas: 760414)\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 8.41ms (21.22ms 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: 977882)\n[PASS] test_AnAgentResigns() (gas: 193582)\n[PASS] test_AnAgentRunsFrensAndCrews() (gas: 1223086)\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.48ms (6.03ms CPU time)\n\nRan 28 tests for test/IMDNames.t.sol:IMDNamesTest\n[PASS] test_ABrokenRendererFallsBackToTheCard() (gas: 10710728)\n[PASS] test_AFeeParksWhenNoPoolCanTakeIt() (gas: 8868921)\n[PASS] test_ANewOwnerPaysTheTollToLink() (gas: 1022372)\n[PASS] test_ARoyaltyPaymentIsBurned() (gas: 537465)\n[PASS] test_AnyoneRegistersAnyFreeName() (gas: 614240)\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: 929703)\n[PASS] test_Prices() (gas: 63586)\n[PASS] test_Primary() (gas: 249650)\n[PASS] test_RegisterForSomeoneElse() (gas: 605215)\n[PASS] test_RegisterWithImd() (gas: 955032)\n[PASS] test_RegisterWithImdRespectsMaxImd() (gas: 784770)\n[PASS] test_RegisteringMintsTheNameAndBurnsTheFee() (gas: 650026)\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: 653230)\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: 1089241)\n[PASS] test_Unlink() (gas: 207574)\nSuite result: ok. 28 passed; 0 failed; 0 skipped; finished in 21.00ms (35.59ms CPU time)\n\nRan 17 tests for test/SwarmPrices.t.sol:SwarmPricesTest\n[PASS] test_AProposalForOldPricesGoesStale() (gas: 3674220)\n[PASS] test_AProposalMustChangeAPrice() (gas: 2199983)\n[PASS] test_ARejectedProposalChangesNothing() (gas: 2232965)\n[PASS] test_AVerdictMustBeUsedWithinTwoWeeks() (gas: 2209636)\n[PASS] test_AWeakPanelIsARejection() (gas: 6238058)\n[PASS] test_AnApprovedChangeCantBeStaledByANoOp() (gas: 2279207)\n[PASS] test_AnExpiredVerdictIsARejection() (gas: 2192812)\n[PASS] test_AnyoneProposesAndTheContractWritesTheQuestion() (gas: 2851091)\n[PASS] test_ApprovedThenAnyoneExecutes() (gas: 3555871)\n[PASS] test_ExecutedOnce() (gas: 2253590)\n[PASS] test_Guardrails() (gas: 210912)\n[PASS] test_NoVerdictClosesTheProposal() (gas: 2225495)\n[PASS] test_OneChangeAWeek() (gas: 3736376)\n[PASS] test_OnlyTheIntakeDeliversAndOnlyForItsOwnProposals() (gas: 2219400)\n[PASS] test_OnlyTheOraclesSignatureForThisContractCounts() (gas: 2357817)\n[PASS] test_StartPrices() (gas: 58594)\n[PASS] test_TheOracleMustBePaid() (gas: 221190)\nSuite result: ok. 17 passed; 0 failed; 0 skipped; finished in 21.62ms (22.92ms CPU time)\n\nRan 20 tests for test/LARPBurner.t.sol:LARPBurnerTest\n[PASS] test_ANestedSwapOutOfGasReverts() (gas: 3158509)\n[PASS] test_ASwapOutOfGasReverts() (gas: 3106126)\n[PASS] test_AWethThatRefusesChangesNothing() (gas: 1089220)\n[PASS] test_AnEmptyPairPoolMeansItAllBurnsAsIMD() (gas: 816882)\n[PASS] test_AnIMD6900ThatWontBurnMeansItAllBurnsAsIMD() (gas: 779316)\n[PASS] test_AtMostMaxBurnPerCall() (gas: 2230521)\n[PASS] test_BurnImdBurnsWhatArrivesInIMD() (gas: 513332)\n[PASS] test_BuysOnPool4First() (gas: 1063211)\n[PASS] test_MinImd() (gas: 954983)\n[PASS] test_NoGasLimitSkipsARoute() (gas: 15731738)\n[PASS] test_NoQuoteWithoutBothPools() (gas: 297210)\n[PASS] test_NoReentry() (gas: 464706)\n[PASS] test_OnlyThePoolManagerCallsBack() (gas: 32791)\n[PASS] test_ParkedWhenNoPoolCanAndBurnedLater() (gas: 1348299)\n[PASS] test_QuoteIsTheHigherOfTheTwoPools() (gas: 1119381)\n[PASS] test_RoyaltiesArriveByPlainTransfer() (gas: 43927)\n[PASS] test_ShareBuysIMD6900AndBurnsIt() (gas: 841522)\n[PASS] test_TheHooklessPoolIfPool4CantTakeIt() (gas: 1175117)\n[PASS] test_WethJoinsTheEthAndTheCapHolds() (gas: 1086627)\n[PASS] test_WethRoyaltiesBurnToo() (gas: 1115908)\nSuite result: ok. 20 passed; 0 failed; 0 skipped; finished in 21.64ms (58.48ms 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 21.77ms (3.92ms CPU time)\n\nRan 4 tests for test/Launch.t.sol:LaunchTest\n[PASS] test_DeploysOnAFreshChain() (gas: 190674)\n[PASS] test_FitsOneTransaction() (gas: 23313)\nLogs:\n  launch gas, four creations: 7030\n\n[PASS] test_PassesTheAdmissionScan() (gas: 17163361)\n[PASS] test_UnderTheCodeSizeLimit() (gas: 9813)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 28.55ms (29.25ms 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    | 1148  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | equip721     | 1173  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveCopy     | 1172  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveIdentity | 1175  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | giveMask     | 1188  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | setFace      | 1173  | 0       | 0        |\n|-------------+--------------+-------+---------+----------|\n| LarpHandler | takeOff      | 1163  | 0       | 0        |\n╰-------------+--------------+-------+---------+----------╯\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 27.14s (27.14s CPU time)\n\nRan 11 test suites in 27.14s (27.28s CPU time): 149 tests passed, 0 failed, 11 skipped (160 total tests)\n","passed":true},{"durationMs":67,"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\":44,\"AUDIT.md\":162,\"README.md\":181,\"foundry.toml\":30,\"src/IIMDNames.sol\":112,\"src/ILARP.sol\":120,\"src/IMDNames.sol\":358,\"src/LARP.sol\":330,\"src/LARPBurner.sol\":279,\"src/LARPLinks.sol\":457,\"src/Labels.sol\":53,\"src/SafeReads.sol\":63,\"src/SwarmPrices.sol\":338,\"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\":305,\"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/OracleConformance.t.sol\":148,\"test/SwarmPrices.t.sol\":366,\"test/fixtures/allocs.json\":118},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":4809,"exitCode":0,"name":"slither","output":"[medium/high] incorrect-equality at src/LARPBurner.sol:148: LARPBurner.burn(uint256) (src/LARPBurner.sol#148-165) uses a dangerous strict equality:\n[medium/medium] uninitialized-local at src/SwarmPrices.sol:323: SwarmPrices._decimal(uint256).digits (src/SwarmPrices.sol#323) 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:223: LARPBurner._burnImd().burned6900 (src/LARPBurner.sol#223) 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/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/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/LARPBurner.sol:184: LARPBurner.unlockCallback(bytes) (src/LARPBurner.sol#184-216) ignores return value by POOL_MANAGER.settle() (src/LARPBurner.sol#200)\n[medium/medium] unused-return at src/LARPBurner.sol:184: LARPBurner.unlockCallback(bytes) (src/LARPBurner.sol#184-216) ignores return value by POOL_MANAGER.settle{value: amount}() (src/LARPBurner.sol#213)\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/LARPBurner.sol:107: LARPBurner.constructor(address,address,uint24,int24,address,uint24,int24,address,uint24,int24,address).pairHook (src/LARPBurner.sol#107) 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:101: LARPBurner.constructor(address,address,uint24,int24,address,uint24,int24,address,uint24,int24,address).pool4Hook (src/LARPBurner.sol#101) lacks a zero-check on :\n[low/medium] calls-loop at src/LARPBurner.sol:240: LARPBurner._tryUnlock(uint8,uint256) (src/LARPBurner.sol#240-248) has external calls inside a loop: r = POOL_MANAGER.unlock(abi.encode(route,amount)) (src/LARPBurner.sol#242-247)\n[low/medium] reentrancy-benign at src/SwarmPrices.sol:148: Reentrancy in SwarmPrices.propose(SwarmPrices.Prices,uint256) (src/SwarmPrices.sol#148-175):\n[low/medium] reentrancy-events at src/LARPBurner.sol:148: Reentrancy in LARPBurner.burn(uint256) (src/LARPBurner.sol#148-165):\n[low/medium] reentrancy-events at src/LARPBurner.sol:219: Reentrancy in LARPBurner._burnImd() (src/LARPBurner.sol#219-232):\n[low/medium] reentrancy-events at src/LARPBurner.sol:148: Reentrancy in LARPBurner.burn(uint256) (src/LARPBurner.sol#148-165):\n[low/medium] reentrancy-events at src/SwarmPrices.sol:148: Reentrancy in SwarmPrices.propose(SwarmPrices.Prices,uint256) (src/SwarmPrices.sol#148-175):\n[low/medium] timestamp at src/SwarmPrices.sol:180: SwarmPrices.onVerdict(bytes32,Attestation,bytes) (src/SwarmPrices.sol#180-191) uses timestamp for comparisons\n[low/medium] timestamp at src/SwarmPrices.sol:205: SwarmPrices.execute(bytes32) (src/SwarmPrices.sol#205-215) 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","passed":true},{"durationMs":498,"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 (56 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:153: 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:200: Unchecked Return\n[low] uninitialized-local-variable at src/LARPBurner.sol:153: 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":"e229981aa30bfa372196c1a66e936dbf4f107c17150803cf361fa9b572ab8969","verifiedTreeHash":"da1ed514f07eb5d865614c5d108667d8e465c3be","verifierVersion":"0.1.0+fb8278c5"}]}