{"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":"719b9f22-aa3f-4b45-8b97-b8b644c033f9","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"5a36d26de9c5159852e641cad36decca76837986e2fd928d1792599864dec781","dependsOn":["audit_imported_code"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"a2cea02e8b33e91eeb784e0e5eaeb571cd62cd69e768d335d5834e24b3aa46e5","skillId":"adapt-contract-project","tools":[]},"key":"adapt_contract_project","kind":"code","role":"implement","skillHash":"a2cea02e8b33e91eeb784e0e5eaeb571cd62cd69e768d335d5834e24b3aa46e5","skillId":"adapt-contract-project","state":"accepted"},{"acceptedSubmissionHash":"e97c9f263653323283f0582a048b90e1a999b3037718b2cc4c750e7e3ddb4a69","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":"830efe378cc4dfd59ed05fea435b71a742b583abc1e64f90cd95aa01e930dec0","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":"a78e1bb3c947da525bea19fb80a7714d7a75cbf39ae5ae3cd412c8a9af71c340","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":"a947978c46f145effccf2bfb88353011a83ef752b2b326f8ba683e79108ad15a","dependsOn":["adapt_contract_project","write_foundry_tests","manifest","audit_math","audit_permissions","audit_economics","audit_flow"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"3014f1ea5961918ca059453a484bf4c8bcbbfc2248dbe31d94ac7c5cdf8f50bd","skillId":"audit-judge","tools":[]},"key":"audit_judge","kind":"code","role":"review","skillHash":"3014f1ea5961918ca059453a484bf4c8bcbbfc2248dbe31d94ac7c5cdf8f50bd","skillId":"audit-judge","state":"accepted"},{"acceptedSubmissionHash":"80f33688b41f1d237ded5057dbfcb8d39d8c680fdd76e9cbb3983a1321ac5c04","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":"f7df55b24434306993fd43669d6ade3addd596515297095d300f783b104c73d6","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":"372cc84b0a69853930c721141a9fc5b27e6d667025ef35c532c7692a960b80e1","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"3ef09b17bf16b07175ca68a710a1f053447143496dd608879ca671ba92604d57","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 part 1 of 3 of the IMD6900 Frens on-chain art, exactly as it is in the repository: the data contracts FrenArtChunk1 and FrenArtChunk2 (src/FrenArtChunks.sol), in that order, no constructor arguments. Their code is generated art data (a STOP byte, then the bytes); do not change them, the renderer only accepts chunks with these exact code hashes (src/FrenArtIndex.sol). The renderer and the other chunks come in launches 2 and 3 (README.md).","parentJobId":null,"planHash":"0f64d73abae7ac24a4bbace903a895d6743aae86d84df3e8e00d170947b47697","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"719b9f22-aa3f-4b45-8b97-b8b644c033f9","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-819-frenartchunk1-frenartchunk2"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"51050","feedbackHash":"10327394c1fba82f02277c49dfe055fda8c9814bf834c96a589bad4a1420fa6d","nodeKey":"adapt_contract_project","submissionHash":"5a36d26de9c5159852e641cad36decca76837986e2fd928d1792599864dec781","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51423","feedbackHash":"dd8da6c526116f58ff977268b627a91a185049878ebfc624a85f31b2585dcda2","nodeKey":"audit_economics","submissionHash":"e97c9f263653323283f0582a048b90e1a999b3037718b2cc4c750e7e3ddb4a69","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51142","feedbackHash":"1ea60d00192cc0276de4c88bcc120dd1554778c4600b6bac222a636c1f8de598","nodeKey":"audit_flow","submissionHash":"830efe378cc4dfd59ed05fea435b71a742b583abc1e64f90cd95aa01e930dec0","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52124","feedbackHash":"c5f3ebf4b0ef35e2b873b618deac03e0f2032f1940ddd1e1eafc67ec919a7f16","nodeKey":"audit_imported_code","submissionHash":"a78e1bb3c947da525bea19fb80a7714d7a75cbf39ae5ae3cd412c8a9af71c340","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52131","feedbackHash":"1755f09f3944e6931f26177bdc95acb7ab85c42a7d5b612d8f727f30e454c6b0","nodeKey":"audit_judge","submissionHash":"a947978c46f145effccf2bfb88353011a83ef752b2b326f8ba683e79108ad15a","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51227","feedbackHash":"bf9b6f5b48ccde6d51fc60233a25e1d2ebb8f4ad5ace76e290b21f178a76dab3","nodeKey":"audit_math","submissionHash":"80f33688b41f1d237ded5057dbfcb8d39d8c680fdd76e9cbb3983a1321ac5c04","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51166","feedbackHash":"45e64fc49a4eca38026d1a9f3bd04a4b1e2404e7596ea493ea31e6b270aeebe3","nodeKey":"audit_permissions","submissionHash":"f7df55b24434306993fd43669d6ade3addd596515297095d300f783b104c73d6","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51193","feedbackHash":"6d7ccefded0a4c226c9e44aa4e41cbb038755fd6d5ff4c4c206ef5e25ad1819e","nodeKey":"manifest","submissionHash":"372cc84b0a69853930c721141a9fc5b27e6d667025ef35c532c7692a960b80e1","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51327","feedbackHash":"f15cded2881bc3aa9926ea3ab06dc4cf6c45a0335e8df9d8d98f0935507dfef7","nodeKey":"write_foundry_tests","submissionHash":"3ef09b17bf16b07175ca68a710a1f053447143496dd608879ca671ba92604d57","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"ce884e7cf5eb909f957b6e2dc1e7e2ff6bcc8457e49d5c73a4218a17cb8a5121","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"e9e1e85f4802b20c30a1bf16406f24caded80f16574701f1077b7d13b1f3f1f1","device":"fedfd42dfee2f4e6","findings":[],"hash":"372cc84b0a69853930c721141a9fc5b27e6d667025ef35c532c7692a960b80e1","nodeId":"b3bb52a9-826e-49b3-b478-e28f007fb9d0","outcome":"completed","summary":"Created [launch.json](/home/seat/.identitymd/work/719b9f22-aa3f-4b45-8b97-b8b644c033f9/b3bb52a9-826e-49b3-b478-e28f007fb9d0/launch.json) with `FrenArtChunk1`, then `FrenArtChunk2`, both with empty constructor arguments.\n\nSchema and compiled ABI checks passed. `forge build` succeeded; all 11 tests passed. Only `launch.json` changed.","treeHash":"442d1e5bdebc265114ae45e89ec5e5f1e8ea41dd","usage":{"cachedInputTokens":408448,"inputTokens":36803,"model":"gpt-6-astra","outputTokens":2465,"runtime":"codex","turns":4,"wallClockMs":202334}},{"artifacts":[],"attempt":1,"bundleHash":"79d8a4de9e748721eef60ee1e9b2eeb178e58bebf7d8c7fc2368738d9a360f9e","device":"c5f970da1a0cc219","findings":[],"hash":"3ef09b17bf16b07175ca68a710a1f053447143496dd608879ca671ba92604d57","nodeId":"f501c0c3-ab3b-4f6b-b490-e0dcad36b063","outcome":"completed","summary":"Added deployment failure/retry tests, CREATE2 collision checks, corrupted-art rejection tests, and ETH conservation/art immutability invariants.\n\nOffline `forge build` and `forge test` pass: 20 tests, including 16,384 randomized invariant calls.\n\nOnly `test/` files changed. No defects requiring a report were found.","treeHash":"e5dd118f0ebc4478c392b0e47edd1ff26e2b6e09","usage":{"cachedInputTokens":972672,"inputTokens":85354,"model":"gpt-6-astra","outputTokens":10832,"runtime":"codex","turns":6,"wallClockMs":474130}},{"artifacts":[],"attempt":1,"bundleHash":"f849475657c2443e64a808aa5163ff1206f169e92240389609c2702d74a7d858","device":"d7953fb8f7e2c68b","findings":[],"hash":"5a36d26de9c5159852e641cad36decca76837986e2fd928d1792599864dec781","nodeId":"b53961e6-ee5b-421f-a3e9-0b3360ecf6ed","outcome":"completed","summary":"Implemented the adaptation, preserving FrenArtChunk1 and FrenArtChunk2 exactly. Fixed the reproduced audit findings and documented every change in [ADAPTATION.md](/home/imd/.identitymd/work/719b9f22-aa3f-4b45-8b97-b8b644c033f9/b53961e6-ee5b-421f-a3e9-0b3360ecf6ed/ADAPTATION.md).\n\nValidation passed: `forge build`, all 13 Solidity tests, and four Python tests. No deployment was broadcast.","treeHash":"db7c7ca086b86655f8964d370ed20d4dec3badbd","usage":{"cachedInputTokens":1045248,"inputTokens":84187,"model":"gpt-6-astra","outputTokens":18618,"runtime":"codex","turns":7,"wallClockMs":702209}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"11e4593175677f7e","findings":[{"citation":"resolved","description":"Boundary check (payable path). The constructor is nonpayable (initcode begins 6080 34 61.. 57: CALLVALUE JUMPI), so deployment with value reverts as test_ConstructorsRejectValue shows. The deployed runtime, however, is byte 0x00 (STOP) followed by art, so any call carrying value succeeds and the chunk has no code path that can ever move the balance out. This matches the design ('calling it does nothing', SSTORE2-style data contract) and harms only the sender, so it is recorded as a trust/usage note rather than a defect. Not a change request: changing the runtime would change the pinned code hashes the renderer requires.","line":387,"path":"src/FrenArtChunks.sol","reproduction":"Deploy FrenArtChunk1 (no args). Then: (bool ok,) = chunk1.call{value: 1 ether}(\"\"); Expected by a naive sender: revert (contract 'does nothing'). Actual: ok == true, chunk1.balance == 1 ether, and no function exists to withdraw it. Verified with a scratch Foundry test (test_ChunkRuntimeAcceptsEther) on this tree.","severity":"info","snippet":"            return(add(code, 32), mload(code))","title":"Chunk runtime is a bare STOP: ETH sent to FrenArtChunk1/2 is accepted and unrecoverable"},{"citation":"resolved","description":"Boundary note on the number that launch 3 depends on. foundry.toml auto-detects any solc >= 0.8.26. The runtime (and so the pinned code hashes 0xf86a2dec.. and 0x8579d215..) is the literal data and is compiler-independent, which the suite confirms. The creation code is not: on this worker (solc 0.8.37) type(FrenArtChunk1).creationCode is 27,486 bytes and FrenArtChunk2 is 28,867 bytes, versus the 27,586 / 29,281 recorded here from another compiler. Since the factory deploys with CREATE2, address = f(factory, salt, keccak256(initcode)), so an address predicted from a locally compiled initcode can differ from the deployed one. The renderer in launch 3 takes chunks 1 and 2 as static address arguments and reverts with BadArt if they point anywhere else. All sizes stay under the 49,152-byte EIP-3860 limit and the gas picture is unchanged (deposit 9,628,000 + calldata ~861k + CREATE2 64k + hashing/initcode words ~15k + constructor execution ~30k, well under 2^24), so this is not a launch-1 defect; it is the one input to a later launch that must be read from chain rather than computed.","line":29,"path":"ADAPTATION.md","reproduction":"On this tree with solc 0.8.37: forge test logs init1 = 27486, init2 = 28867 (scratch test), while ADAPTATION.md line 29 states 27,586 / 29,281. keccak256 of the two initcodes therefore differs between compilers, and so does the CREATE2 address for the same factory and salt. Expected: the launch-3 manifest uses the addresses emitted by the launch-1 deployment. Actual risk if a worker predicts them from a local build: FrenRenderer constructor reverts BadArt (cs[k].codehash != want) and launch 3 fails.","severity":"info","snippet":"Results: build passed; all 11 deliverable Solidity tests plus the two scratch reproduction tests passed; all four Python tests passed. The original opcode-scan proof now passes. Estimated launch totals are 11,646,976 / 10,863,832 / 14,986,176 gas. The part-1 constructor ABIs are nonpayable with no inputs, and their initcode sizes remain 27,586 / 29,281 bytes.","title":"Part-1 initcode size and CREATE2 address are compiler-dependent; launch-3 static addresses must come from the actual deployment, not local prediction"}],"hash":"80f33688b41f1d237ded5057dbfcb8d39d8c680fdd76e9cbb3983a1321ac5c04","nodeId":"7e5cab0e-7507-4771-81cb-9cc151825118","outcome":"completed","summary":"The review is complete. The findings file is in place, the scratch tests are removed, and the working tree is clean apart from the harness-ignored findings file.\n\n**Outcome: no defect in the assigned area.** The math, boundary and numerical-gap checks on launch 1 all hold. Two informational notes are recorded in `.imd-findings.json`, neither of which asks for a code change.\n\n**What I verified for chunks 1 and 2**\n\n- **Index arithmetic.** Decoded all 70 index entries on the deployed chunks. Chunk 1 holds 14 entries covering exactly 24,000 decoded bytes, chunk 2 holds 11 covering exactly 24,138, with no gaps, overlaps or out-of-range offsets. The reader's `1 + off + len` bound and `extcodecopy` from offset `1 + off` are correct for the STOP-prefixed layout.\n- **Layer data.** Every one of the 69 layers, including the 25 faces in chunks 1 and 2, consumes exactly its indexed length, has no zero-length run, sums each row to its width, and stays inside the 120x120 space. A zero run would have been an infinite loop in `_draw`, so this was the key data boundary to rule out.\n- **Window math.** All ten backgrounds are 120x120 at the origin, so the 0..36 seed shift always covers the 84x84 canvas. Rendering every background at both shift extremes left no unpainted pixel.\n- **Sizes and gas.** Runtimes of 24,001 and 24,139 bytes sit under EIP-170, initcodes under EIP-3860, and the opcode scan passes. Launch 1 costs about 10.7M gas against the 2^24 cap, dominated by code deposit. The constructor is a nonpayable PUSH31/MSTORE sequence with negligible execution cost.\n- **Slither leads.** All ten target the renderer, not launch 1. The uninitialized locals are intentional zero defaults, and the missing zero-checks are covered by the codehash comparison, which fails for the zero address.\n\n**Informational notes recorded**\n\n- The chunk runtime is a bare STOP, so ETH sent to it succeeds and is permanently stuck. This is by design and only harms the sender.\n- Initcode size depends on the compiler. Under this worker's solc 0.8.37 the initcodes are 27,486 and 28,867 bytes rather than the sizes in ADAPTATION.md. Runtime hashes are unaffected, but the CREATE2 addresses launch 3 needs must be read from the actual deployment, not predicted locally.\n\n**Entry point coverage.** FrenArtChunk1 constructor: holds. FrenArtChunk2 constructor: holds. Chunk runtime fallback: holds, with the ETH note above. Renderer reads of chunks 1 and 2 via `_entry` and `_draw`: holds. Renderer constructor, `tokenURI`, `pendingURI`, `canvas`, `attributes`: outside the launch-1 area, traced for math only and holding. The PUSH-encoded read path for chunks 4 and 7 belongs to launch 2 and 3 and was checked for arithmetic consistency but not exhaustively.","treeHash":null,"usage":{"cachedInputTokens":988366,"inputTokens":386,"model":"claude-fable-5-1","outputTokens":23623,"runtime":"claude","turns":24,"wallClockMs":475719}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"e57a8e639cccfbab","findings":[{"citation":"resolved","description":"FrenArtChunk1 and FrenArtChunk2 return a runtime whose first byte is STOP (0x00). STOP halts successfully, so a plain call with value does not revert: the ETH is credited to the data contract and there is no code path that can ever move it out (no owner, no withdraw, SELFDESTRUCT forbidden by the launch floor). This is the intended SSTORE2-style design and not a defect of the launch, but it is a trust/UX assumption worth stating: the chunk addresses must never be published as payment or mint addresses, and the frens contract or any front end must not send value to them. The same holds for FrenArtChunk2 (same constructor at src/FrenArtChunks.sol:775).","line":387,"path":"src/FrenArtChunks.sol","reproduction":"State: FrenArtChunk1 deployed at address c (any deployer; constructor takes no arguments and no value). Input: `(bool ok, bytes memory ret) = c.call{value: 1 ether}(\"\")`. Expected for a pure data contract: revert, or at least a recoverable balance. Actual: ok == true, ret.length == 0, c.balance == 1 ether, and no function exists to recover it. Verified in a scratch Foundry test (test_EthSentToChunkIsStranded) against the current tree: all three assertions hold. By contrast the constructor itself does reject value (test/LaunchPart1.t.sol test_ConstructorsRejectValue), so only post-deployment transfers are affected.","severity":"info","snippet":"            return(add(code, 32), mload(code))","title":"Chunk runtime (STOP) accepts and permanently strands any ETH sent to it"},{"citation":"resolved","description":"The chunks' runtime bytes are the hex literal returned by the constructor, so their code hash is compiler-independent and FrenArtIndex.CHUNK_HASHES / test/LaunchPart1.t.sol pin it correctly. The creation (init) code is not compiler-independent: with foundry.toml's auto_detect_solc = true and the floating pragma, the initcode (and the CBOR solc tag it embeds) changes with the installed solc, and with it keccak256(initcode) and the CREATE2 address the factory produces. Nothing in the repository is wrong, and the attestation described for the service binds the deployable creation bytes, so this is informational. It matters operationally for the two places that consume chunk addresses: the protected floor's IMD_PROJECT_ADDRESS_i prediction must be computed from the very build whose bytes are deployed, and launch 3's static address arguments for FrenArtChunk1/2 must be the addresses actually confirmed on chain after launch 1, never precomputed from a local build. If a precomputed address is wrong, FrenRenderer's constructor reads codehash 0 at that address and reverts BadArt, so launch 3 fails (recoverable by re-submitting with the right addresses; no funds at risk).","line":2,"path":"src/FrenArtChunks.sol","reproduction":"Build the same tree twice. `forge build` with the auto-detected solc 0.8.37 gives type(FrenArtChunk1).creationCode.length == 27486 and FrenArtChunk2 == 28867 (logged by a scratch test on this tree). `forge build --use 0.8.26` into a separate out dir gives 27586 and 29281 (the numbers ADAPTATION.md also records). Same salt and factory therefore yield two different CREATE2 addresses (address = keccak256(0xff ++ factory ++ salt ++ keccak256(initcode))), while in both builds the deployed runtime is 24001 / 24139 bytes with codehash 0xf86a2dec...2d4b / 0x8579d215...650e (asserted by test/LaunchPart1.t.sol and test_AllChunksPassFloorAndMatchIndex, which pass under 0.8.37 here and passed under 0.8.26 per ADAPTATION.md). Failing state for the downstream consumer: FrenRenderer deployed with c1 = an address predicted from build A while launch 1 was deployed from build B -> `cs[0].codehash` is 0 -> revert BadArt (src/FrenRenderer.sol:61).","severity":"info","snippet":"pragma solidity ^0.8.26;","title":"Creation code, and therefore the CREATE2 address of each chunk, depends on the solc version the builder auto-detects; only the runtime hash is pinned"}],"hash":"830efe378cc4dfd59ed05fea435b71a742b583abc1e64f90cd95aa01e930dec0","nodeId":"08fb008a-ea71-47d8-8e20-8a9df4842ecb","outcome":"completed","summary":"The review is complete. The findings file is in place, the scratch test is removed, and the working tree holds nothing new beyond the harness-excluded findings file.\n\n**Outcome: no defects in the launch-1 contracts.** FrenArtChunk1 and FrenArtChunk2 behave exactly as the repository states, and `.imd-findings.json` records two informational notes only, neither of which blocks deployment.\n\n**What I verified for the assigned area** (Execution Trace, Periphery, First Principles):\n\n- **Constructors** are nonpayable, take no arguments, read no storage, and return the hex literal as runtime. The existing suite passes under solc 0.8.37, pinning runtime sizes 24,001 and 24,139 and the two code hashes the renderer and generator both require.\n- **Launch-floor opcode scan** reproduced independently with the protected test's exact algorithm against freshly deployed chunks 1 and 2. Both pass. Initcode sizes are under the 49,152 limit.\n- **Index integrity** for the entries pointing into these chunks: 14 entries tile chunk 1 contiguously to decoded byte 24,000 and 11 entries tile chunk 2 to 24,138, each exactly one byte short of the runtime length, so the renderer's bounds check at `src/FrenRenderer.sol:315` and the STOP offset line up with no gap or overlap.\n- **Gas** from the real initcode bytes: calldata plus code deposit alone comes to about 10.6M, consistent with the repo's 11.6M estimate and under the 2^24 transaction cap.\n\n**Informational findings recorded:**\n\n1. The STOP runtime accepts value, so ETH sent to a chunk address is stranded with no recovery path. Reproduced with a 1 ether call that succeeds and leaves the balance in place. This is the intended data-contract design, flagged as a trust assumption.\n2. Creation code varies with the auto-detected solc version (27,586/29,281 bytes under 0.8.26 versus 27,486/28,867 under 0.8.37) while runtime hashes are identical. The CREATE2 address therefore depends on the toolchain, so launch 3's static chunk addresses must be read from the confirmed launch-1 deployment rather than precomputed, or the renderer constructor reverts with BadArt.\n\n**Coverage rows:**\n\n- FrenArtChunk1 constructor: holds.\n- FrenArtChunk2 constructor: holds.\n- Chunk runtime fallback (any call): finding 1 (value accepted and stranded, otherwise inert).\n- FrenRenderer constructor: holds for my area, with finding 2 as a deployment-process note.\n- FrenRenderer tokenURI, pendingURI, silhouette, attributes, bmp, canvas: holds for the chunk-1/2 read path; full rendering logic is outside this area and rests on the passing reference-equivalence tests. The slither leads on FrenRenderer are default-initialised locals and non-defects.\n\nNo high or critical findings, so no proof tests were attached.","treeHash":null,"usage":{"cachedInputTokens":778511,"inputTokens":386,"model":"claude-fable-5-1","outputTokens":19764,"runtime":"claude","turns":26,"wallClockMs":551177}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"03845cacb54c3a73","findings":[{"citation":"resolved","description":"The protected floor (.imd/reads/protected/evm_contracts/Contracts.protected.t.sol, test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes) walks each deployed application's runtime code byte by byte, skips only PUSH immediates (0x60..0x7f), and fails on any 0xf4 (DELEGATECALL), 0xf2 (CALLCODE) or 0xff (SELFDESTRUCT) it meets. The chunks' code is a STOP byte followed by raw art data, so none of those bytes is ever executed, but the scanner cannot tell data from code. The art's coat-shade slot indices are 244..248 (0xf4..0xf8, FrenRenderer SLOT0 = 244) and the palette holds 0xff colour components, and script/art/chunks.py never checks the packed bytes against the scanner. Replaying the scanner on the compiled code of all seven chunks: chunk 1 and 2 (this launch) 0 hits, chunk 3 0, chunk 4 234 hits (all 0xf4, first at code offset 3912 = this line byte 8), chunk 5 0, chunk 6 0, chunk 7 14 hits (1x 0xf2 at offset 7671, 2x 0xf4, 11x 0xff in the palette, line 2278). Launch 2 (FrenArtChunk3, FrenArtChunk4) and launch 3 (FrenArtChunk5..7 + FrenRenderer) are therefore rejected automatically. Because FrenRenderer's constructor reverts with BadArt unless every chunk has exactly the code hash in FrenArtIndex.CHUNK_HASHES, there is no way to deploy a working renderer through the factory without re-encoding the art (for example re-mapping the slot indices or padding chunks 4 and 7 so no unshielded 0xf2/0xf4/0xff byte remains) and regenerating FrenArtIndex, which changes the hashes the renderer accepts. Launch 1 itself passes the floor, but the two chunks it deploys (about 9.63M gas of code deposit) are useful only if the regenerated art keeps FrenArtChunk1 and FrenArtChunk2 byte-identical; the requester should settle the re-encoding before launch 1 spends that gas. Fix: in chunks.py, scan every packed chunk (STOP byte + art) with the floor's exact algorithm and fail generation on any hit, then re-pack (pad or re-map) until all seven pass; regenerate FrenArtChunks.sol and FrenArtIndex.sol together.","line":1226,"path":"src/FrenArtChunks.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {\n    FrenArtChunk1, FrenArtChunk2, FrenArtChunk3, FrenArtChunk4, FrenArtChunk5, FrenArtChunk6, FrenArtChunk7\n} from \"src/FrenArtChunks.sol\";\n\n/// @notice Every FrenArtChunk's runtime code must pass the launch factory's protected floor\n///         (Contracts.protected.t.sol, test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes):\n///         the scanner walks the code byte by byte, skips PUSH immediates, and rejects 0xf4 / 0xf2 / 0xff\n///         wherever else they appear. The art is data, but the scanner cannot know that. As generated,\n///         FrenArtChunk4 (234 bytes) and FrenArtChunk7 (14 bytes) are rejected, so launches 2 and 3 fail\n///         and the renderer, which accepts only these exact code hashes, can never be deployed.\ncontract FloorScanTest is Test {\n    function _forbidden(bytes memory code) internal pure returns (uint256 hits) {\n        for (uint256 j; j < code.length; ++j) {\n            uint8 op = uint8(code[j]);\n            if (op >= 0x60 && op <= 0x7f) { j += op - 0x5f; continue; }\n            if (op == 0xf4 || op == 0xf2 || op == 0xff) ++hits;\n        }\n    }\n\n    function _floor(string memory name, address a) internal view {\n        bytes memory code = a.code;\n        assertGt(code.length, 0, string.concat(name, \": missing runtime\"));\n        assertLe(code.length, 24_576, string.concat(name, \": runtime exceeds EIP-170\"));\n        assertEq(_forbidden(code), 0, string.concat(name, \": forbidden application opcode\"));\n    }\n\n    function test_EveryChunkPassesTheProtectedFloor() public {\n        _floor(\"FrenArtChunk1\", address(new FrenArtChunk1()));\n        _floor(\"FrenArtChunk2\", address(new FrenArtChunk2()));\n        _floor(\"FrenArtChunk3\", address(new FrenArtChunk3()));\n        _floor(\"FrenArtChunk4\", address(new FrenArtChunk4()));\n        _floor(\"FrenArtChunk5\", address(new FrenArtChunk5()));\n        _floor(\"FrenArtChunk6\", address(new FrenArtChunk6()));\n        _floor(\"FrenArtChunk7\", address(new FrenArtChunk7()));\n    }\n}","reproduction":"State: the repository as committed. Steps: deploy FrenArtChunk4 with `new FrenArtChunk4()` (no arguments), read `address.code`, and run the floor's scan: for j in 0..len, op = code[j]; if 0x60 <= op <= 0x7f skip op-0x5f bytes; else require op not in {0xf4, 0xf2, 0xff}. Expected (what the launch requires): zero hits for every chunk, as is the case for FrenArtChunk1 (24001 bytes) and FrenArtChunk2 (24139 bytes). Actual: FrenArtChunk4 yields 234 hits, the first 0xf4 at code offset 3912 (the 9th byte of src/FrenArtChunks.sol:1226, `...f802f4...`), and FrenArtChunk7 yields 14 hits, the first 0xf2 at offset 7671 (src/FrenArtChunks.sol:2277) and 0xff bytes in the palette at src/FrenArtChunks.sol:2278 (`...00ffffff00...`). The attached test fails with `FrenArtChunk4: forbidden application opcode: 234 != 0`. Run: forge test --match-path test/scratch/FloorScan.t.sol -vv","severity":"high","snippet":"            hex\"f82f00060001f802f401f52f00050001f804f401f52e00050001f805f401f52d00040001f806f401f52d00040001f805f401f801f401f52c00030001f801f70a\"","title":"FrenArtChunk4 and FrenArtChunk7 runtime bytes are rejected by the launch floor's forbidden-opcode scan, so launches 2 and 3 can never deploy and the renderer that only accepts these code hashes is unr"},{"citation":"resolved","description":"The test adds the gas measured around each launch call to 21,000 plus 16 gas per init-code byte and asserts the total is under 95% of 2^24. In the toolchain this repository is checked with (forge 1.8.4), gasleft() around a CREATE does not account for contract creation at all: measuring `new FrenArtChunk1()` from a helper contract gives 2,954 gas, and vm.startSnapshotGas around the same deploy gives 509 gas, although the code deposit alone is 24,001 bytes x 200 = 4,800,200 gas. The test therefore logs 1,000,622 / 940,916 / 1,267,983 gas for the three launches and passes, while the README quotes about 10.7M, 9.8M and 13.7M for the same launches measured elsewhere. A by-hand estimate for launch 1 (code deposit 9,628,000 for 48,140 runtime bytes, 2 x 32,000 CREATE, EIP-3860 init-code words, init execution and memory, about 56.9 KB of calldata at up to 16 gas per byte, factory overhead) lands near the README's 10.7M and under the 16,777,216 cap, so the launch is not blocked, but that is not what the test shows: a launch that exceeded the cap, or the policy's gas ceiling, would pass it unchanged. Fix: measure with --isolate-style per-transaction accounting that includes creation, or compute the deposit term explicitly (200 x runtime bytes per contract) and assert on that sum; and make the test fail if the measured creation gas is below the code-deposit floor so a non-metering environment is detected.","line":147,"path":"test/FrenRenderer.t.sol","reproduction":"State: the repository as committed. Run `forge test --match-path test/FrenRenderer.t.sol --match-test test_LaunchesFitTransactions -vv`. Expected: the logged `launch 1 gas (with calldata)` is at least 9,628,000 (the EIP-170 code deposit of FrenArtChunk1 + FrenArtChunk2 at 200 gas per byte). Actual: 1,000,622, and the test passes. Direct check: a contract doing `g = gasleft(); new FrenArtChunk1(); used = g - gasleft();` reports used = 2,954 in this toolchain, and `vm.startSnapshotGas(); new FrenArtChunk1(); vm.stopSnapshotGas()` reports 509, both far below the 4,800,200 deposit.","severity":"low","snippet":"            uint256 total = launchGas[i] + 21_000 + 16 * launchInitBytes[i];","title":"test_LaunchesFitTransactions does not measure contract creation in this Foundry build, so it cannot show the launches fit the transaction cap"},{"citation":"resolved","description":"The comment on the line above says 'the renderer checks the chunks it's given' by size, but FrenRenderer reads only CHUNK_HASHES (constructor) and INDEX (_entry); CHUNK_SIZES has no reader anywhere in src/ or test/. The values are correct (0x5dc1 = 24001 and 0x5e4b = 24139 match the compiled code of FrenArtChunk1 and FrenArtChunk2; all seven match), and the hash check subsumes the size check, so this is a documentation mismatch, not a defect. Either drop the constant or make the comment say it is informational.","line":21,"path":"src/FrenArtIndex.sol","reproduction":"Run `grep -rn CHUNK_SIZES src test`: the only occurrence is its declaration at src/FrenArtIndex.sol:21. Expected per the comment at line 20: a read in FrenRenderer's constructor comparing each chunk's code length to the table. Actual: no read; the constructor compares codehash only (src/FrenRenderer.sol:61).","severity":"info","snippet":"    bytes internal constant CHUNK_SIZES = hex\"5dc15e4b5bb7503b4bcb539d21d3\";","title":"FrenArtIndex.CHUNK_SIZES is documented as checked by the renderer but nothing reads it"},{"citation":"resolved","description":"Read in full: src/FrenArtChunks.sol (FrenArtChunk1..7: structure, constructors, assembly return; the hex data was checked by machine, not by eye), src/FrenArtIndex.sol, src/FrenRenderer.sol, test/FrenRenderer.t.sol, script/art/chunks.py, README.md, foundry.toml, the protected floor test and the Pashov guide. Read in part: test/ref/FrenRendererRef.sol (header and the FrenArtRef store; the reference renderer body was not reviewed since it is a test oracle, not launch code). Not reached: the frens contract IMD6900Frens at 0x69004fEd3d8a34FFA952d15A128f74D8340fa79d (not in the repository, no network use), and the IMD policy row (gas ceiling, factory, chain) which is not a repository file. Checks on the two launch-1 contracts, all passing: constructors take no arguments and are nonpayable; init code 27,586 and 29,281 bytes (under the floor's 49,152 limit); runtime code 24,001 and 24,139 bytes (under EIP-170's 24,576), first byte 0x00 (STOP), so the contracts are inert when called; runtime keccak256 equals CHUNK_HASHES[0] and [1] (0xf86a2dec... and 0x8579d215...), so these exact compiled bytes are what FrenRenderer will accept in launch 3; the floor's forbidden-opcode scan finds 0 hits in both; no owner, storage, selfdestruct, delegatecall, proxy, initializer, mint, pause or custody of any asset: the contracts hold no state and move no value, so the loss-of-funds, access-control, reentrancy, arithmetic and invariant checklists have no surface here. The project suite (6 tests) passes: the renderer's output matches the art kit's reference and the launch renderer byte for byte. No defect was found in FrenArtChunk1 or FrenArtChunk2 themselves; the high finding concerns the other chunks of the same generated set and whether launch 1 should spend gas before they are regenerated.","line":8,"path":"src/FrenArtChunks.sol","reproduction":"Not a defect. Verification commands: `forge test --match-path test/FrenRenderer.t.sol -vv` (6 passed); a scratch test deploying FrenArtChunk1 and FrenArtChunk2, asserting code.length == 24001 / 24139, code[0] == 0x00, codehash == the first two 32-byte words of FrenArtIndex.CHUNK_HASHES, and 0 hits from the protected floor's scanner, passed for both.","severity":"info","snippet":"contract FrenArtChunk1 {","title":"Review coverage: contracts read and checks performed for launch 1 (FrenArtChunk1, FrenArtChunk2)"}],"hash":"a78e1bb3c947da525bea19fb80a7714d7a75cbf39ae5ae3cd412c8a9af71c340","nodeId":"37fc2e67-433d-4d6b-85ce-d4ffbdcaf5a5","outcome":"completed","summary":"The review is complete. The findings file is in place at the repository root, and nothing else in the tree changed.\n\n**Outcome for launch 1:** FrenArtChunk1 and FrenArtChunk2 have no defects of their own. Both pass every check the protected floor applies, and I verified each one by deploying the compiled contracts:\n\n- Runtime starts with a STOP byte, so calling either contract does nothing.\n- Runtime sizes are 24,001 and 24,139 bytes, under the EIP-170 limit; init code is under the floor's 49,152-byte limit.\n- The deployed code hashes equal the first two entries of the renderer's hash table, so launch 3 will accept them.\n- The floor's forbidden-opcode scan finds zero hits in both.\n- No constructor arguments, nonpayable, no owner, no storage, no custody, no proxy or initializer.\n\n**Findings written to `.imd-findings.json`:**\n\n1. **High, with proof.** FrenArtChunk4 and FrenArtChunk7 fail the floor's forbidden-opcode scan. The art's coat-shade slot indices are 0xf4 to 0xf8 and the palette contains 0xff, and the scanner cannot tell data from code. Chunk 4 has 234 flagged bytes and chunk 7 has 14. Launches 2 and 3 would be rejected automatically, and since the renderer only accepts these exact code hashes, no working renderer can be deployed without re-encoding the art and regenerating the index. Launch 1 is only worth its gas if the regenerated art keeps chunks 1 and 2 byte-identical. The proof test under `test/scratch/FloorScan.t.sol` fails on the current code with the message below.\n\n```\n[FAIL: FrenArtChunk4: forbidden application opcode: 234 != 0]\n```\n\n2. **Low.** The project's gas-fit test does not measure contract creation in this Foundry build. It logs about 1.0M gas for launch 1 while the code deposit alone is 9.6M. My by-hand estimate agrees with the README's 10.7M and sits under the 2^24 cap, so the launch is not blocked, but the test cannot show that.\n\n3. **Info.** The index's chunk-size table is documented as checked by the renderer but has no reader.\n\n4. **Info.** Coverage statement: all three source files, the test, the generator script, the README and the floor test were read in full. The reference renderer body was read only in part. The live frens contract and the policy row were not reachable from the repository.\n\nThe project's own six tests pass, including the byte-for-byte match against the reference renderer.","treeHash":null,"usage":{"cachedInputTokens":1226287,"inputTokens":450,"model":"claude-fable-5-1","outputTokens":26471,"runtime":"claude","turns":32,"wallClockMs":803693}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"de319b702da6aa2e","findings":[{"citation":"resolved","description":"Merges four specialist reports (audit_flow 4e6effdf, audit_math dfea6a1f, audit_permissions 9a02773e, audit_economics cd425d1f), which share one root cause. FrenArtChunk1 (src/FrenArtChunks.sol:387) and FrenArtChunk2 (src/FrenArtChunks.sol:775, same constructor) return a runtime whose first byte is 0x00 (STOP). The constructors are nonpayable, so deploying with value fails, and test/LaunchPart1.t.sol test_ConstructorsRejectValue confirms this. After deployment, though, any CALL with value runs STOP and succeeds, so the chunk keeps the ETH. The runtime has no code path, owner or SELFDESTRUCT that could ever move it out. The README and NatSpec say 'Calling it does nothing', which is true for storage and return data but not for value. Only someone who mis-sends ETH to a data address is harmed, and no protocol funds pass through these contracts, so this is a usage note and not a launch blocker. The bytes must not change, because FrenArtIndex.CHUNK_HASHES and the FrenRenderer constructor pin them. The only remedy is documentation: never publish chunk addresses as payment addresses.","line":387,"path":"src/FrenArtChunks.sol","reproduction":"Compiled with solc 0.8.26, which forge auto-detected on this tree. Deploy FrenArtChunk1 and FrenArtChunk2 with CREATE2 (salt 0, value 0). The resulting codehashes are 0xf86a2dec...2d4b and 0x8579d215...650e, and both runtimes pass the protected floor's PUSH-skipping opcode scan and the EIP-170 size limit. Then, holding 2 ether: (bool ok, bytes memory r) = c1.call{value: 1 ether}(\"\") gives ok == true, r.length == 0 and c1.balance == 1 ether. c2.call{value: 1 ether}(hex\"deadbeef\") gives ok == true and c2.balance == 1 ether. A plain reading of 'calling it does nothing' would expect the call to revert or the value to be recoverable. Actual: the call is accepted and the balance is permanently stuck. This was reproduced in a scratch Foundry test (test/scratch/Repro.t.sol, not kept), and it passed.","severity":"info","snippet":"            return(add(code, 32), mload(code))","title":"Deployed chunk runtime (leading STOP byte) accepts ETH sent to it and can never release it"}],"hash":"a947978c46f145effccf2bfb88353011a83ef752b2b326f8ba683e79108ad15a","nodeId":"ee6bdf21-355e-44cf-a653-64660b4e2807","outcome":"completed","summary":"I found nothing that should block launch 1. The only finding I kept is informational, and it's written to `.imd-findings.json`. No tracked files changed, and I deleted my scratch test.\n\n**Checks I ran:**\n- **Test suite:** `forge test` passes, 20 of 20, using forge 1.8.4 with solc 0.8.26, which forge picked automatically.\n- **The two chunks:** in a scratch test, `FrenArtChunk1` and `FrenArtChunk2` deployed with CREATE2, no arguments and no ETH.\n  - Their code hashes match the pinned ones in `src/FrenArtIndex.sol` (`0xf86a2dec…2d4b` and `0x8579d215…650e`).\n  - Their code sizes are 24,001 and 24,139 bytes, under the 24,576-byte limit.\n  - Both pass the protected opcode scan.\n  - Deploying them with ETH attached fails, as it should.\n- **`launch.json`:** it lists `FrenArtChunk1` then `FrenArtChunk2`, with no constructor arguments, and is valid against the schema.\n\n**The finding I kept (info):** once deployed, each chunk accepts ETH sent to it and can never send it back. Their code starts with a STOP byte, so a call carrying ETH succeeds and the ETH is stuck (`src/FrenArtChunks.sol:387`, and `:775` for chunk 2). Four specialists reported this, and I merged their reports into one finding. I reproduced it: sending 1 ether to each chunk succeeded and left a balance of 1 ether. Only someone who sends ETH there by mistake loses anything. The code can't change without breaking the hashes the renderer requires, so the fix is documentation: never publish the chunk addresses as places to pay.\n\n**Dropped:**\n- **Creation code depends on the compiler version (2 reports):** I couldn't reproduce this. Only solc 0.8.26 is installed, and installing a second version failed because the filesystem is read-only. With 0.8.26 the creation-code sizes are 27,586 and 29,281 bytes, which match what `ADAPTATION.md` says. The pinned code hashes don't depend on the compiler. The claim that launch 3 must use the addresses actually deployed on chain, not ones predicted from a local build, is still sound advice, but it isn't a code defect in this launch.\n- **Slither leads in `FrenRenderer.sol`:** these are not defects, and the renderer isn't part of this launch anyway. The \"uninitialized\" local variables at lines 97, 142 and 143 are meant to start at zero. The missing zero-address checks don't matter, because the constructor already reverts with `BadArt` when an address has no code: its code hash can't match the pinned one.\n- **Test-writer:** reported no findings.\n\nThe only entry points in this launch are the two constructors and the code each chunk leaves behind. The constructors hold: they take no input, reject ETH and return the exact pinned bytes. The deployed code holds too, except for the ETH note above.","treeHash":null,"usage":{"cachedInputTokens":513981,"inputTokens":20,"model":"claude-opus-5-5","outputTokens":6116,"runtime":"claude","turns":11,"wallClockMs":337289}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"56e50117311155be","findings":[{"citation":"resolved","description":"FrenArtChunk1 and FrenArtChunk2 return a runtime whose first byte is 0x00 (STOP). The constructor is nonpayable (verified: deploying with 1 wei of value fails, test_ConstructorsRejectValue), but once deployed the runtime has no revert path at all: a CALL with value executes STOP and succeeds, so ETH sent to a chunk address is accepted and can never be moved out (no code path, no owner, no SELFDESTRUCT; the opcode scan forbids it). This is the same property every SSTORE2-style data pointer has and no protocol funds flow here, so it is informational: the only victim is whoever mis-sends value to a data address. It is reported because the README (lines 5-6 of the NatSpec, 'Calling it does nothing') and the protected floor do not state it, and because it is the only value flow these two contracts have. No change to the chunks is recommended (their code hashes are pinned by FrenArtIndex.CHUNK_HASHES and the renderer); at most, document it. Economic/invariant/flow-gap coverage of the launch otherwise found no defect: runtime hashes recomputed independently with cast keccak match the pinned 0xf86a2d.../0x8579d2... values; every INDEX entry assigned to chunk 0 ends at 24000 and to chunk 1 at 24138, exactly the data behind the STOP byte; CHUNK_SIZES 0x5dc1/0x5e4b equal the runtimes; the exact protected opcode scan passes; an isolated Foundry measurement of a factory CREATE2 of each chunk costs 5,331,393 and 5,363,237 gas including code deposit, plus ~867k calldata gas (25,958 and 27,366 non-zero initcode bytes), about 11.6M total against the 16,777,216 transaction cap.","line":387,"path":"src/FrenArtChunks.sol","reproduction":"Deploy FrenArtChunk1 through any factory (e.g. the Part1FactoryProbe in test/LaunchPart1.t.sol) to address c1. Then from any account with 1 ether: (bool ok,) = c1.call{value: 1 ether}(\"\"); Expected per README ('calling it does nothing'): the value transfer is refused or at least recoverable. Actual (measured in a scratch test): ok == true, c1.balance == 1 ether, c1.codehash unchanged, and there is no function, owner or opcode in the runtime that can ever send the balance out.","severity":"info","snippet":"            return(add(code, 32), mload(code))","title":"Chunk runtimes (STOP byte) accept and permanently strand any ETH sent to them; README's 'calling it does nothing' omits this"}],"hash":"e97c9f263653323283f0582a048b90e1a999b3037718b2cc4c750e7e3ddb4a69","nodeId":"0d1eb86b-149f-49c4-9960-47d1478842ba","outcome":"completed","summary":"Review complete. The findings file holds one informational entry and no defects of medium severity or above.\n\n**Outcome.** Part 1 of the launch, FrenArtChunk1 then FrenArtChunk2 with no arguments, holds under the Economic Security, Invariant and Flow Gap guides. The `.imd-findings.json` file at the repository root contains one info finding and nothing blocking.\n\n**What I verified independently** rather than trusting the existing tests:\n\n- **Runtime identity.** I re-extracted both literals from the source and hashed them with `cast keccak`. Both match the hashes pinned in the index library and in the launch test, and both begin with a STOP byte.\n- **Index invariants.** Every layer entry for chunk 0 ends exactly at byte 24000 and for chunk 1 at byte 24138, matching the data behind the STOP byte with no gap or overrun. The informational size table equals the real runtime lengths.\n- **Original bytes.** The retention test compares all 69 decoded layers and the palette against the exported art files, and it passes. I could not verify that the export itself is the artist's original, which is outside the tree.\n- **Opcode floor.** The test's scan is byte for byte the protected harness's scan, and both chunks pass it. All vendored library files are regular blobs, so the offline verifier will find them.\n- **Gas economics.** An isolated scratch measurement of a factory CREATE2 for each chunk came to about 5.3M gas each including code deposit. With roughly 867k gas of calldata that is about 11.6M per launch transaction, in line with the repo's estimate and under the 16,777,216 cap. The policy's wei ceiling is a service setting I cannot see, so that remains an open item for the deployer simulation.\n- **Flow gaps across launches.** The renderer's constructor fails closed on any address whose code hash differs, and chunk code cannot change after deployment because the floor forbids SELFDESTRUCT. The static chunk addresses for launch 3 must come from the confirmed deployment handoff, not from a prediction, since initcode and therefore the CREATE2 address depends on the solc version the verifier builds with.\n\n**The one finding (info).** The STOP runtime accepts value: a call sending 1 ether to a deployed chunk succeeds and the balance is stranded forever. This is normal for SSTORE2-style data pointers and no protocol funds pass through these contracts, so I recommend only a documentation note. Changing the chunks is not an option because their hashes are pinned.\n\n**Coverage rows.** FrenArtChunk1 constructor: holds. FrenArtChunk2 constructor: holds. Chunk runtime fallback behaviour: finding 1 (info). FrenRenderer constructor and read path: holds for the properties that touch launch 1, not fully reviewed otherwise since it belongs to launch 3. The Slither leads all point at FrenRenderer and are outside this launch, so I left them to the launch-3 review.\n\nI removed the scratch test after measuring, so the tree is unchanged apart from the findings file.","treeHash":null,"usage":{"cachedInputTokens":896560,"inputTokens":482,"model":"claude-fable-5-1","outputTokens":19858,"runtime":"claude","turns":20,"wallClockMs":612166}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"45aa937328087de3","findings":[{"citation":"resolved","description":"Trust-boundary note, not a permission bypass. FrenArtChunk1 and FrenArtChunk2 have nonpayable constructors (deployment with value reverts, confirmed), but their runtime is the single opcode STOP followed by data. STOP halts successfully and keeps any msg.value, so any call with value to a deployed chunk succeeds and the ETH is unrecoverable: there is no owner, no withdraw, and no SELFDESTRUCT (and none could be added without changing the pinned code hash). The README/NatSpec describe calls as inert, which is true for state and return data, but the contracts are not value-rejecting. Harm is limited to the sender's own funds (self-harm only under the Pashov validation gates), so this is informational and does not block the launch. If the author wants value-rejection they cannot have it for launch 1 without changing the code hashes the renderer pins, so the correct action is documentation only.","line":7,"path":"src/FrenArtChunks.sol","reproduction":"Deploy FrenArtChunk1 via any CREATE2 factory (no value). Then from any account with 1 ether: (bool ok,) = chunk1.call{value: 1 wei}(\"\") -> ok == true and chunk1.balance == 1; chunk1.call{value: 1 wei}(hex\"deadbeef\") -> ok == true and chunk1.balance == 2. Expected by a reader of 'calling it does nothing': value calls revert or are refundable. Actual: accepted and stuck forever. Reproduced in a scratch Foundry test on this tree (forge 1.8.3, solc 0.8.30). Same for FrenArtChunk2.","severity":"info","snippet":"///         (FrenArtIndex says what is where). Calling it does nothing.","title":"Chunk runtimes accept and permanently trap ETH sent to them (STOP keeps call value)"},{"citation":"resolved","description":"Trust-gap note between documentation and the deployable bytes. foundry.toml sets auto_detect_solc = true with pragma ^0.8.26, so the creation code (and therefore the CREATE2 address and the creation-bytecode hash the attestation binds) depends on which solc the verifier has installed. On this worker 0.8.26 and 0.8.30 are both installed; forge picks 0.8.30 for src, giving initcode of 27,486 / 28,867 bytes, while ADAPTATION.md states 27,586 / 29,281, which are the 0.8.26 numbers. The runtime bytes and code hashes are compiler-independent (the constructor returns the literal; both builds yield 0xf86a2dec... and 0x8579d215...), so the renderer's hash pinning is unaffected and this is not a code defect. It matters only for anyone cross-checking the signed creation bytes or predicted addresses against the document; the service must take sizes/hashes from the attested artifact, not from this text.","line":29,"path":"ADAPTATION.md","reproduction":"On this tree: `forge build` (auto-detect selects 0.8.30) then read out/FrenArtChunks.sol/FrenArtChunk1.json and FrenArtChunk2.json bytecode.object lengths -> 27,486 and 28,867 bytes. `forge build --use 0.8.26 --out /tmp/out26` -> 27,586 and 29,281 bytes, matching ADAPTATION.md:29. Expected: the documented sizes match the build the verifier's toolchain produces, or the document states the solc version they belong to. Actual: they match only 0.8.26. Deploying either build gives the same 24,001 / 24,139-byte runtimes with the pinned hashes.","severity":"info","snippet":"Results: build passed; all 11 deliverable Solidity tests plus the two scratch reproduction tests passed; all four Python tests passed. The original opcode-scan proof now passes. Estimated launch totals are 11,646,976 / 10,863,832 / 14,986,176 gas. The part-1 constructor ABIs are nonpayable with no inputs, and their initcode sizes remain 27,586 / 29,281 bytes.","title":"Documented part-1 creation-code sizes (27,586 / 29,281) hold only for solc 0.8.26; auto-detected 0.8.30 yields 27,486 / 28,867 bytes"}],"hash":"f7df55b24434306993fd43669d6ade3addd596515297095d300f783b104c73d6","nodeId":"e568450b-a95f-4856-a72e-0719f1b09fbf","outcome":"completed","summary":"Review complete. The findings file holds two informational notes and no defects in the assigned area.\n\n**Result for the assigned area (Access Control, Trust Gap, Asymmetry) on FrenArtChunk1 and FrenArtChunk2:** no permission bypass, trust gap or asymmetry found. These contracts have no roles, no storage, no initializer and no external calls. Each constructor is nonpayable and returns the art literal as runtime, which begins with STOP. I verified on this tree: both runtimes deploy through a CREATE2 factory probe with the pinned hashes (0xf86a2dec…, 0x8579d215…) and sizes 24,001 / 24,139 bytes, contain zero raw 0xF2/0xF4/0xFF/0xEF bytes, pass the exact protected floor scan when run with the real creation bytes, and every FrenArtIndex entry that points at chunk 0 or 1 stays inside the deployed code. The renderer's hash check rejects address(0), a funded code-less address and any swapped order, so the launch-3 static addresses cannot substitute other art. The vendored libs contain no git submodule. All 11 existing tests pass.\n\n**Findings written to .imd-findings.json (both info, neither blocks the launch):**\n- Chunk runtimes accept and permanently trap ETH sent to them. A value call succeeds because STOP keeps msg.value. Self-harm only, and unfixable without changing the pinned code hashes, so documentation is the only action.\n- ADAPTATION.md's creation-code sizes hold only under solc 0.8.26. Auto-detect picks 0.8.30 here and yields 27,486 / 28,867 bytes. Runtime bytes and hashes are identical under both compilers, so this affects only cross-checks of signed creation bytes or predicted addresses.\n\n**Coverage rows:**\n\n| Entry point | Status | Reason |\n|---|---|---|\n| FrenArtChunk1 constructor | holds | nonpayable, no args, returns literal; rejects value, deploys pinned hash |\n| FrenArtChunk1 runtime fallback | finding (info 1) | STOP, no state, no return; keeps value |\n| FrenArtChunk2 constructor | holds | same as chunk 1 |\n| FrenArtChunk2 runtime fallback | finding (info 1) | same as chunk 1 |\n| FrenRenderer constructor (launch 3) | holds | codehash check per chunk, immutables only, no owner |\n| FrenRenderer tokenURI / pendingURI / silhouette / bmp / canvas / attributes | holds | all view or pure, no state, index reads bounded by combo checks; tests match the reference renderer byte for byte |\n\nSlither leads on FrenRenderer (uninitialized locals, missing zero checks) are intentional zero-initialised locals and addresses covered by the codehash check, so none became findings. Out of area and not reached: economics and gas-ceiling behaviour of the real factory transaction, which the deployment service simulates. My scratch tests were removed and no repository file was changed.","treeHash":null,"usage":{"cachedInputTokens":1163230,"inputTokens":450,"model":"claude-fable-5-1","outputTokens":22863,"runtime":"claude","turns":38,"wallClockMs":675911}}],"verification":[{"checks":[{"durationMs":237612,"exitCode":0,"name":"build","output":"Compiling 35 files with Solc 0.8.30\nSolc 0.8.30 finished in 237.34s\nCompiler run successful!\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n   ╭▸ src/FrenRenderer.sol:61:41\n   │\n61 │             if (cs[k].codehash != want) revert BadArt();\n   │                                         ━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:101:49\n    │\n101 │         _draw(cv, _entry(f + 20 + PENDING_BG), -int256(seed % 37), -int256((seed >> 8) % 37), slot, 0);\n    │                                                 ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:101:69\n    │\n101 │         _draw(cv, _entry(f + 20 + PENDING_BG), -int256(seed % 37), -int256((seed >> 8) % 37), slot, 0);\n    │                                                                     ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:102:63\n    │\n102 │         _draw(cv, _entry(uint8(FrenArtIndex.FACE_TABLE[0])), -int256(CX), -int256(CY), slot, shadow);\n    │                                                               ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:102:76\n    │\n102 │         _draw(cv, _entry(uint8(FrenArtIndex.FACE_TABLE[0])), -int256(CX), -int256(CY), slot, shadow);\n    │                                                                            ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:103:31\n    │\n103 │         _draw(cv, _entry(f), -int256(CX), -int256(CY), slot, shadow);\n    │                               ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:103:44\n    │\n103 │         _draw(cv, _entry(f), -int256(CX), -int256(CY), slot, shadow);\n    │                                            ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/FrenRenderer.sol:147:54\n    │\n147 │                     bytes memory out = new bytes(j - start);\n    │                                                      ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FrenRenderer.sol:146:21\n    │\n146 │                 if (k == i) {\n    │                     ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:232:41\n    │\n232 │         _draw(cv, _entry(f + 20 + bg), -int256(seed % 37), -int256((seed >> 8) % 37), slot, 0);\n    │                                         ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:232:61\n    │\n232 │         _draw(cv, _entry(f + 20 + bg), -int256(seed % 37), -int256((seed >> 8) % 37), slot, 0);\n    │                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:233:79\n    │\n233 │         _draw(cv, _entry(uint8(FrenArtIndex.FACE_TABLE[ch * FACES + face])), -int256(CX), -int256(CY), slot, 0);\n    │                                                                               ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:233:92\n    │\n233 │         _draw(cv, _entry(uint8(FrenArtIndex.FACE_TABLE[ch * FACES + face])), -int256(CX), -int256(CY), slot, 0);\n    │                                                                                            ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:234:36\n    │\n234 │         _draw(cv, _entry(f + ch), -int256(CX), -int256(CY), slot, 0);\n    │                                    ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:234:49\n    │\n234 │         _draw(cv, _entry(f + ch), -int256(CX), -int256(CY), slot, 0);\n    │                                                 ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:237:55\n    │\n237 │         if (hat != 0) _draw(cv, _entry(f + 2 + hat), -int256(CX), -int256(CY), slot, 0);\n    │                                                       ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:237:68\n    │\n237 │         if (hat != 0) _draw(cv, _entry(f + 2 + hat), -int256(CX), -int256(CY), slot, 0);\n    │                                                                    ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:239:57\n    │\n239 │         if (item != 0) _draw(cv, _entry(f + 4 + item), -int256(CX), -int256(CY), slot, 0);\n    │                                                         ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:239:70\n    │\n239 │         if (item != 0) _draw(cv, _entry(f + 4 + item), -int256(CX), -int256(CY), slot, 0);\n    │                                                                      ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:253:25\n    │\n253 │             int256 yy = int256(y) + dy;\n    │                         ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:254:40\n    │\n254 │             bool row = yy >= 0 && yy < int256(N);\n    │                                        ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:262:32\n    │\n262 │                     int256 a = int256(x) + dx;\n    │                                ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:263:36\n    │\n263 │                     int256 b = a + int256(n);\n    │                                    ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:265:29\n    │\n265 │                     if (b > int256(N)) b = int256(N);\n    │                             ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:265:44\n    │\n265 │                     if (b > int256(N)) b = int256(N);\n    │                                            ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:266:36\n    │\n266 │                     uint256 base = uint256(yy) * N;\n    │                                    ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:268:35\n    │\n268 │                         cv[base + uint256(xx)] = bytes1(uint8(c));\n    │                                   ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:268:57\n    │\n268 │                         cv[base + uint256(xx)] = bytes1(uint8(c));\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/FrenRenderer.sol:278:32\n    │\n278 │             b[at + i] = bytes1(uint8(v >> (8 * i)));\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/FrenRenderer.sol:303:20\n    │\n303 │             while (written < len) {\n    │                    ━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\n","passed":true},{"durationMs":3493,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 2 tests for test/LaunchPart1.t.sol:LaunchPart1Test\n[PASS] test_ConstructorsRejectValue() (gas: 1219068)\n[PASS] test_FactoryDeploysExactChunksInOrderWithoutArguments() (gas: 10960319)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.16ms (4.82ms CPU time)\n\nRan 9 tests for test/FrenRenderer.t.sol:FrenRendererTest\n[PASS] test_AllChunksPassFloorAndMatchIndex() (gas: 246751667)\n[PASS] test_AllEntriesRetainOriginalBytes() (gas: 5155043)\n[PASS] test_GasEstimateDetectsCodeDepositOverTransactionCap() (gas: 3248)\n[PASS] test_LaunchesFitTransactions() (gas: 64422)\nLogs:\n  launch 1 gas estimate (with calldata): 11630392\n  launch 2 gas estimate (with calldata): 10849576\n  launch 3 gas estimate (with calldata): 14978744\n\n[PASS] test_MatchesTheReference() (gas: 55012869)\n[PASS] test_RejectsCombosOutsideTheArt() (gas: 11302473)\n[PASS] test_SameAsTheLaunchRenderer() (gas: 912959390)\n[PASS] test_TakesOnlyThisArt() (gas: 624702)\n[PASS] test_TokenURIIsCheapEnoughToRead() (gas: 13073396)\nLogs:\n  tokenURI gas: 13067389\n\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 3.29s (4.10s CPU time)\n\nRan 2 test suites in 3.29s (3.29s CPU time): 11 tests passed, 0 failed, 0 skipped (11 total tests)\n","passed":true},{"durationMs":146,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":29,\"README.md\":60,\"foundry.toml\":22,\"launch.json\":14,\"script/art/chunks.py\":133,\"script/art/data/expected.json\":32,\"script/art/data/facetable.bin\":2,\"script/art/data/layers/bg0.bin\":59,\"script/art/data/layers/bg1.bin\":44,\"script/art/data/layers/bg2.bin\":44,\"script/art/data/layers/bg3.bin\":4,\"script/art/data/layers/bg4.bin\":2,\"script/art/data/layers/bg5.bin\":1,\"script/art/data/layers/bg6.bin\":6,\"script/art/data/layers/bg7.bin\":13,\"script/art/data/layers/bg8.bin\":20,\"script/art/data/layers/bg9.bin\":4,\"script/art/data/layers/coat0.bin\":10,\"script/art/data/layers/coat1.bin\":10,\"script/art/data/layers/coat2.bin\":10,\"script/art/data/layers/face0.bin\":36,\"script/art/data/layers/face1.bin\":29,\"script/art/data/layers/face10.bin\":34,\"script/art/data/layers/face11.bin\":33,\"script/art/data/layers/face12.bin\":36,\"script/art/data/layers/face13.bin\":19,\"script/art/data/layers/face14.bin\":20,\"script/art/data/layers/face15.bin\":20,\"script/art/data/layers/face16.bin\":19,\"script/art/data/layers/face17.bin\":20,\"script/art/data/layers/face18.bin\":19,\"script/art/data/layers/face19.bin\":21,\"script/art/data/layers/face2.bin\":34,\"script/art/data/layers/face20.bin\":20,\"script/art/data/layers/face21.bin\":19,\"script/art/data/layers/face22.bin\":19,\"script/art/data/layers/face23.bin\":20,\"script/art/data/layers/face24.bin\":20,\"script/art/data/layers/face25.bin\":19,\"script/art/data/layers/face26.bin\":23,\"script/art/data/layers/face27.bin\":23,\"script/art/data/layers/face28.bin\":23,\"script/art/data/layers/face29.bin\":23,\"script/art/data/layers/face3.bin\":31,\"script/art/data/layers/face30.bin\":23,\"script/art/data/layers/face31.bin\":23,\"script/art/data/layers/face32.bin\":26,\"script/art/data/layers/face33.bin\":24,\"script/art/data/layers/face34.bin\":23,\"script/art/data/layers/face35.bin\":22,\"script/art/data/layers/face36.bin\":22,\"script/art/data/layers/face37.bin\":24,\"script/art/data/layers/face38.bin\":22,\"script/art/data/layers/face4.bin\":31,\"script/art/data/layers/face5.bin\":29,\"script/art/data/layers/face6.bin\":29,\"script/art/data/layers/face7.bin\":28,\"script/art/data/layers/face8.bin\":29,\"script/art/data/layers/face9.bin\":30,\"script/art/data/layers/hat0.bin\":3,\"script/art/data/layers/hat1.bin\":5,\"script/art/data/layers/item0.bin\":2,\"script/art/data/layers/item1.bin\":1,\"script/art/data/layers/item10.bin\":1,\"script/art/data/layers/item11.bin\":1,\"script/art/data/layers/item12.bin\":1,\"script/art/data/layers/item13.bin\":1,\"script/art/data/layers/item14.bin\":3,\"script/art/data/layers/item2.bin\":3,\"script/art/data/layers/item3.bin\":1,\"script/art/data/layers/item4.bin\":1,\"script/art/data/layers/item5.bin\":2,\"script/art/data/layers/item6.bin\":3,\"script/art/data/layers/item7.bin\":1,\"script/art/data/layers/item8.bin\":1,\"script/art/data/layers/item9.bin\":1,\"script/art/data/manifest.json\":329,\"script/art/data/palette.bin\":7,\"script/art/data/tables.bin\":2,\"script/art/test_chunks.py\":40,\"src/FrenArtChunks.sol\":2305,\"src/FrenArtIndex.sol\":33,\"src/FrenRenderer.sol\":321,\"test/FrenRenderer.t.sol\":249,\"test/LaunchPart1.t.sol\":58,\"test/ref/FrenRendererRef.sol\":313},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"372cc84b0a69853930c721141a9fc5b27e6d667025ef35c532c7692a960b80e1","verifiedTreeHash":"442d1e5bdebc265114ae45e89ec5e5f1e8ea41dd","verifierVersion":"0.1.0+e6140b7a"},{"checks":[{"durationMs":88323,"exitCode":0,"name":"build","output":"Compiling 36 files with Solc 0.8.30\nSolc 0.8.30 finished in 88.21s\nCompiler run successful!\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n   ╭▸ src/FrenRenderer.sol:61:41\n   │\n61 │             if (cs[k].codehash != want) revert BadArt();\n   │                                         ━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:101:49\n    │\n101 │         _draw(cv, _entry(f + 20 + PENDING_BG), -int256(seed % 37), -int256((seed >> 8) % 37), slot, 0);\n    │                                                 ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:101:69\n    │\n101 │         _draw(cv, _entry(f + 20 + PENDING_BG), -int256(seed % 37), -int256((seed >> 8) % 37), slot, 0);\n    │                                                                     ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:102:63\n    │\n102 │         _draw(cv, _entry(uint8(FrenArtIndex.FACE_TABLE[0])), -int256(CX), -int256(CY), slot, shadow);\n    │                                                               ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:102:76\n    │\n102 │         _draw(cv, _entry(uint8(FrenArtIndex.FACE_TABLE[0])), -int256(CX), -int256(CY), slot, shadow);\n    │                                                                            ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:103:31\n    │\n103 │         _draw(cv, _entry(f), -int256(CX), -int256(CY), slot, shadow);\n    │                               ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:103:44\n    │\n103 │         _draw(cv, _entry(f), -int256(CX), -int256(CY), slot, shadow);\n    │                                            ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/FrenRenderer.sol:146:21\n    │\n146 │                 if (k == i) {\n    │                     ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FrenRenderer.sol:147:54\n    │\n147 │                     bytes memory out = new bytes(j - start);\n    │                                                      ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:232:41\n    │\n232 │         _draw(cv, _entry(f + 20 + bg), -int256(seed % 37), -int256((seed >> 8) % 37), slot, 0);\n    │                                         ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:232:61\n    │\n232 │         _draw(cv, _entry(f + 20 + bg), -int256(seed % 37), -int256((seed >> 8) % 37), slot, 0);\n    │                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:233:79\n    │\n233 │         _draw(cv, _entry(uint8(FrenArtIndex.FACE_TABLE[ch * FACES + face])), -int256(CX), -int256(CY), slot, 0);\n    │                                                                               ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:233:92\n    │\n233 │         _draw(cv, _entry(uint8(FrenArtIndex.FACE_TABLE[ch * FACES + face])), -int256(CX), -int256(CY), slot, 0);\n    │                                                                                            ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:234:36\n    │\n234 │         _draw(cv, _entry(f + ch), -int256(CX), -int256(CY), slot, 0);\n    │                                    ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:234:49\n    │\n234 │         _draw(cv, _entry(f + ch), -int256(CX), -int256(CY), slot, 0);\n    │                                                 ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:237:55\n    │\n237 │         if (hat != 0) _draw(cv, _entry(f + 2 + hat), -int256(CX), -int256(CY), slot, 0);\n    │                                                       ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:237:68\n    │\n237 │         if (hat != 0) _draw(cv, _entry(f + 2 + hat), -int256(CX), -int256(CY), slot, 0);\n    │                                                                    ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:239:57\n    │\n239 │         if (item != 0) _draw(cv, _entry(f + 4 + item), -int256(CX), -int256(CY), slot, 0);\n    │                                                         ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:239:70\n    │\n239 │         if (item != 0) _draw(cv, _entry(f + 4 + item), -int256(CX), -int256(CY), slot, 0);\n    │                                                                      ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:253:25\n    │\n253 │             int256 yy = int256(y) + dy;\n    │                         ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:254:40\n    │\n254 │             bool row = yy >= 0 && yy < int256(N);\n    │                                        ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:262:32\n    │\n262 │                     int256 a = int256(x) + dx;\n    │                                ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:263:36\n    │\n263 │                     int256 b = a + int256(n);\n    │                                    ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:265:29\n    │\n265 │                     if (b > int256(N)) b = int256(N);\n    │                             ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:265:44\n    │\n265 │                     if (b > int256(N)) b = int256(N);\n    │                                            ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:266:36\n    │\n266 │                     uint256 base = uint256(yy) * N;\n    │                                    ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:268:35\n    │\n268 │                         cv[base + uint256(xx)] = bytes1(uint8(c));\n    │                                   ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:268:57\n    │\n268 │                         cv[base + uint256(xx)] = bytes1(uint8(c));\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/FrenRenderer.sol:278:32\n    │\n278 │             b[at + i] = bytes1(uint8(v >> (8 * i)));\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/FrenRenderer.sol:303:20\n    │\n303 │             while (written < len) {\n    │                    ━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\n","passed":true},{"durationMs":2275,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 6 tests for test/LaunchPart1.t.sol:LaunchPart1Test\n[PASS] testFuzz_ValueRejectionLeavesBothAddressesReusable(bytes32,uint128) (runs: 256, μ: 11920741, ~: 11921250)\nLogs:\n  Bound result 105071248302426481287649066\n\n[PASS] test_ConstructorsRejectValue() (gas: 1219236)\n[PASS] test_Create2CollisionCannotOverwriteEitherChunk() (gas: 11055295)\n[PASS] test_FactoryDeploysExactChunksInOrderWithoutArguments() (gas: 10961210)\n[PASS] test_PreFundedCreate2AddressesStillDeployWithZeroEndowment() (gas: 11002856)\n[PASS] test_ValueRejectionEdgesLeaveBothAddressesReusable() (gas: 23876603)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 59.27ms (65.21ms CPU time)\n\nRan 12 tests for test/FrenRenderer.t.sol:FrenRendererTest\n[PASS] testFuzz_RejectsAnyChangedLaunch1Byte(uint256,uint8) (runs: 256, μ: 697712, ~: 697919)\nLogs:\n  Bound result 1\n  Bound result 21134\n  Bound result 4199\n\n[PASS] test_AllChunksPassFloorAndMatchIndex() (gas: 246751667)\n[PASS] test_AllEntriesRetainOriginalBytes() (gas: 5155065)\n[PASS] test_GasEstimateDetectsCodeDepositOverTransactionCap() (gas: 3248)\n[PASS] test_LaunchesFitTransactions() (gas: 64561)\nLogs:\n  launch 1 gas estimate (with calldata): 11630392\n  launch 2 gas estimate (with calldata): 10849576\n  launch 3 gas estimate (with calldata): 14978744\n\n[PASS] test_MatchesTheReference() (gas: 55012869)\n[PASS] test_RejectsCombosOutsideTheArt() (gas: 11302495)\n[PASS] test_RejectsLaunch1PrefixTailTruncationAndAppendedData() (gas: 2471709)\n[PASS] test_RejectsMissingOrDuplicatedLaunch1Chunks() (gas: 1761394)\n[PASS] test_SameAsTheLaunchRenderer() (gas: 916531492)\n[PASS] test_TakesOnlyThisArt() (gas: 624804)\n[PASS] test_TokenURIIsCheapEnoughToRead() (gas: 13073418)\nLogs:\n  tokenURI gas: 13067389\n\nSuite result: ok. 12 passed; 0 failed; 0 skipped; finished in 1.45s (1.86s CPU time)\n\nRan 2 tests for test/LaunchPart1Invariant.t.sol:LaunchPart1InvariantTest\n[PASS]\nLaunchPart1InvariantTest invariants:\n[PASS] invariant_ArtRemainsExactlyThePinnedLaunch1Data\n[PASS] invariant_EtherIsConservedAcrossActorsAndChunks\n LaunchPart1InvariantTest invariants (runs: 256, calls: 16384, reverts: 0)\n\n╭--------------------+-----------+-------+---------+----------╮\n| Contract           | Selector  | Calls | Reverts | Discards |\n+=============================================================+\n| LaunchPart1Handler | callChunk | 5496  | 0       | 0        |\n|--------------------+-----------+-------+---------+----------|\n| LaunchPart1Handler | readChunk | 5536  | 0       | 0        |\n|--------------------+-----------+-------+---------+----------|\n| LaunchPart1Handler | sendEther | 5352  | 0       | 0        |\n╰--------------------+-----------+-------+---------+----------╯\n\nLogs:\n  Bound result 0\n  Bound result 1\n  Bound result 16384\n  Bound result 1\n  Bound result 3\n  Bound result 424242\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 3797897120786441963\n  Bound result 0\n  Bound result 0\n  Bound result 4280296542905869\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 3\n  Bound result 4\n  Bound result 1\n  Bound result 0\n  Bound result 49805780452529080311\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 3\n  Bound result 100\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 6012\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 3\n  Bound result 22\n  Bound result 1\n  Bound result 0\n  Bound result 319794850178\n  Bound result 1\n  Bound result 0\n  Bound result 317170\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 0\n  Bound result 45555597883216997954\n  Bound result 0\n  Bound result 3\n  Bound result 1\n  Bound result 2\n  Bound result 4550\n  Bound result 0\n  Bound result 1\n  Bound result 5756\n  Bound result 1\n  Bound result 0\n  Bound result 5764\n  Bound result 0\n  Bound result 0\n  Bound result 5120\n  Bound result 1\n  Bound result 0\n  Bound result 6\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 15\n  Bound result 1\n  Bound result 0\n  Bound result 3583\n  Bound result 0\n  Bound result 0\n  Bound result 826\n  Bound result 1\n  Bound result 0\n  Bound result 24139\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 1\n  Bound result 44015950866991245959\n  Bound result 1\n  Bound result 0\n  Bound result 6274\n  Bound result 1\n  Bound result 3\n  Bound result 224\n  Bound result 1\n  Bound result 3\n  Bound result 3465\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 47813847987777710076\n  Bound result 1\n  Bound result 0\n  Bound result 333\n  Bound result 1\n  Bound result 0\n  Bound result 3173\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 3\n  Bound result 1\n  Bound result 2\n  Bound result 31959522303104631216\n  Bound result 0\n  Bound result 1\n  Bound result 224\n  Bound result 1\n  Bound result 2\n  Bound result 166477\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 1\n  Bound result 2800590298239446220\n  Bound result 0\n  Bound result 1\n  Bound result 1379344946570544931\n  Bound result 1\n  Bound result 0\n  Bound result 1825625345370\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 3\n  Bound result 3925\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 3\n  Bound result 6175\n  Bound result 0\n  Bound result 3\n  Bound result 91855331175513698857\n  Bound result 0\n  Bound result 0\n  Bound result 6982221\n  Bound result 1\n  Bound result 2\n  Bound result 2236\n  Bound result 1\n  Bound result 0\n  Bound result 1174319353202021367\n  Bound result 1\n  Bound result 3\n  Bound result 3358\n  Bound result 0\n  Bound result 3\n  Bound result 64\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 0\n  Bound result 25\n\n[PASS] test_CallEdgesAndRepeatedCallsKeepArtAndBalances() (gas: 1219884)\nLogs:\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 99999999999999999999\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 99999999999999999999\n  Bound result 1\n  Bound result 1\n  Bound result 0\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 2.18s (2.18s CPU time)\n\nRan 3 test suites in 2.18s (3.69s CPU time): 20 tests passed, 0 failed, 0 skipped (20 total tests)\n","passed":true},{"durationMs":52,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":29,\"README.md\":60,\"foundry.toml\":22,\"script/art/chunks.py\":133,\"script/art/data/expected.json\":32,\"script/art/data/facetable.bin\":2,\"script/art/data/layers/bg0.bin\":59,\"script/art/data/layers/bg1.bin\":44,\"script/art/data/layers/bg2.bin\":44,\"script/art/data/layers/bg3.bin\":4,\"script/art/data/layers/bg4.bin\":2,\"script/art/data/layers/bg5.bin\":1,\"script/art/data/layers/bg6.bin\":6,\"script/art/data/layers/bg7.bin\":13,\"script/art/data/layers/bg8.bin\":20,\"script/art/data/layers/bg9.bin\":4,\"script/art/data/layers/coat0.bin\":10,\"script/art/data/layers/coat1.bin\":10,\"script/art/data/layers/coat2.bin\":10,\"script/art/data/layers/face0.bin\":36,\"script/art/data/layers/face1.bin\":29,\"script/art/data/layers/face10.bin\":34,\"script/art/data/layers/face11.bin\":33,\"script/art/data/layers/face12.bin\":36,\"script/art/data/layers/face13.bin\":19,\"script/art/data/layers/face14.bin\":20,\"script/art/data/layers/face15.bin\":20,\"script/art/data/layers/face16.bin\":19,\"script/art/data/layers/face17.bin\":20,\"script/art/data/layers/face18.bin\":19,\"script/art/data/layers/face19.bin\":21,\"script/art/data/layers/face2.bin\":34,\"script/art/data/layers/face20.bin\":20,\"script/art/data/layers/face21.bin\":19,\"script/art/data/layers/face22.bin\":19,\"script/art/data/layers/face23.bin\":20,\"script/art/data/layers/face24.bin\":20,\"script/art/data/layers/face25.bin\":19,\"script/art/data/layers/face26.bin\":23,\"script/art/data/layers/face27.bin\":23,\"script/art/data/layers/face28.bin\":23,\"script/art/data/layers/face29.bin\":23,\"script/art/data/layers/face3.bin\":31,\"script/art/data/layers/face30.bin\":23,\"script/art/data/layers/face31.bin\":23,\"script/art/data/layers/face32.bin\":26,\"script/art/data/layers/face33.bin\":24,\"script/art/data/layers/face34.bin\":23,\"script/art/data/layers/face35.bin\":22,\"script/art/data/layers/face36.bin\":22,\"script/art/data/layers/face37.bin\":24,\"script/art/data/layers/face38.bin\":22,\"script/art/data/layers/face4.bin\":31,\"script/art/data/layers/face5.bin\":29,\"script/art/data/layers/face6.bin\":29,\"script/art/data/layers/face7.bin\":28,\"script/art/data/layers/face8.bin\":29,\"script/art/data/layers/face9.bin\":30,\"script/art/data/layers/hat0.bin\":3,\"script/art/data/layers/hat1.bin\":5,\"script/art/data/layers/item0.bin\":2,\"script/art/data/layers/item1.bin\":1,\"script/art/data/layers/item10.bin\":1,\"script/art/data/layers/item11.bin\":1,\"script/art/data/layers/item12.bin\":1,\"script/art/data/layers/item13.bin\":1,\"script/art/data/layers/item14.bin\":3,\"script/art/data/layers/item2.bin\":3,\"script/art/data/layers/item3.bin\":1,\"script/art/data/layers/item4.bin\":1,\"script/art/data/layers/item5.bin\":2,\"script/art/data/layers/item6.bin\":3,\"script/art/data/layers/item7.bin\":1,\"script/art/data/layers/item8.bin\":1,\"script/art/data/layers/item9.bin\":1,\"script/art/data/manifest.json\":329,\"script/art/data/palette.bin\":7,\"script/art/data/tables.bin\":2,\"script/art/test_chunks.py\":40,\"src/FrenArtChunks.sol\":2305,\"src/FrenArtIndex.sol\":33,\"src/FrenRenderer.sol\":321,\"test/FrenRenderer.t.sol\":306,\"test/LaunchPart1.t.sol\":129,\"test/LaunchPart1Invariant.t.sol\":135,\"test/ref/FrenRendererRef.sol\":313},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"3ef09b17bf16b07175ca68a710a1f053447143496dd608879ca671ba92604d57","verifiedTreeHash":"e5dd118f0ebc4478c392b0e47edd1ff26e2b6e09","verifierVersion":"0.1.0+e6140b7a"},{"checks":[{"durationMs":90599,"exitCode":0,"name":"build","output":"Compiling 35 files with Solc 0.8.30\nSolc 0.8.30 finished in 90.47s\nCompiler run successful!\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n   ╭▸ src/FrenRenderer.sol:61:41\n   │\n61 │             if (cs[k].codehash != want) revert BadArt();\n   │                                         ━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:101:49\n    │\n101 │         _draw(cv, _entry(f + 20 + PENDING_BG), -int256(seed % 37), -int256((seed >> 8) % 37), slot, 0);\n    │                                                 ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:101:69\n    │\n101 │         _draw(cv, _entry(f + 20 + PENDING_BG), -int256(seed % 37), -int256((seed >> 8) % 37), slot, 0);\n    │                                                                     ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:102:63\n    │\n102 │         _draw(cv, _entry(uint8(FrenArtIndex.FACE_TABLE[0])), -int256(CX), -int256(CY), slot, shadow);\n    │                                                               ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:102:76\n    │\n102 │         _draw(cv, _entry(uint8(FrenArtIndex.FACE_TABLE[0])), -int256(CX), -int256(CY), slot, shadow);\n    │                                                                            ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:103:31\n    │\n103 │         _draw(cv, _entry(f), -int256(CX), -int256(CY), slot, shadow);\n    │                               ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:103:44\n    │\n103 │         _draw(cv, _entry(f), -int256(CX), -int256(CY), slot, shadow);\n    │                                            ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe 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/FrenRenderer.sol:146:21\n    │\n146 │                 if (k == i) {\n    │                     ━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/FrenRenderer.sol:147:54\n    │\n147 │                     bytes memory out = new bytes(j - start);\n    │                                                      ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:232:41\n    │\n232 │         _draw(cv, _entry(f + 20 + bg), -int256(seed % 37), -int256((seed >> 8) % 37), slot, 0);\n    │                                         ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:232:61\n    │\n232 │         _draw(cv, _entry(f + 20 + bg), -int256(seed % 37), -int256((seed >> 8) % 37), slot, 0);\n    │                                                             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:233:79\n    │\n233 │         _draw(cv, _entry(uint8(FrenArtIndex.FACE_TABLE[ch * FACES + face])), -int256(CX), -int256(CY), slot, 0);\n    │                                                                               ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:233:92\n    │\n233 │         _draw(cv, _entry(uint8(FrenArtIndex.FACE_TABLE[ch * FACES + face])), -int256(CX), -int256(CY), slot, 0);\n    │                                                                                            ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:234:36\n    │\n234 │         _draw(cv, _entry(f + ch), -int256(CX), -int256(CY), slot, 0);\n    │                                    ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:234:49\n    │\n234 │         _draw(cv, _entry(f + ch), -int256(CX), -int256(CY), slot, 0);\n    │                                                 ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:237:55\n    │\n237 │         if (hat != 0) _draw(cv, _entry(f + 2 + hat), -int256(CX), -int256(CY), slot, 0);\n    │                                                       ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:237:68\n    │\n237 │         if (hat != 0) _draw(cv, _entry(f + 2 + hat), -int256(CX), -int256(CY), slot, 0);\n    │                                                                    ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:239:57\n    │\n239 │         if (item != 0) _draw(cv, _entry(f + 4 + item), -int256(CX), -int256(CY), slot, 0);\n    │                                                         ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:239:70\n    │\n239 │         if (item != 0) _draw(cv, _entry(f + 4 + item), -int256(CX), -int256(CY), slot, 0);\n    │                                                                      ━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:253:25\n    │\n253 │             int256 yy = int256(y) + dy;\n    │                         ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:254:40\n    │\n254 │             bool row = yy >= 0 && yy < int256(N);\n    │                                        ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:262:32\n    │\n262 │                     int256 a = int256(x) + dx;\n    │                                ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:263:36\n    │\n263 │                     int256 b = a + int256(n);\n    │                                    ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:265:29\n    │\n265 │                     if (b > int256(N)) b = int256(N);\n    │                             ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:265:44\n    │\n265 │                     if (b > int256(N)) b = int256(N);\n    │                                            ━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'int256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:266:36\n    │\n266 │                     uint256 base = uint256(yy) * N;\n    │                                    ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:268:35\n    │\n268 │                         cv[base + uint256(xx)] = bytes1(uint8(c));\n    │                                   ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint256' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/FrenRenderer.sol:268:57\n    │\n268 │                         cv[base + uint256(xx)] = bytes1(uint8(c));\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/FrenRenderer.sol:278:32\n    │\n278 │             b[at + i] = bytes1(uint8(v >> (8 * i)));\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/FrenRenderer.sol:303:20\n    │\n303 │             while (written < len) {\n    │                    ━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\n","passed":true},{"durationMs":1393,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 2 tests for test/LaunchPart1.t.sol:LaunchPart1Test\n[PASS] test_ConstructorsRejectValue() (gas: 1219068)\n[PASS] test_FactoryDeploysExactChunksInOrderWithoutArguments() (gas: 10960319)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 1.01ms (1.22ms CPU time)\n\nRan 9 tests for test/FrenRenderer.t.sol:FrenRendererTest\n[PASS] test_AllChunksPassFloorAndMatchIndex() (gas: 246751667)\n[PASS] test_AllEntriesRetainOriginalBytes() (gas: 5155043)\n[PASS] test_GasEstimateDetectsCodeDepositOverTransactionCap() (gas: 3248)\n[PASS] test_LaunchesFitTransactions() (gas: 64422)\nLogs:\n  launch 1 gas estimate (with calldata): 11630392\n  launch 2 gas estimate (with calldata): 10849576\n  launch 3 gas estimate (with calldata): 14978744\n\n[PASS] test_MatchesTheReference() (gas: 55012869)\n[PASS] test_RejectsCombosOutsideTheArt() (gas: 11302473)\n[PASS] test_SameAsTheLaunchRenderer() (gas: 912959390)\n[PASS] test_TakesOnlyThisArt() (gas: 624702)\n[PASS] test_TokenURIIsCheapEnoughToRead() (gas: 13073396)\nLogs:\n  tokenURI gas: 13067389\n\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 1.30s (1.65s CPU time)\n\nRan 2 test suites in 1.30s (1.30s CPU time): 11 tests passed, 0 failed, 0 skipped (11 total tests)\n","passed":true},{"durationMs":58,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":29,\"README.md\":60,\"foundry.toml\":22,\"script/art/chunks.py\":133,\"script/art/data/expected.json\":32,\"script/art/data/facetable.bin\":2,\"script/art/data/layers/bg0.bin\":59,\"script/art/data/layers/bg1.bin\":44,\"script/art/data/layers/bg2.bin\":44,\"script/art/data/layers/bg3.bin\":4,\"script/art/data/layers/bg4.bin\":2,\"script/art/data/layers/bg5.bin\":1,\"script/art/data/layers/bg6.bin\":6,\"script/art/data/layers/bg7.bin\":13,\"script/art/data/layers/bg8.bin\":20,\"script/art/data/layers/bg9.bin\":4,\"script/art/data/layers/coat0.bin\":10,\"script/art/data/layers/coat1.bin\":10,\"script/art/data/layers/coat2.bin\":10,\"script/art/data/layers/face0.bin\":36,\"script/art/data/layers/face1.bin\":29,\"script/art/data/layers/face10.bin\":34,\"script/art/data/layers/face11.bin\":33,\"script/art/data/layers/face12.bin\":36,\"script/art/data/layers/face13.bin\":19,\"script/art/data/layers/face14.bin\":20,\"script/art/data/layers/face15.bin\":20,\"script/art/data/layers/face16.bin\":19,\"script/art/data/layers/face17.bin\":20,\"script/art/data/layers/face18.bin\":19,\"script/art/data/layers/face19.bin\":21,\"script/art/data/layers/face2.bin\":34,\"script/art/data/layers/face20.bin\":20,\"script/art/data/layers/face21.bin\":19,\"script/art/data/layers/face22.bin\":19,\"script/art/data/layers/face23.bin\":20,\"script/art/data/layers/face24.bin\":20,\"script/art/data/layers/face25.bin\":19,\"script/art/data/layers/face26.bin\":23,\"script/art/data/layers/face27.bin\":23,\"script/art/data/layers/face28.bin\":23,\"script/art/data/layers/face29.bin\":23,\"script/art/data/layers/face3.bin\":31,\"script/art/data/layers/face30.bin\":23,\"script/art/data/layers/face31.bin\":23,\"script/art/data/layers/face32.bin\":26,\"script/art/data/layers/face33.bin\":24,\"script/art/data/layers/face34.bin\":23,\"script/art/data/layers/face35.bin\":22,\"script/art/data/layers/face36.bin\":22,\"script/art/data/layers/face37.bin\":24,\"script/art/data/layers/face38.bin\":22,\"script/art/data/layers/face4.bin\":31,\"script/art/data/layers/face5.bin\":29,\"script/art/data/layers/face6.bin\":29,\"script/art/data/layers/face7.bin\":28,\"script/art/data/layers/face8.bin\":29,\"script/art/data/layers/face9.bin\":30,\"script/art/data/layers/hat0.bin\":3,\"script/art/data/layers/hat1.bin\":5,\"script/art/data/layers/item0.bin\":2,\"script/art/data/layers/item1.bin\":1,\"script/art/data/layers/item10.bin\":1,\"script/art/data/layers/item11.bin\":1,\"script/art/data/layers/item12.bin\":1,\"script/art/data/layers/item13.bin\":1,\"script/art/data/layers/item14.bin\":3,\"script/art/data/layers/item2.bin\":3,\"script/art/data/layers/item3.bin\":1,\"script/art/data/layers/item4.bin\":1,\"script/art/data/layers/item5.bin\":2,\"script/art/data/layers/item6.bin\":3,\"script/art/data/layers/item7.bin\":1,\"script/art/data/layers/item8.bin\":1,\"script/art/data/layers/item9.bin\":1,\"script/art/data/manifest.json\":329,\"script/art/data/palette.bin\":7,\"script/art/data/tables.bin\":2,\"script/art/test_chunks.py\":40,\"src/FrenArtChunks.sol\":2305,\"src/FrenArtIndex.sol\":33,\"src/FrenRenderer.sol\":321,\"test/FrenRenderer.t.sol\":249,\"test/LaunchPart1.t.sol\":58,\"test/ref/FrenRendererRef.sol\":313},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":25414,"exitCode":0,"name":"slither","output":"[medium/medium] uninitialized-local at src/FrenRenderer.sol:97: FrenRenderer.silhouette(uint256).slot (src/FrenRenderer.sol#97) is a local variable never initialized\n[medium/medium] uninitialized-local at src/FrenRenderer.sol:142: FrenRenderer._name(uint256,string).start (src/FrenRenderer.sol#142) is a local variable never initialized\n[medium/medium] uninitialized-local at src/FrenRenderer.sol:143: FrenRenderer._name(uint256,string).k (src/FrenRenderer.sol#143) is a local variable never initialized\n[low/medium] missing-zero-check at src/FrenRenderer.sol:53: FrenRenderer.constructor(address,address,address,address,address,address,address).c7 (src/FrenRenderer.sol#53) lacks a zero-check on :\n[low/medium] missing-zero-check at src/FrenRenderer.sol:53: FrenRenderer.constructor(address,address,address,address,address,address,address).c4 (src/FrenRenderer.sol#53) lacks a zero-check on :\n[low/medium] missing-zero-check at src/FrenRenderer.sol:53: FrenRenderer.constructor(address,address,address,address,address,address,address).c3 (src/FrenRenderer.sol#53) lacks a zero-check on :\n[low/medium] missing-zero-check at src/FrenRenderer.sol:53: FrenRenderer.constructor(address,address,address,address,address,address,address).c6 (src/FrenRenderer.sol#53) lacks a zero-check on :\n[low/medium] missing-zero-check at src/FrenRenderer.sol:53: FrenRenderer.constructor(address,address,address,address,address,address,address).c1 (src/FrenRenderer.sol#53) lacks a zero-check on :\n[low/medium] missing-zero-check at src/FrenRenderer.sol:53: FrenRenderer.constructor(address,address,address,address,address,address,address).c5 (src/FrenRenderer.sol#53) lacks a zero-check on :\n[low/medium] missing-zero-check at src/FrenRenderer.sol:53: FrenRenderer.constructor(address,address,address,address,address,address,address).c2 (src/FrenRenderer.sol#53) lacks a zero-check on :","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"5a36d26de9c5159852e641cad36decca76837986e2fd928d1792599864dec781","verifiedTreeHash":"db7c7ca086b86655f8964d370ed20d4dec3badbd","verifierVersion":"0.1.0+e6140b7a"}]}