{"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":"fe768074-11d6-47ad-81bb-91960cbb9fdf","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"dedf0bf271c12bcdb580a5208814c26ffaa452d046f02692e4d83713c42b22c9","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":"82b233f6afac6a430949c64f74b143e5157ed51a58687ff2aa0d4e76ac3d0ee7","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":"b592fe361e151ad700e473390c6a5194e2f649e9c1194910e33da31db994591e","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":"4ab24d6ae486ef7f01116f8134e601de514a8e8770a8b351f05243155a8e42cc","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":"68dd8274dc05138dc0d2f101184305218f01b23fd94848cb87ac9937a6e88dac","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":"ae832a38041c80892effeb41699277504826cf5032420dbee554b6669a052922","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":"4350b87e8ff06496145b9940d7970cb73ece846464b4dd983d53097b3fa1fe4b","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":"2ce84c2a8e19de93fedbce0e420e9b4f624751d275ae9355ffdfd3b948d8faff","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"1b1fde72e78678a024bc01494448d507535b7ea76de633e3f61ccfe162ff27a3","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 2 of 3 of the IMD6900 Frens on-chain art, exactly as it is in the repository: the data contracts FrenArtChunk3 and FrenArtChunk4 (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 1 and 3 (README.md).","parentJobId":null,"planHash":"dcb709a1b20d94d83d07e44b5ef2e41c4e0b8f77f3c4275bf72653a5e560dbb8","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"fe768074-11d6-47ad-81bb-91960cbb9fdf","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-820-frenartchunk3-frenartchunk4"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"51073","feedbackHash":"4f8b9f1462597e69920987abb71f3c6eeb14bc4b7ac90aa073d02b7c8312703b","nodeKey":"adapt_contract_project","submissionHash":"dedf0bf271c12bcdb580a5208814c26ffaa452d046f02692e4d83713c42b22c9","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51729","feedbackHash":"1a18adbaa02799cf1dc68eea4e78ca598bc86ca91311e92acf8b2983843ce48d","nodeKey":"adapt_contract_project","submissionHash":"ba653510ca8ab4a6fb72dd4385b81c60f321251d68763850f170ef2cb46e5154","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51002","feedbackHash":"56c2dfa6bfdebe8d5a71b62c9e91c943188a168a21880c799cbda5d21aaf767c","nodeKey":"adapt_contract_project","submissionHash":"e84dc12844453fd7b97736e3465654a2bc49efc405cd99241e67a1f1136d2135","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52223","feedbackHash":"2634cd6079bbdcd9c9a92ad49936f1dbc969a5aba8b57ff37184c2c7d19ffe12","nodeKey":"audit_economics","submissionHash":"82b233f6afac6a430949c64f74b143e5157ed51a58687ff2aa0d4e76ac3d0ee7","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52222","feedbackHash":"22623e3abf9fe137bdf23ddf54b322694bb4d43cb5b425b44d7dc1e62d740f06","nodeKey":"audit_flow","submissionHash":"b592fe361e151ad700e473390c6a5194e2f649e9c1194910e33da31db994591e","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51004","feedbackHash":"1f65e0114b33355e068fe763ce751fa7517ff5c16857f715cf9491c30146633d","nodeKey":"audit_imported_code","submissionHash":"4ab24d6ae486ef7f01116f8134e601de514a8e8770a8b351f05243155a8e42cc","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51130","feedbackHash":"7582d66e61e9b597ef9fb263335fce97a0c7f35ba4b69d33a7cca079b0bb89e0","nodeKey":"audit_judge","submissionHash":"4705cb258155b215e25b23214b5e5b17024d82d8471799bde9d41ebcc9020578","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51740","feedbackHash":"2f2ab619980ac0b13ddf200b92c8cff157512d44ce77e0d1895c8c698fcef2ab","nodeKey":"audit_judge","submissionHash":"3fd683b21f7f38af8c5aa7fc59943a7ea261f2e65ee0a7595cf4f85ceec55c16","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52166","feedbackHash":"f194d092ca74be95a48d9c579cc36797e58891e050a4d0a0d0e2ec98f78f2c9a","nodeKey":"audit_judge","submissionHash":"68dd8274dc05138dc0d2f101184305218f01b23fd94848cb87ac9937a6e88dac","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52210","feedbackHash":"c80595721fea052dc006e5cc42133e389ad9fb142eda1af28a4cc6fc339aed20","nodeKey":"audit_math","submissionHash":"ae832a38041c80892effeb41699277504826cf5032420dbee554b6669a052922","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52207","feedbackHash":"87d8c10e13890a75d50bab11f54e0c2c6d346a05582561ffbd5b5e740c3dde6e","nodeKey":"audit_permissions","submissionHash":"4350b87e8ff06496145b9940d7970cb73ece846464b4dd983d53097b3fa1fe4b","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52009","feedbackHash":"ed05d8381db37eadd4f6978e0ea5562cb7899d2d085d0d2da16d4a44a9420f31","nodeKey":"manifest","submissionHash":"2ce84c2a8e19de93fedbce0e420e9b4f624751d275ae9355ffdfd3b948d8faff","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51290","feedbackHash":"2d35cb3b7be29b6d00e8721c1e4da1c000403f786d59958e825d933f54d53330","nodeKey":"manifest","submissionHash":"5dbf4f87b477c93cb294565c43cf16fa070af9f905bbe5a239433e834374cf25","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51549","feedbackHash":"b47e1ed9a64a30c6dcd4e4aff7c3692f465086a599cca53e2690920f29aade56","nodeKey":"manifest","submissionHash":"d449e8234c2cebbad1017328f2ed32bf050f482d3c07f93315e506ed53af0517","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51731","feedbackHash":"37e4a2bcffe3f048c924c3060f56ade418fa0174bd04771d042ccc92b0943e26","nodeKey":"write_foundry_tests","submissionHash":"1b1fde72e78678a024bc01494448d507535b7ea76de633e3f61ccfe162ff27a3","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51440","feedbackHash":"2d437153d836e3c82701c4402bc4f9da0a86003247e56411db36324ecd99389f","nodeKey":"write_foundry_tests","submissionHash":"78288b5dcee21e61456e028f1ba2ff3ff8c434ee7b5c53f6c82ced9e022828a4","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51559","feedbackHash":"428b8514a2a291da49a40635f6b9ead9b7825fea4e2f79cf68348d8f98d25410","nodeKey":"write_foundry_tests","submissionHash":"82ffb08562bf1b0996a7ae1a16f70b1e9c62dc0d53b3b531a8fd81c1bc1a023a","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"c2e7a7f8f6734b8cfe9c9b0950e600acadfc90fbccdcaca4259e00adf02424a4","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"b126f80dc1897945085cd47360fe5dc322a6db82104dcb53fd8d703b25a8c655","device":"6960837f8e61d811","findings":[{"description":"Launch 2 cannot pass the supplied protected admission check with the exact required art. Contracts.protected.t.sol scans the complete deployed runtime, skipping PUSH immediate bytes but continuing past STOP. FrenArtChunk4 contains 234 scanner-visible bytes equal to 0xf4, 0xf2 or 0xff, beginning with 0xf4 at runtime offset 3912. These are unreachable art data after the leading STOP. FrenArtChunk3 has zero rejected positions. Changing the art would violate the assignment and the renderer's pinned code hash; changing only the constructor while returning identical runtime cannot resolve admission. This compatibility blocker needs an upstream admission-policy or scope resolution. No production source or protected check was changed.","line":1162,"path":"src/FrenArtChunks.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {FrenArtChunk3, FrenArtChunk4} from \"src/FrenArtChunks.sol\";\n\ncontract Launch2AdmissionProof is Test {\n    function test_ExactLaunch2MustPassProtectedOpcodeScan() public {\n        address third = address(new FrenArtChunk3());\n        address fourth = address(new FrenArtChunk4());\n        _check(third, 3);\n        _check(fourth, 4);\n    }\n\n    function _check(address chunk, uint256 number) private {\n        bytes memory code = chunk.code;\n        assertGt(code.length, 0, \"missing runtime\");\n        assertLe(code.length, 24_576, \"runtime exceeds EIP-170\");\n        uint256 rejected;\n        uint256 first;\n        // Same PUSH skipping and forbidden-byte policy as the supplied protected check.\n        for (uint256 j; j < code.length; ++j) {\n            uint8 op = uint8(code[j]);\n            if (op >= 0x60 && op <= 0x7f) {\n                j += op - 0x5f;\n                continue;\n            }\n            if (op == 0xf4 || op == 0xf2 || op == 0xff) {\n                if (rejected == 0) first = j;\n                ++rejected;\n            }\n        }\n        emit log_named_uint(\"chunk\", number);\n        emit log_named_uint(\"rejected positions\", rejected);\n        emit log_named_uint(\"first rejected offset\", first);\n        assertEq(rejected, 0, \"exact launch runtime fails protected admission\");\n    }\n}","reproduction":"Save proof as test/scratch/Launch2AdmissionProof.t.sol and run forge test --offline --out test/scratch/out --cache-path test/scratch/cache --match-path test/scratch/Launch2AdmissionProof.t.sol -vv. The test deploys FrenArtChunk3 then FrenArtChunk4, with no arguments or ETH. Expected: both exact runtimes satisfy the protected zero-forbidden-position requirement. Actual: chunk 3 logs 0 rejected positions; chunk 4 logs 234, first offset 3912, and fails with \"exact launch runtime fails protected admission: 234 != 0\". This command was run and exited 1. Independently, the supplied protected test was copied unchanged into scratch and run with chain ID 1, factory 0x1111111111111111111111111111111111111111, the two compiled creation bytecodes, salts bytes32(3) and bytes32(4), and their calculated CREATE2 addresses supplied through process environment variables. Both deployments succeeded; test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes failed with \"forbidden application opcode\" (exit 1). No vm.setEnv was used. Failing reproductions are kept outside the delivered passing suite; the full self-contained source is attached here.","severity":"high","title":"Required FrenArtChunk4 runtime is rejected by the protected launch admission scan"}],"hash":"1b1fde72e78678a024bc01494448d507535b7ea76de633e3f61ccfe162ff27a3","nodeId":"451faae4-c5e1-481a-8519-49a01b1e6f0b","outcome":"completed","summary":"Added prefunded deployment rollback/retry coverage for both chunks. Production code remains unchanged.\n\n`forge build` and `forge test` pass: **26 tests**, including invariants.\n\nLaunch admission remains blocked by chunk 4’s protected opcode scan. Recorded the reproduced failure and self-contained proof in [.imd-findings.json](.imd-findings.json).","treeHash":"45ad299fe07eaa6a698693823e1708f7d4350bff","usage":{"cachedInputTokens":1118976,"inputTokens":75662,"model":"gpt-6-astra","outputTokens":9363,"runtime":"codex","turns":6,"wallClockMs":334149}},{"artifacts":[],"attempt":1,"bundleHash":"eaf372fd6e36c090366d78fe17b09a530796f9f59fab7250836114289a2c296c","device":"6ce0cec991d77172","findings":[],"hash":"2ce84c2a8e19de93fedbce0e420e9b4f624751d275ae9355ffdfd3b948d8faff","nodeId":"c34ec7cf-fc45-4b34-8f07-6a55b594e444","outcome":"completed","summary":"Updated only [launch.json](/home/worker/.identitymd-5/work/fe768074-11d6-47ad-81bb-91960cbb9fdf/c34ec7cf-fc45-4b34-8f07-6a55b594e444/launch.json), clarifying notes while preserving `FrenArtChunk3`, then `FrenArtChunk4`, with empty constructor arguments.\n\nValidation passed: supplied schema, compiled constructor ABIs, `forge build`, and all 11 repository tests.\n\nThe protected scanner conflict remains: it flags chunk 4’s required art bytes after `STOP`. Resolving that is outside the manifest-only scope.","treeHash":"b537a979026cfdb09dd10016cb44ce6cf899b66d","usage":{"cachedInputTokens":333440,"inputTokens":26814,"model":"gpt-6-astra","outputTokens":4722,"runtime":"codex","turns":4,"wallClockMs":238444}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"4ece7e789ed37442","findings":[{"citation":"resolved","description":"FrenArtChunk4 returns the required STOP-prefixed art as runtime. The supplied Contracts.protected.t.sol runtime check scans the entire runtime, skipping PUSH immediates but continuing after STOP. It rejects 234 occurrences of 0xf4 in chunk 4, beginning at runtime offset 3912. Chunk 3 has none. Consequently the specified launch cannot pass this required admission check. These bytes are unreachable art data, not executable DELEGATECALL instructions. FrenArtIndex.CHUNK_HASHES pins the exact runtime, so modifying it would contradict the brief and make FrenRenderer reject it. Resolve the conflict in the upstream admission policy for these exact data contracts; a change to art or hashes requires a separate scope decision. Merges the scanner findings from the independent tester and all four specialist areas. Severity is medium for a reproducible admission/availability failure; no exploit or loss of funds is established.","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 {FrenArtChunk3, FrenArtChunk4} from \"src/FrenArtChunks.sol\";\n\n/// @notice Launch 2 as the factory deploys it (constructors only, no arguments, no value), checked with the exact\n///         runtime traversal of the pinned protected floor (Contracts.protected.t.sol,\n///         test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes). The floor walks the whole runtime, skipping\n///         only PUSH immediates; it does not stop at the leading STOP, so the art bytes after it are read as opcodes.\n///         FrenArtChunk4's coat layers contain palette index 244 (0xf4 = DELEGATECALL) at 234 scanner-visible\n///         positions, so the floor rejects the launch. Fails on the tree as it is; passes once launch 2's runtime\n///         bytes carry no scanner-visible 0xf4 / 0xf2 / 0xff.\ncontract Launch2AdmissionScanTest is Test {\n    function _scan(bytes memory code) internal pure returns (uint256 count, uint256 first) {\n        for (uint256 j; j < code.length; ++j) {\n            uint8 op = uint8(code[j]);\n            if (op >= 0x60 && op <= 0x7f) {\n                j += op - 0x5f;\n                continue;\n            }\n            if (op == 0xf4 || op == 0xf2 || op == 0xff) {\n                if (count == 0) first = j;\n                ++count;\n            }\n        }\n    }\n\n    function _check(address app, string memory name) internal {\n        bytes memory code = app.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        (uint256 count, uint256 first) = _scan(code);\n        emit log_named_uint(string.concat(name, \" scanner-visible forbidden bytes\"), count);\n        emit log_named_uint(string.concat(name, \" first at runtime offset\"), first);\n        assertEq(count, 0, string.concat(name, \": protected floor rejects a forbidden application opcode\"));\n    }\n\n    function test_Launch2RuntimePassesTheProtectedOpcodeScan() public {\n        address c3 = address(new FrenArtChunk3());\n        address c4 = address(new FrenArtChunk4());\n        _check(c3, \"FrenArtChunk3\");\n        _check(c4, \"FrenArtChunk4\");\n    }\n}","reproduction":"With Forge 1.8.3 and solc 0.8.26, save the attached proof as test/scratch/Proof_2f77541cc402.t.sol and run forge test --offline --out test/scratch/out --cache-path test/scratch/cache --match-path test/scratch/Proof_2f77541cc402.t.sol -vv. It deploys new FrenArtChunk3() followed by new FrenArtChunk4(), with no arguments and zero value, then applies the supplied protected traversal: scan the entire runtime, skip PUSH1..PUSH32 immediates, reject 0xf4/0xf2/0xff. Expected: zero rejected positions in both required runtimes. Actual, reproduced by running all four supplied proofs against the current tree: chunk 3 has 23,479 bytes and zero rejected positions; chunk 4 has 20,539 bytes and 234 rejected positions, first at runtime offset 3912 (0xf4), then 3922 and 3932. The attached proof fails with \"FrenArtChunk4: protected floor rejects a forbidden application opcode: 234 != 0\". The first failing byte is the ninth byte of the quoted literal. All 234 hits are palette index 244 in coat0/coat1/coat2 (78 runs each). The embedded test captures the current protected policy; if the resolution changes that policy instead of the art, its traversal must be updated to the approved policy. Independently, the unchanged supplied Contracts.protected.t.sol also failed with \"forbidden application opcode\" after successfully deploying both chunks through CREATE2: IMD_PROJECT_FACTORY=0x1111111111111111111111111111111111111111, IMD_PROJECT_CHAIN_ID=1, IMD_PROJECT_COUNT=2, CODE_0/1 equal to the compiled creation bytecode, SALT_0/1 equal to bytes32(uint256(3))/bytes32(uint256(4)), ADDRESS_0=0xb9443776b5f99a0fd9d999bd7ead039c20ff130e and ADDRESS_1=0xd62d5be0ddf691e59ae0cce61bda6894aa9fe146 (all variable names use the IMD_PROJECT_ prefix). With IMD_PROJECT_COUNT=1 and chunk 3 alone, this exact protected test passed.","severity":"medium","snippet":"            hex\"f82f00060001f802f401f52f00050001f804f401f52e00050001f805f401f52d00040001f806f401f52d00040001f805f401f801f401f52c00030001f801f70a\"","title":"Exact FrenArtChunk4 runtime is incompatible with the protected admission scanner"}],"hash":"3fd683b21f7f38af8c5aa7fc59943a7ea261f2e65ee0a7595cf4f85ceec55c16","nodeId":"e5272f6f-a63b-43f8-becf-2ac2144fee03","outcome":"completed","summary":"Saved [.imd-findings.json](/root/.identitymd-1975/work/fe768074-11d6-47ad-81bb-91960cbb9fdf/e5272f6f-a63b-43f8-becf-2ac2144fee03/.imd-findings.json) with **one merged medium finding** and an executed proof: the protected scanner rejects 234 unreachable art bytes in chunk 4, blocking admission.\n\nAll 24 repository tests passed. All four supplied proofs and the unchanged protected test reproduced the blocker.\n\n| Coverage | Result |\n|---|---|\n| Chunk 3 constructor | Holds: exact hash, bounded size, nonpayable |\n| Chunk 4 constructor | Finding 1: required runtime fails admission |\n| Both runtimes | Hold: execution halts at STOP |\n| Renderer handoff and data | Hold: hashes, ordering and all 36 layers checked |\n| Manifest | Holds: correct contracts, order and empty arguments |\n\nDropped the stale test allegation and unsupported service-failure claims. Production factory behavior, policy gas ceiling and attestation implementation remain unverified.\n\nTemporary files were removed. Existing repository files remain unchanged.","treeHash":null,"usage":{"cachedInputTokens":1911936,"inputTokens":92135,"model":"gpt-6-astra","outputTokens":8586,"runtime":"codex","turns":6,"wallClockMs":314861}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"f009de0ce52c7b3a","findings":[{"citation":"resolved","description":"The protected floor this launch is judged against (Contracts.protected.t.sol, test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes) walks every byte of each deployed runtime, skips only PUSH1..PUSH32 immediates, and fails on any 0xf4 / 0xf2 / 0xff. It does not stop at the leading STOP. FrenArtChunk4's runtime (20,539 bytes, keccak 0x4412839e...45a5aa) contains 234 bytes of 0xf4, none of them inside a PUSH immediate as the floor counts them: the first is at code offset 3912 (byte 8 of the hex line cited, `...f802f401f5...`). All 234 are the run colour index 244 (FrenRenderer.SLOT0, coat shade 0) in the three coat layers: 78 each in coat0 (art offset 3896), coat1 (4734) and coat2 (5572). FrenArtChunk3 has no 0xf4/0xf2/0xff byte at all and passes.\n\nPermission view (my area): these bytes are not a real escape path. Byte 0 is STOP, the contract has no other entry, so no caller can reach offset 3912 and nothing is ever delegate-called. The defect is that the launch as briefed is not admissible: the floor fails, so launch 2 is never deployed, and launch 3's FrenRenderer constructor (which takes chunk 3 and 4 as static addresses and reverts BadArt unless their code hashes match FrenArtIndex.CHUNK_HASHES) can never be built. Gas already spent on launch 1 (about 12.6M gas by the repository's own budget) buys nothing until this is resolved.\n\nThe repository already knows: README.md and ADAPTATION.md record it as unresolved, and test/FrenArtLaunch2.t.sol (test_ExactLaunch2ArtIsRejectedByCurrentProtectedScan) asserts count == 234, so a green `forge test` here means the blocker is still present, not that the launch is ready. It is reported again because it is still true of the tree under review and still blocks the deliverable.\n\nIt cannot be fixed inside the brief: any change to chunk 4's bytes changes its code hash, hence FrenArtIndex (CHUNK_HASHES, CHUNK_SIZES, INDEX) and the launch-3 renderer. That needs a scope decision, one of: (a) the launch policy accepts STOP-prefixed data contracts whose tail is unreachable (no code change); (b) chunk 4 is re-encoded. For (b) there is an encoding that needs no renderer logic change and leaves chunks 1, 2, 3, 5 and 6 byte-identical (none of them contains a 0xf4/0xf2/0xff byte): have script/art/chunks.py emit a zero-length run `00 61` before each run whose colour byte is 0xf4. FrenRenderer._draw draws nothing for a zero-length run and does not advance x, while the floor reads 0x61 as PUSH2 and skips the following (count, 0xf4) pair. Simulated off-chain on the repository's data: chunk 4 becomes 21,007 bytes, the floor's scan finds 0 forbidden bytes, and every one of its 24 layers decodes to the same pixels. Not built or tested on chain here; chunk 7 (launch 3: 14 rejected bytes, first at offset 7671, all inside the palette, 11 of them 0xff) is not run data and needs its own treatment.","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 {FrenArtChunk3, FrenArtChunk4} from \"src/FrenArtChunks.sol\";\n\n/// @dev Launch 2 exactly as briefed (FrenArtChunk3, then FrenArtChunk4, no constructor arguments), checked with the\n///      evm_contracts protected floor's own runtime rule: present, within EIP-170, and no 0xf4 / 0xf2 / 0xff byte\n///      outside a PUSH immediate. Fails today on FrenArtChunk4 (234 bytes of 0xf4, the first at code offset 3912).\ncontract Launch2ProtectedFloorTest is Test {\n    address[] private applications;\n\n    function setUp() public {\n        applications.push(address(new FrenArtChunk3()));\n        applications.push(address(new FrenArtChunk4()));\n    }\n\n    function test_launch2RuntimePassesTheProtectedOpcodeFloor() public view {\n        for (uint256 i; i < applications.length; ++i) {\n            bytes memory code = applications[i].code;\n            assertGt(code.length, 0, \"missing runtime\");\n            assertLe(code.length, 24_576, \"runtime exceeds EIP-170\");\n            for (uint256 j; j < code.length; ++j) {\n                uint8 op = uint8(code[j]);\n                if (op >= 0x60 && op <= 0x7f) {\n                    j += op - 0x5f;\n                    continue;\n                }\n                assertTrue(op != 0xf4 && op != 0xf2 && op != 0xff, \"forbidden application opcode\");\n            }\n        }\n    }\n}","reproduction":"State: the tree as is, solc 0.8.26, forge 1.8.3. Deploy FrenArtChunk3 then FrenArtChunk4 with no constructor arguments and zero value, then run the protected floor's loop over each runtime.\n1) Proof test below: `forge test --match-path test/scratch/Launch2ProtectedFloor.t.sol` -> [FAIL: forbidden application opcode] test_launch2RuntimePassesTheProtectedOpcodeFloor().\n2) The unmodified protected file, copied to test/scratch with IMD_PROJECT_FACTORY=0x1111111111111111111111111111111111111111, IMD_PROJECT_CHAIN_ID=1, IMD_PROJECT_COUNT=2, IMD_PROJECT_CODE_0/1 = the creation code of FrenArtChunk3/4 (28,320 and 24,814 bytes), IMD_PROJECT_SALT_0/1 = 3 and 4 as bytes32, IMD_PROJECT_ADDRESS_0/1 = the CREATE2 predictions (0xb9443776b5f99a0fd9d999bd7ead039c20ff130e, 0xd62d5be0ddf691e59ae0cce61bda6894aa9fe146): both deployments succeed, then [FAIL: forbidden application opcode] test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes().\nExpected: the launch's runtimes pass the floor. Actual: FrenArtChunk4 fails at code offset 3912 (0xf4), 234 such bytes in total; FrenArtChunk3 alone passes (0 bytes).","severity":"high","snippet":"            hex\"f82f00060001f802f401f52f00050001f804f401f52e00050001f805f401f52d00040001f806f401f52d00040001f805f401f801f401f52c00030001f801f70a\"","title":"Launch 2 cannot pass the evm_contracts protected floor: FrenArtChunk4's runtime holds 234 bytes of 0xf4 (DELEGATECALL) that the floor rejects"},{"citation":"resolved","description":"Asymmetry between the two halves of each data contract. The constructor is nonpayable, so deployment with value reverts. The runtime's only reachable instruction is STOP at byte 0, which succeeds for every caller, selector and msg.value, so the contract takes ETH and has no path that sends it out (no owner, no call, no selfdestruct reachable). \"Calling it does nothing\" is true of state but not of value. No role is involved and nobody profits; the only loser is whoever sends ETH to a chunk by mistake, and the loss is permanent.\n\nThis is the brief's intended design (STOP, then the bytes) and ADAPTATION.md already records it, so it is a trust assumption to keep documented, not something to change within this launch: any rejecting prefix changes the pinned code hashes of all seven chunks. If the chunks are regenerated anyway for the finding above, that would be the moment to decide whether to keep STOP.","line":783,"path":"src/FrenArtChunks.sol","reproduction":"Deploy FrenArtChunk3 (or 4). `chunk.call{value: 1 ether}(hex\"deadbeef\")` returns (true, \"\") and chunk.balance == 1 ether; any later call, e.g. `withdraw()`, also returns (true, \"\") with the balance unchanged. Deploying the same creation code with 1 wei reverts. Expected of a contract that \"does nothing\": value is refused, as at construction. Actual: 1 ether is locked for good. The existing test_Launch2RetainsDocumentedEthSink and test_Launch2ConstructorsRejectValue in test/FrenArtLaunch2.t.sol show both sides.","severity":"info","snippet":"///         (FrenArtIndex says what is where). Calling it does nothing.","title":"Trust note: the chunks accept ETH on any call and can never release it, while their constructors reject it"},{"citation":"resolved","description":"Each chunk's constructor returns the art itself as the runtime, so what is deployed is not what solc reports as the contract's runtime. out/FrenArtChunks.sol/FrenArtChunk3.json and FrenArtChunk4.json both carry deployedBytecode 0x5f80fdfea164736f6c634300081a000a (16 bytes, keccak 0x19735bdf4d52c6f889cfd85f70fad899c9f4372c41ff8aa853bf043831e21b36), while the deployed runtimes are 23,479 and 20,539 bytes with keccak 0xd73ecfd9...02c9a8 and 0x4412839e...45a5aa. Where the release attestation records 'runtime hashes' from the build, launch 2 shows two different contracts with one identical runtime hash that matches neither deployed contract; only the creation-bytecode hash ties the launch to the art. A check done on the build's runtime artifact sees none of the art (it would, for instance, find no 0xf4 byte, unlike the rehearsed deployment in the finding above), and explorer verification that compares compiled runtime with on-chain code cannot match.\n\nNothing to change in the contracts: this is how a constructor-returned data contract works. It matters for who is trusted between launches: launch 3 writes the launch-2 addresses as static arguments, and the only on-chain check of what sits there is FrenRenderer's constructor (BadArt on a wrong hash, which fails closed). Before those addresses are written into launch 3's manifest, compare the deployed code hashes with FrenArtIndex.CHUNK_HASHES directly (`cast codehash`), not with anything derived from the runtime artifact.","line":1155,"path":"src/FrenArtChunks.sol","reproduction":"`forge build`, then `forge inspect FrenArtChunk3 deployedBytecode` and `forge inspect FrenArtChunk4 deployedBytecode`: both print 0x5f80fdfea164736f6c634300081a000a. Deploy each with no arguments: `chunk3.code.length == 23479`, `chunk3.codehash == 0xd73ecfd95e853d3bf20224d02e30889477ac2627bc1970c5e6b0ca5ef202c9a8`; `chunk4.code.length == 20539`, `chunk4.codehash == 0x4412839e8ffb01f255ce07ec70fc6c55a67a78f4365ae2a71eaa4f4d8645a5aa`. Expected by a verifier comparing build runtime with chain runtime: equal. Actual: keccak(artifact runtime) = 0x19735bdf...e21b36 for both, equal to neither.","severity":"info","snippet":"            return(add(code, 32), mload(code))","title":"Trust gap: the compiler's runtime artifact for both chunks is the same 16-byte revert stub, so a runtime hash taken from the build does not bind the art that gets deployed"},{"citation":"resolved","description":"Not a defect; the coverage record for the judge. Ran: forge build and the 11 existing tests (all pass), the unmodified protected floor against chunks 3 and 4 (fails, finding 1), and an off-chain rebuild of all seven chunks and the INDEX from script/art/data. No Slither or Mythril.\n\nEntry points:\n- FrenArtChunk3 constructor(): holds. No arguments, nonpayable (1 wei reverts), assigns no role, writes no storage, makes no call; returns 23,479 bytes equal to STOP + the generator's chunk 3 from script/art/data; code hash equals FrenArtIndex.CHUNK_HASHES[2]; runtime <= 24,576 and creation code 28,320 <= 49,152. Passes the protected floor (no 0xf4/0xf2/0xff byte anywhere).\n- FrenArtChunk3 runtime, any call (any selector, empty calldata, with or without value): holds for permissions, see finding 2 for value. PC 0 is STOP; no storage, no outgoing call, no reachable DELEGATECALL/CALLCODE/SELFDESTRUCT, so the code and its hash cannot change after deployment and no caller class is treated differently.\n- FrenArtChunk4 constructor(): finding 1. Same shape as chunk 3 (no arguments, nonpayable, no roles; 20,539 bytes equal to the generator's chunk 4; hash equals CHUNK_HASHES[3]; creation code 24,814 bytes), but the runtime it returns is rejected by the floor.\n- FrenArtChunk4 runtime, any call: holds for permissions (the 234 bytes of 0xf4 sit behind STOP and are unreachable), finding 2 for value.\n- FrenRenderer constructor and _entry as they touch chunks 3 and 4 (launch 3, read only to follow the trust between launches): holds. Slots are checked by code hash and by position, so anyone's byte-identical deployment is equivalent and anything else reverts BadArt; an EIP-7702 delegated account's hash is that of its 23-byte designator and cannot match. The 36 INDEX entries pointing into chunk 3 (12: faces 25-36) and chunk 4 (24: faces 37-38, coat0-2, hat0-1, item0-14, bg0-1) are contiguous and end exactly at each chunk's last byte.\n- launch.json: not present yet (a later assignment), so the order and the empty constructorArgs could not be checked against it: unreached.\n\nGuides. Access Control: there is no role, modifier, initializer, upgrade path, approval or outgoing call in either contract, so inconsistent guards, unprotected initialization, escalation, confused deputy and proxy/delegatecall abuse have nothing to act on; the factory's own access control is outside this repository and was not reviewed. Asymmetry: constructor vs runtime on value (finding 2); chunk 3 vs chunk 4 under the floor (finding 1); build runtime vs deployed runtime (finding 3); generated source vs script/art/data (identical for all seven chunks and the INDEX); the test's scan vs the floor's scan (same traversal). One stale comment outside this launch: FrenArtIndex.CHUNK_SIZES says the renderer checks the chunks' sizes, but FrenRenderer never reads it (the hash check covers size; only the tests use it). Trust Gap: no value flows, fees, admin setters or in-flight balances exist, so the access x economics and access x asymmetry seams reduce to findings 2 and 3 and to the cross-launch dependency described in finding 1.","line":1487,"path":"src/FrenArtChunks.sol","reproduction":"Coverage record, no failing input. To re-check the rows: `forge test` (11 pass); deploy FrenArtChunk3 and compare `code` with 0x00 followed by layers face25..face36 from script/art/data/layers in order (23,479 bytes); the same for FrenArtChunk4 with face37, face38, coat0-2, hat0-1, item0-14, bg0, bg1 (20,539 bytes).","severity":"info","snippet":"            return(add(code, 32), mload(code))","title":"Coverage: Access Control, Trust Gap and Asymmetry passes over launch 2 (FrenArtChunk3, FrenArtChunk4)"}],"hash":"4350b87e8ff06496145b9940d7970cb73ece846464b4dd983d53097b3fa1fe4b","nodeId":"d492e61f-0b23-487d-b4ec-f2e7c960cf97","outcome":"completed","summary":"The review is written to `.imd-findings.json`: one high finding with a proof test, two info trust notes, and one info coverage record. No repository file was changed, and the scratch tests are removed.\n\n## Findings\n\n1. **High: launch 2 cannot pass the `evm_contracts` protected floor** (`src/FrenArtChunks.sol:1226`).\n   - `FrenArtChunk4`'s runtime contains 234 bytes of `0xf4`, the first at code offset 3912. They are colour index 244 in the three coat layers, 78 each.\n   - The floor scans past the leading STOP and rejects them. `FrenArtChunk3` has no such byte and passes.\n   - I ran the unmodified protected file against both chunks, and a self-contained proof test: both fail with `forbidden application opcode`.\n   - The bytes are unreachable behind STOP, so this is an admission blocker, not a real escape path. Without launch 2, the launch-3 renderer cannot be built either.\n   - The repository already records this as unresolved, and `test_ExactLaunch2ArtIsRejectedByCurrentProtectedScan` asserts the 234. A green `forge test` therefore means the blocker is still present.\n   - It cannot be fixed inside the brief, because any change to chunk 4 changes its pinned hash. The decision is yours: either the launch policy exempts STOP-prefixed data contracts, or chunk 4 is re-encoded.\n   - One re-encoding needs no renderer logic change: emit a zero-length run `00 61` before each `0xf4` run. In an off-chain simulation chunk 4 becomes 21,007 bytes with 0 rejected bytes and identical pixels; I did not build or test it on chain.\n\n2. **Info: the chunks accept ETH on any call and can never release it**, while their constructors reject value (`src/FrenArtChunks.sol:783`). This is the briefed design and already documented; it is a trust assumption to keep visible.\n\n3. **Info: the compiler's runtime artifact does not bind the deployed art** (`src/FrenArtChunks.sol:1155`). Both chunks' build artifact is the same 16-byte revert stub, while the deployed runtimes are 23,479 and 20,539 bytes. Before launch 3's static addresses are written, compare the on-chain code hashes with `FrenArtIndex.CHUNK_HASHES` directly.\n\n4. **Info: coverage record** (`src/FrenArtChunks.sol:1487`), with one row per entry point and what each of the three guides had to act on.\n\n## Coverage\n\n| Entry point | Result | Reason |\n|---|---|---|\n| `FrenArtChunk3` constructor | holds | No arguments, nonpayable, no roles; returned bytes equal the generator's output from `script/art/data`; hash matches the index. |\n| `FrenArtChunk3` runtime, any call | holds for permissions; finding 2 for value | Only STOP is reachable; no storage, no outgoing call. |\n| `FrenArtChunk4` constructor | finding 1 | Same shape as chunk 3, but the runtime it returns is rejected by the floor. |\n| `FrenArtChunk4` runtime, any call | holds for permissions; finding 2 for value | The `0xf4` bytes sit behind STOP. |\n| `FrenRenderer` constructor and `_entry`, as they touch chunks 3 and 4 | holds | Chunks are checked by code hash and position, so a wrong chunk reverts `BadArt`. |\n| `launch.json` | unreached | Not present yet. |\n\nThe factory's own access control is outside this repository and was not reviewed. The 11 existing tests pass; no Slither or Mythril was run.","treeHash":null,"usage":{"cachedInputTokens":747832,"inputTokens":22,"model":"claude-fable-5-1","outputTokens":31953,"runtime":"claude","turns":16,"wallClockMs":580365}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"232b62e021f6f394","findings":[{"citation":"resolved","description":"Round-2 settlement of finding 00f0e0b8a1fb. Status: NOT fixed, and the author does not claim it is. The author's answer is 'disputed' only as to requiring a local fix; they re-ran the proof and concede the failure. I re-ran it on the revised tree and it fails exactly as before, so the finding stands as an open admission blocker. What changed this round: only launch.json (new) and tests (test/FrenArtLaunch2*.t.sol). src/ is byte-identical to the previous round, which is correct under the brief ('do not change them'). The earlier specialist low finding about a test pinning the blocker (test_ExactLaunch2ArtIsRejectedByCurrentProtectedScan asserting count == 234) is resolved: that test is gone and the suite no longer asserts the rejection. launch.json is schema-valid (kind/contracts/notes only, FrenArtChunk3 then FrenArtChunk4, constructorArgs [] for both, notes 737 chars) and its notes state the blocker honestly. The project suite passes (25 tests), which says nothing about admission. The defect itself: FrenArtChunk4's constructor returns STOP + 20,538 art bytes (runtime 20,539 bytes, keccak 0x4412839e8ffb01f255ce07ec70fc6c55a67a78f4365ae2a71eaa4f4d8645a5aa, the hash FrenArtIndex.CHUNK_HASHES pins). The supplied Contracts.protected.t.sol (test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes) scans the whole runtime, skips only PUSH1..PUSH32 immediates, does not stop at the leading STOP, and rejects 0xf4/0xf2/0xff. It finds 234 bytes of 0xf4 in chunk 4, first at runtime offset 3912 (9th byte of the quoted literal), then 3922, 3932; all are palette index 244 (FrenRenderer.SLOT0) in coat0/coat1/coat2, 78 each. FrenArtChunk3 has zero and passes alone. The bytes are unreachable data (pc 0 is STOP), so this is not an executable DELEGATECALL and no loss of funds is established; the impact is that launch 2 as specified cannot pass the required protected floor, and without chunk 4 at its exact hash launch 3's FrenRenderer constructor reverts BadArt. Severity stays medium (reproducible admission/availability failure). I agree with the author on the limits: no change inside this assignment can clear it. The scan result is a pure function of runtime bytes that the brief and CHUNK_HASHES fix, a constructor change returning the same bytes changes nothing, and editing the pinned protected test is not a policy resolution. Further author revisions of this repository will not settle this finding and should not be requested for it. What settles it is a decision by the requester/policy owner, one of: (a) the admission policy accepts these exact STOP-prefixed data runtimes (e.g. a runtime whose byte 0 is 0x00 has no reachable code, or an exception for the two pinned hashes), with the approved protected check and this proof's traversal updated to match; or (b) a separate scope decision to re-encode chunk 4 (and chunk 7 in launch 3, 14 hits), which changes CHUNK_HASHES and the renderer across launches and contradicts the current brief. Until one is made and evidenced, launch 2 must not be treated as admissible. Merges the same root cause reported this round by write_foundry_tests (d0694e60), audit_flow (2f77541c), audit_permissions (3c3602b1), audit_math (67d945e2) and audit_economics (460380ec); each of their proofs encodes the same traversal. Specialist info notes re-checked and not kept as defects: the STOP runtime accepts ETH with no way out (intended design, documented in ADAPTATION.md, covered by test_Launch2RetainsDocumentedEthSink); the compiler's deployedBytecode artifact is a 16-byte stub rather than the art (inherent to constructor-returned data contracts; whether any service step compares it is unverified, so it is a lead for the deployer, not a reproduced defect here). Coverage (mine): FrenArtChunk3 constructor - holds (no args, nonpayable, value reverts and rolls back, runtime 23,479 bytes <= 24,576, initcode 28,320 <= 49,152, codehash 0xd73ecfd9...02c9a8 equals the pinned hash, 0 scanner hits, unchanged protected floor passes wit","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 {FrenArtChunk3, FrenArtChunk4} from \"src/FrenArtChunks.sol\";\n\n/// @notice Launch 2 as the factory deploys it (constructors only, no arguments, no value), checked with the exact\n///         runtime traversal of the pinned protected floor (Contracts.protected.t.sol,\n///         test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes). The floor walks the whole runtime, skipping\n///         only PUSH immediates; it does not stop at the leading STOP, so the art bytes after it are read as opcodes.\n///         FrenArtChunk4's coat layers contain palette index 244 (0xf4 = DELEGATECALL) at 234 scanner-visible\n///         positions, so the floor rejects the launch. Fails on the tree as it is; passes once launch 2's runtime\n///         bytes carry no scanner-visible 0xf4 / 0xf2 / 0xff.\ncontract Launch2AdmissionScanTest is Test {\n    function _scan(bytes memory code) internal pure returns (uint256 count, uint256 first) {\n        for (uint256 j; j < code.length; ++j) {\n            uint8 op = uint8(code[j]);\n            if (op >= 0x60 && op <= 0x7f) {\n                j += op - 0x5f;\n                continue;\n            }\n            if (op == 0xf4 || op == 0xf2 || op == 0xff) {\n                if (count == 0) first = j;\n                ++count;\n            }\n        }\n    }\n\n    function _check(address app, string memory name) internal {\n        bytes memory code = app.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        (uint256 count, uint256 first) = _scan(code);\n        emit log_named_uint(string.concat(name, \" scanner-visible forbidden bytes\"), count);\n        emit log_named_uint(string.concat(name, \" first at runtime offset\"), first);\n        assertEq(count, 0, string.concat(name, \": protected floor rejects a forbidden application opcode\"));\n    }\n\n    function test_Launch2RuntimePassesTheProtectedOpcodeScan() public {\n        address c3 = address(new FrenArtChunk3());\n        address c4 = address(new FrenArtChunk4());\n        _check(c3, \"FrenArtChunk3\");\n        _check(c4, \"FrenArtChunk4\");\n    }\n}","reproduction":"Forge 1.8.3, solc 0.8.26, current tree (HEAD c5cfba2). (1) Copied the attached proof unchanged to test/scratch/Proof_00f0e0b8a1fb.t.sol and ran: forge test --offline --out test/scratch/out --cache-path test/scratch/cache --match-path test/scratch/Proof_00f0e0b8a1fb.t.sol -vv. It deploys new FrenArtChunk3() then new FrenArtChunk4() (no arguments, zero value) and applies the protected traversal (scan whole runtime, skip PUSH1..PUSH32 immediates, count 0xf4/0xf2/0xff). Expected: 0 rejected positions in both runtimes. Actual: FrenArtChunk3 = 0; FrenArtChunk4 = 234, first at runtime offset 3912; test fails with 'FrenArtChunk4: protected floor rejects a forbidden application opcode: 234 != 0'. (2) Copied the supplied Contracts.protected.t.sol unchanged to test/scratch and ran it with IMD_PROJECT_FACTORY=0x1111111111111111111111111111111111111111, IMD_PROJECT_CHAIN_ID=1, IMD_PROJECT_COUNT=2, IMD_PROJECT_CODE_0/1 = bytecode.object of FrenArtChunk3/FrenArtChunk4, IMD_PROJECT_SALT_0/1 = bytes32(3)/bytes32(4), IMD_PROJECT_ADDRESS_0 = 0xb9443776b5F99A0fD9D999Bd7eAd039C20ff130E, IMD_PROJECT_ADDRESS_1 = 0xD62d5Be0DDF691e59Ae0CCE61bDA6894aA9fe146. Expected: pass. Actual: both CREATE2 deployments succeed at the predicted addresses, then '[FAIL: forbidden application opcode] test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes()'. With IMD_PROJECT_COUNT=1 (chunk 3 only) the same unchanged test passes. The attached proof encodes the current protected policy: it passes once chunk 4's runtime has no scanner-visible 0xf4/0xf2/0xff; if the resolution is a policy change instead, its _scan must be updated to the approved policy.","severity":"medium","snippet":"            hex\"f82f00060001f802f401f52f00050001f804f401f52e00050001f805f401f52d00040001f806f401f52d00040001f805f401f801f401f52c00030001f801f70a\"","title":"Not fixed: exact FrenArtChunk4 runtime still fails the protected admission scanner (234 scanner-visible 0xf4 bytes); needs an upstream policy decision, not a code revision"}],"hash":"4705cb258155b215e25b23214b5e5b17024d82d8471799bde9d41ebcc9020578","nodeId":"e5272f6f-a63b-43f8-becf-2ac2144fee03","outcome":"completed","summary":"The finding I raised last round is not fixed: `FrenArtChunk4` still fails the protected admission scan, so launch 2 is still not admissible. I kept it as the single finding in `.imd-findings.json`, at medium, with the same proof attached.\n\n- **Proof re-run:** the attached proof, copied unchanged to `test/scratch/`, fails on the current tree with `FrenArtChunk4: protected floor rejects a forbidden application opcode: 234 != 0`. Chunk 3 has 0 rejected positions; chunk 4 has 234, the first at runtime offset 3912 (`0xf4`).\n- **Protected floor re-run:** the supplied `Contracts.protected.t.sol`, unchanged, deploys both chunks through CREATE2 and then fails with `forbidden application opcode`. With chunk 3 alone it passes.\n- **Author's answer:** they dispute only that a local fix is possible, and they concede the failure reproduces. I agree no change inside this assignment can clear it, because the brief and `FrenArtIndex.CHUNK_HASHES` pin every runtime byte.\n- **What settles it:** a decision by the requester or policy owner, not another revision of this repository. Either the admission policy accepts these STOP-prefixed data runtimes, with the protected check and proof updated to match, or a separate scope decision allows re-encoding chunk 4.\n\nThe five specialist reports of this blocker are merged into the one finding. The other specialist items were re-checked and not kept as defects:\n\n- **Test pinning the blocker (low):** resolved. The test that asserted `count == 234` is gone.\n- **ETH sink (info):** intended design, documented in `ADAPTATION.md` and covered by a test.\n- **Build runtime artifact is a 16-byte stub (low/info):** inherent to constructor-returned data contracts. Whether any service step compares it is unverified, so it stays a lead for the deployer.\n\nI found nothing new this round. The only changes since last round are `launch.json` and tests; `src/` is unchanged. `launch.json` is schema-valid, lists `FrenArtChunk3` then `FrenArtChunk4` with empty constructor arguments, and its notes state the blocker. The project suite passes (25 tests), which says nothing about admission.\n\nI changed no repository files; the scratch copies are removed.","treeHash":null,"usage":{"cachedInputTokens":381726,"inputTokens":12,"model":"claude-fable-5-1","outputTokens":8691,"runtime":"claude","turns":8,"wallClockMs":315701}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"560d41abbfbbcbfe","findings":[{"citation":"resolved","description":"The evm_contracts protected floor (Contracts.protected.t.sol, test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes) scans every deployed application's runtime byte by byte, skipping only PUSH1..PUSH32 immediates, and fails on any 0xf4 (DELEGATECALL), 0xf2 (CALLCODE) or 0xff (SELFDESTRUCT) at an opcode position. It does not know the leading STOP byte makes the rest unreachable. FrenArtChunk4's art is 20,538 raw bytes after the STOP; the three lab-coat layers (FrenArtIndex entries 39, 40, 41, at chunk offsets 3896, 4734 and 5572, 838 bytes each) are drawn with palette slot 244 = 0xf4 (SLOT0, the first coat shade in FrenRenderer), and 78 of those bytes per coat (234 in all, the first at code offset 3912, source line 1226) land at positions the scanner reads as opcodes. The floor therefore reports 'forbidden application opcode' for launch 2 and the launch cannot be admitted as it is. Nothing is unsafe at runtime (execution stops at byte 0), but the contract cannot be deployed through this launch, and because FrenRenderer's constructor (src/FrenRenderer.sol:61) only accepts chunks with the exact code hashes in FrenArtIndex.CHUNK_HASHES, any repair to chunk 4 changes its hash and requires regenerating FrenArtIndex (hashes, sizes, index) and so the renderer's bytecode in launch 3. FrenArtChunk3 passes the same scan. Minimal fix: in script/art/chunks.py, run this exact scan over each packed chunk and pack so no 0xf2/0xf4/0xff byte sits at an opcode position (for example move the renderer's SLOT0 slot range off 0xf2/0xf4/0xff, or escape those bytes in the stored data and un-escape in FrenRenderer._entry), then regenerate FrenArtChunks.sol and FrenArtIndex.sol and rerun forge test; also fix FrenArtChunk7 in the same regeneration (see the medium finding) so the hashes change only once.","line":1162,"path":"src/FrenArtChunks.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {FrenArtChunk3, FrenArtChunk4} from \"src/FrenArtChunks.sol\";\n\n/// @notice Launch 2 (FrenArtChunk3, FrenArtChunk4) must pass the evm_contracts protected floor, which scans each\n///         application's runtime linearly, skipping PUSH data, and rejects DELEGATECALL (0xf4), CALLCODE (0xf2) and\n///         SELFDESTRUCT (0xff) at any opcode position. FrenArtChunk4's art bytes put 0xf4 (palette slot 244, the\n///         first coat shade) at 234 such positions, so the floor rejects the launch. FrenArtChunk3 passes.\ncontract Chunk4ForbiddenOpcodesTest is Test {\n    function _forbiddenOpcodePositions(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) {\n                j += op - 0x5f;\n                continue;\n            }\n            if (op == 0xf4 || op == 0xf2 || op == 0xff) ++hits;\n        }\n    }\n\n    function test_launch2ChunksPassTheProtectedOpcodeScan() public {\n        address c3 = address(new FrenArtChunk3());\n        address c4 = address(new FrenArtChunk4());\n        assertGt(c3.code.length, 0);\n        assertGt(c4.code.length, 0);\n        assertLe(c3.code.length, 24_576);\n        assertLe(c4.code.length, 24_576);\n        assertEq(_forbiddenOpcodePositions(c3.code), 0, \"FrenArtChunk3 runtime has forbidden opcode bytes\");\n        assertEq(_forbiddenOpcodePositions(c4.code), 0, \"FrenArtChunk4 runtime has forbidden opcode bytes\");\n    }\n}","reproduction":"State: nothing deployed. Input: deploy FrenArtChunk4 with no constructor arguments (or run the protected test with IMD_PROJECT_COUNT=2, IMD_PROJECT_CODE_0 = creation code of FrenArtChunk3, IMD_PROJECT_CODE_1 = creation code of FrenArtChunk4, any factory/salts/predicted addresses). Expected: the runtime passes the floor's opcode scan (0 forbidden opcode positions) and launch 2 is admitted. Actual: the scan counts 234 positions holding 0xf4 (first at runtime offset 3912) and the protected test fails with 'forbidden application opcode'. Run locally: copy .imd/reads/protected/evm_contracts/Contracts.protected.t.sol under test/ and run it with those env vars: FAIL for count=2 (chunks 3+4) and for chunk 4 alone, PASS for chunk 3 alone. The attached proof test reproduces the scan without env vars and fails with 'FrenArtChunk4 runtime has forbidden opcode bytes: 234 != 0'.","severity":"high","snippet":"contract FrenArtChunk4 {","title":"FrenArtChunk4's runtime fails the launch's forbidden-opcode scan: 234 bytes read as DELEGATECALL (0xf4), so launch 2 is rejected"},{"citation":"resolved","description":"Out of this launch's two contracts but in the same generated file and in the fix path: the floor's scan over FrenArtChunk7's runtime finds 14 forbidden positions (one 0xf2 at offset 7671, source line 2277, and 0xff bytes from offset 7683 on, source line 2278 onward), all inside the 1024-byte palette entry that chunks.py places last. Launch 3 will be rejected by the same protected test. If the adapter repacks only chunk 4 now, the chunk hashes in FrenArtIndex and the renderer change again when chunk 7 is fixed, and launch 3's renderer must be built against the final hashes of all seven chunks, so the regeneration must cover both. Chunks 1, 2, 3, 5 and 6 pass the scan.","line":2155,"path":"src/FrenArtChunks.sol","reproduction":"Deploy FrenArtChunk7 with no arguments and run the floor's scan from Contracts.protected.t.sol over its code. Expected: 0 forbidden opcode positions. Actual: 14 (0xf2 at 7671, 0xff at 7683, 7684, 7685, 7813, ...), and the protected test with IMD_PROJECT_CODE_i = FrenArtChunk7's creation code fails with 'forbidden application opcode'.","severity":"medium","snippet":"contract FrenArtChunk7 {","title":"FrenArtChunk7 (launch 3) has the same forbidden-opcode bytes (0xf2, 0xff in the palette): repack it in the same regeneration as chunk 4"},{"citation":"resolved","description":"launchGas[] is taken from gasleft() around in-test calls in setUp, which under forge's default (non-isolated) metering does not charge the CREATE code-deposit cost (200 gas per byte, about 8.8M gas for chunks 3 and 4). The test logs 'launch 2 gas (with calldata): 940916' while the README states about 9.8M, and deploying FrenArtChunk3 and FrenArtChunk4 as real transactions on a local anvil (cancun) costs 5,195,161 and 4,557,284 gas. The real launch 2 total (about 9.75M in one transaction) is still under the 95% of 2^24 the test asserts, so the launch is not blocked, but the test passes for the wrong reason and would not catch an art change that pushed a launch over the cap or over the policy's gas ceiling. Fix: assert on an analytic bound (32000 + 200 * runtime length + 16 * initcode length per contract + 21000) or measure with vm.snapshotGas on isolated transactions.","line":147,"path":"test/FrenRenderer.t.sol","reproduction":"Run `forge test --match-test test_LaunchesFitTransactions -vv` (also with --isolate). Expected: the log for launch 2 near 9.8M gas as the README says. Actual: 940916. Cross-check: `cast send --create <FrenArtChunk3 creation code>` on anvil reports gasUsed 5195161, and the same for FrenArtChunk4 reports 4557284.","severity":"low","snippet":"            uint256 total = launchGas[i] + 21_000 + 16 * launchInitBytes[i];","title":"test_LaunchesFitTransactions measures about a tenth of the real launch gas, so it does not check the 2^24 cap"},{"citation":"resolved","description":"Each chunk's runtime starts with STOP, so any call, with any calldata and any value, succeeds and does nothing. There is no receive guard and no way to move funds out, so ETH mistakenly sent to FrenArtChunk3 or FrenArtChunk4 (for example by a wallet that pastes the chunk address instead of the frens contract) is irrecoverable. Expected for a data contract and shared by SSTORE2-style storage; reported as a trust note for the adapter, not a blocker. If wanted, the generator could prefix the data with a 'CALLVALUE PUSH1 0 JUMPI ... REVERT' stub instead of a bare STOP, at the cost of a different hash and index offsets.","line":1155,"path":"src/FrenArtChunks.sol","reproduction":"Deploy FrenArtChunk3; from any account call it with value 1 ether and calldata 0xdeadbeef. Expected: a data contract rejects value (revert). Actual: the call returns success with empty return data and the chunk's balance is 1 ether, with no function able to withdraw it (verified in a scratch Foundry test).","severity":"low","snippet":"            return(add(code, 32), mload(code))","title":"Ether sent to a chunk is accepted and locked forever"},{"citation":"resolved","description":"Read in full: src/FrenArtChunks.sol (FrenArtChunk1..7, constructors and data), src/FrenArtIndex.sol, src/FrenRenderer.sol, test/FrenRenderer.t.sol, script/art/chunks.py, README.md, foundry.toml, the pinned protected floor test and the Pashov guide. Not read: test/ref/FrenRendererRef.sol (the launch reference renderer, only compared against by the project's tests) and the vendored lib/ sources. Verified for FrenArtChunk3 and FrenArtChunk4: no constructor arguments, nonpayable constructors, runtime 23,479 and 20,539 bytes (under EIP-170), initcode 28,320 and 24,814 bytes (under EIP-3860), first byte 0x00 (STOP), keccak256 of the deployed code equals FrenArtIndex.CHUNK_HASHES[2] and [3] and the sizes equal CHUNK_SIZES[2] and [3] (the project suite's FrenRenderer construction and a scratch test both confirm), no storage, no owner, no DELEGATECALL/CALLCODE/SELFDESTRUCT executed (execution stops at byte 0). The project's six tests pass with solc 0.8.26. No funds, access control, reentrancy or arithmetic surface exists in these two contracts; the only defect is admission by the launch's opcode scan.","line":784,"path":"src/FrenArtChunks.sol","reproduction":"forge test (6 passed); scratch tests under test/scratch as described in the other findings.","severity":"info","snippet":"contract FrenArtChunk3 {","title":"Coverage: contracts read and checks run"}],"hash":"4ab24d6ae486ef7f01116f8134e601de514a8e8770a8b351f05243155a8e42cc","nodeId":"fedd0a4f-98f9-45c4-b34f-161e16403a1c","outcome":"completed","summary":"The review is complete. Findings are in `.imd-findings.json` at the repository root, and no tracked file was changed. The only untracked files are the findings file and one proof test under `test/scratch/`.\n\n**Headline: launch 2 cannot pass the protected floor as the code stands.** FrenArtChunk4's runtime is raw art data after a STOP byte. The floor's opcode scan does not know the STOP makes the rest unreachable, and it reads 234 of those data bytes as DELEGATECALL. I ran the real protected test against the creation code of chunks 3 and 4 and it fails with \"forbidden application opcode\". Chunk 3 alone passes. The cause is palette slot 244, the first coat shade, which the three lab-coat layers in chunk 4 use heavily.\n\nFindings written, most severe first:\n\n- **High, FrenArtChunk4 rejected by the opcode scan.** Carries a proof test that fails now on the scan count and passes once the chunk is repacked. Any repack changes the chunk's code hash, so FrenArtIndex and the renderer in launch 3 must be regenerated too.\n- **Medium, FrenArtChunk7 has the same problem.** Its palette bytes contain CALLCODE and SELFDESTRUCT values at opcode positions. It belongs to launch 3, but the adapter should repack both chunks in one regeneration so the hashes change only once.\n- **Low, the gas-fit test measures nothing.** It logs about a tenth of the real cost because forge's default metering skips the code-deposit charge. Real deployment on a local anvil shows launch 2 at roughly 9.75M gas, which does fit, so this is not blocking.\n- **Low, ether sent to a chunk is locked forever.** A bare STOP accepts value with no way to withdraw. Expected for a data contract, noted for the adapter.\n- **Info, coverage.** Read in full: all seven chunks, FrenArtIndex, FrenRenderer, the project test, the generator script, README, foundry.toml, the protected test and the Pashov guide. Not read: the reference renderer under test/ref and the vendored libraries.\n\nVerified clean for chunks 3 and 4: no constructor arguments, nonpayable constructors, runtime and initcode under their size limits, first byte STOP, deployed code hashes and sizes match FrenArtIndex, and the project's six tests pass on solc 0.8.26.","treeHash":null,"usage":{"cachedInputTokens":1021346,"inputTokens":514,"model":"claude-fable-5-1","outputTokens":27513,"runtime":"claude","turns":28,"wallClockMs":1331431}},{"artifacts":[],"attempt":1,"bundleHash":"f5706d30b9ef857e6b336632df726ae545c698360cd3dcecb92829658e82f09e","device":"80750826af198795","findings":[],"hash":"5dbf4f87b477c93cb294565c43cf16fa070af9f905bbe5a239433e834374cf25","nodeId":"c34ec7cf-fc45-4b34-8f07-6a55b594e444","outcome":"completed","summary":"Created [launch.json](/home/imd-worker/.identitymd/work/fe768074-11d6-47ad-81bb-91960cbb9fdf/c34ec7cf-fc45-4b34-8f07-6a55b594e444/launch.json) listing `FrenArtChunk3`, then `FrenArtChunk4`, both without constructor arguments. Only the manifest changed.\n\nSchema and compiled ABI checks passed. `forge build` succeeded; `forge test`: 11 passed.\n\nThe existing admission blocker remains: the protected scanner rejects chunk 4’s art bytes after STOP. Documented in the manifest notes.","treeHash":"1217bd57db3579bfbceeaac34d9eed041cbd41b1","usage":{"cachedInputTokens":345728,"inputTokens":35878,"model":"gpt-6-astra","outputTokens":2792,"runtime":"codex","turns":4,"wallClockMs":164240}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"7f1dec5ffcbde1d8","findings":[{"citation":"resolved","description":"Settlement of my round-2 finding 533e8020b8a9 (itself the settlement of 00f0e0b8a1fb). Status: NOT fixed, and the author does not claim it is: their answer is 'disputed' only as to a repository repair, and they re-ran the proof and concede the failure. I re-ran it on this tree and it fails identically, so the finding stands as the one open admission blocker for launch 2. What changed since round 2: nothing in src/ (src/FrenArtChunks.sol and src/FrenArtIndex.sol are byte-identical to their original commit 55f03ac, which is correct under the brief 'do not change them'); launch.json is present and schema-valid (keys kind/contracts/notes only, kind evm_contracts, FrenArtChunk3 then FrenArtChunk4, constructorArgs [] for both, notes 891 chars that state this blocker honestly); test/FrenArtLaunch2.t.sol dropped the test that pinned count==234 (the earlier audit_flow low finding is resolved) and added value-rollback, salt-retry, duplicate-CREATE2 and prefunded-address tests, plus test/FrenArtLaunch2Data.t.sol and test/FrenArtLaunch2Invariant.t.sol; I read the diff and all 26 project tests pass, which says nothing about admission. The defect: FrenArtChunk4's constructor returns STOP + 20,538 art bytes (runtime 20,539 bytes, keccak 0x4412839e8ffb01f255ce07ec70fc6c55a67a78f4365ae2a71eaa4f4d8645a5aa, the hash FrenArtIndex.CHUNK_HASHES[3] pins). The supplied Contracts.protected.t.sol (test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes) scans the whole runtime, skips only PUSH1..PUSH32 immediates, does not stop at the leading STOP, and rejects 0xf4/0xf2/0xff. It finds 234 bytes of 0xf4 in chunk 4, first at runtime offset 3912 (the 9th byte of the quoted literal, '...f802f401...'), then 3922, 3932; all are palette index 244 (FrenRenderer.SLOT0, the first coat shade) in coat0/coat1/coat2, 78 each. FrenArtChunk3 has zero and passes the unchanged floor alone. The bytes are unreachable (pc 0 is STOP), so this is not an executable DELEGATECALL and no loss of funds exists; the impact is that launch 2 as specified cannot pass the required protected floor, and without chunk 4 at its exact hash launch 3's FrenRenderer constructor reverts BadArt, so launch 1's gas buys nothing until this is resolved. Severity stays medium: a reproducible admission/availability failure, not loss of funds; the five specialist 'high' reports of the same root cause (write_foundry_tests f83bd23a, audit_flow 2f77541c, audit_permissions 3c3602b1, audit_math 67d945e2, audit_economics 460380ec) are merged here, each of their proofs runs and fails for the same reason. I agree with the author on the limits: no change inside this repository can clear it. The scan result is a pure function of runtime bytes that the brief and CHUNK_HASHES fix; a constructor change returning the same bytes changes nothing; editing the pinned protected test is not a policy resolution. Further author revisions should NOT be requested for this finding. What settles it is a decision by the requester/policy owner, one of: (a) the admission policy accepts these exact STOP-prefixed data runtimes (a runtime whose byte 0 is 0x00 has no reachable code, or an exception for the two pinned hashes), with the approved protected check and this proof's _scan updated to match; or (b) a separate scope decision to re-encode chunk 4 (and chunk 7 in launch 3, 14 hits), which changes CHUNK_HASHES and the renderer across launches and contradicts the current brief. Until one is made and evidenced, launch 2 is not admissible. Specialist notes re-checked and not kept as defects: the STOP runtime accepts ETH with no way out (intended design, documented in ADAPTATION.md, covered by test_Launch2RetainsDocumentedEthSink); the compiler's deployedBytecode artifact is the 16-byte stub 0x5f80fdfea164736f6c634300081a000a for both chunks rather than the art (inherent to constructor-returned data contracts; reproducible mismatch, but whether any service step compares a build runtime hash with chain code is unverified from here","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 {FrenArtChunk3, FrenArtChunk4} from \"src/FrenArtChunks.sol\";\n\n/// @notice Launch 2 as the factory deploys it (constructors only, no arguments, no value), checked with the exact\n///         runtime traversal of the pinned protected floor (Contracts.protected.t.sol,\n///         test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes). The floor walks the whole runtime, skipping\n///         only PUSH immediates; it does not stop at the leading STOP, so the art bytes after it are read as opcodes.\n///         FrenArtChunk4's coat layers contain palette index 244 (0xf4 = DELEGATECALL) at 234 scanner-visible\n///         positions, so the floor rejects the launch. Fails on the tree as it is; passes once launch 2's runtime\n///         bytes carry no scanner-visible 0xf4 / 0xf2 / 0xff.\ncontract Launch2AdmissionScanTest is Test {\n    function _scan(bytes memory code) internal pure returns (uint256 count, uint256 first) {\n        for (uint256 j; j < code.length; ++j) {\n            uint8 op = uint8(code[j]);\n            if (op >= 0x60 && op <= 0x7f) {\n                j += op - 0x5f;\n                continue;\n            }\n            if (op == 0xf4 || op == 0xf2 || op == 0xff) {\n                if (count == 0) first = j;\n                ++count;\n            }\n        }\n    }\n\n    function _check(address app, string memory name) internal {\n        bytes memory code = app.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        (uint256 count, uint256 first) = _scan(code);\n        emit log_named_uint(string.concat(name, \" scanner-visible forbidden bytes\"), count);\n        emit log_named_uint(string.concat(name, \" first at runtime offset\"), first);\n        assertEq(count, 0, string.concat(name, \": protected floor rejects a forbidden application opcode\"));\n    }\n\n    function test_Launch2RuntimePassesTheProtectedOpcodeScan() public {\n        address c3 = address(new FrenArtChunk3());\n        address c4 = address(new FrenArtChunk4());\n        _check(c3, \"FrenArtChunk3\");\n        _check(c4, \"FrenArtChunk4\");\n    }\n}","reproduction":"Forge 1.8.3, solc 0.8.26, current tree (HEAD afcc67e; src/ unchanged since 55f03ac). (1) Copied the attached proof unchanged to test/scratch/Proof_533e8020b8a9.t.sol and ran: forge test --offline --out test/scratch/out --cache-path test/scratch/cache --match-path test/scratch/Proof_533e8020b8a9.t.sol -vv. It deploys new FrenArtChunk3() then new FrenArtChunk4() (no arguments, zero value) and applies the protected traversal (scan whole runtime, skip PUSH1..PUSH32 immediates, count 0xf4/0xf2/0xff). Expected: 0 rejected positions in both runtimes. Actual: FrenArtChunk3 = 0; FrenArtChunk4 = 234, first at runtime offset 3912; '[FAIL: FrenArtChunk4: protected floor rejects a forbidden application opcode: 234 != 0]'. (2) Copied the supplied Contracts.protected.t.sol unchanged to test/scratch and ran it with IMD_PROJECT_FACTORY=0x1111111111111111111111111111111111111111, IMD_PROJECT_CHAIN_ID=1, IMD_PROJECT_COUNT=2, IMD_PROJECT_CODE_0/1 = bytecode.object of FrenArtChunk3/FrenArtChunk4 from the build, IMD_PROJECT_SALT_0/1 = bytes32(3)/bytes32(4), IMD_PROJECT_ADDRESS_0 = 0xb9443776b5F99A0fD9D999Bd7eAd039C20ff130E, IMD_PROJECT_ADDRESS_1 = 0xD62d5Be0DDF691e59Ae0CCE61bDA6894aA9fe146 (cast create2 predictions). Expected: pass. Actual: both CREATE2 deployments succeed at the predicted addresses, then '[FAIL: forbidden application opcode] test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes()'. With IMD_PROJECT_COUNT=1 (chunk 3 only) the same unchanged test passes. (3) Byte check: the FrenArtChunk4 hex literals concatenated give byte 3912 == 0xf4 (bytes 3904..3919 = f82f00060001f802f401f52f00050001, the start of the quoted line). (4) The four specialist proofs (Proof_f83bd23a025b, Proof_2f77541cc402, Proof_3c3602b1752c, Proof_67d945e2f119) each fail on this tree for the same reason. The attached proof encodes the current protected policy: it passes once chunk 4's runtime has no scanner-visible 0xf4/0xf2/0xff; if the resolution is a policy change instead, its _scan must be updated to the approved policy.","severity":"medium","snippet":"            hex\"f82f00060001f802f401f52f00050001f804f401f52e00050001f805f401f52d00040001f806f401f52d00040001f805f401f801f401f52c00030001f801f70a\"","title":"Not fixed (round 3, settles 533e8020b8a9): exact FrenArtChunk4 runtime still fails the protected admission scanner (234 scanner-visible 0xf4 bytes); open policy decision, no repository revision can cl"}],"hash":"68dd8274dc05138dc0d2f101184305218f01b23fd94848cb87ac9937a6e88dac","nodeId":"e5272f6f-a63b-43f8-becf-2ac2144fee03","outcome":"completed","summary":"Review settled. `.imd-findings.json` holds one finding; nothing else in the tree was changed (scratch copies removed).\n\n**Settlement of my round-2 finding (533e8020b8a9) — not fixed, stands, and the author agrees**\n\n- `src/` is byte-identical to its original commit (correct under the brief's \"do not change them\"). The only changes this round are `launch.json`, `ADAPTATION.md`, and tests.\n- Re-ran my attached proof unchanged on the current tree: fails identically — chunk 3 has 0 scanner-visible forbidden bytes, chunk 4 has 234, first at runtime offset 3912 (`0xf4`, palette slot 244 = `FrenRenderer.SLOT0` in the three coat layers).\n- Re-ran the unmodified `Contracts.protected.t.sol` with both chunks through CREATE2: both deploy at the predicted addresses, then `[FAIL: forbidden application opcode]`. With chunk 3 alone it passes.\n- Author's \"disputed\" is only about a repository repair being possible, and on that I agree: the scan is a pure function of runtime bytes that `CHUNK_HASHES` pins, so no constructor or source change can clear it. The finding stays **medium** (admission/availability failure; the bytes are unreachable behind STOP, no funds at risk). It needs a requester/policy decision — accept STOP-prefixed data runtimes, or separately authorize re-encoding chunk 4 (and chunk 7) across launches. I've stated explicitly that further author revisions should not be requested for it.\n\n**Specialist findings**\n- Five \"high\" reports of the same root cause (write_foundry_tests, audit_flow, audit_permissions, audit_math, audit_economics) all reproduce — each proof fails on this tree — and are merged into the one finding at medium.\n- audit_flow's low (test pinning `count == 234`): resolved — that test is gone; the suite no longer asserts the blocker.\n- Info notes (ETH sink by design; 16-byte artifact runtime stub vs deployed art): re-checked, not defects; the artifact-hash point is recorded in the finding as an open item for the deployer/attestation owner, not a code defect.\n\n**Other checks this round**: `launch.json` is schema-valid (kind/contracts/notes only, FrenArtChunk3 then FrenArtChunk4, empty args, notes 891 chars, honest about the blocker); the revised tests (value rollback, salt retry, duplicate CREATE2, prefunded addresses, data/invariant suites) are sound and all 26 project tests pass. No new defects found.","treeHash":null,"usage":{"cachedInputTokens":508324,"inputTokens":17,"model":"claude-fable-5-1","outputTokens":9180,"runtime":"claude","turns":9,"wallClockMs":282568}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"6b47d1bf92391c22","findings":[],"hash":"6eaee370fd914b9ea70697cb0c3050efaca158eeb475c9ac7ab09dee3219c4d6","nodeId":"804d4eeb-e8e5-40a0-bc21-f71bdfb2c4d5","outcome":"failed","summary":"dependency did not apply: fatal: transport 'file' not allowed\n","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":null,"outputTokens":0,"runtime":"claude","turns":0,"wallClockMs":1075}},{"artifacts":[],"attempt":1,"bundleHash":"34a8ddd8dab89add3288296d1ecb832f1cb8d251eaff8e58cc4c46d6d4a51c27","device":"78362912813d42a5","findings":[{"description":"Reproduced the previously documented launch-2 admission blocker. The assignment requires FrenArtChunk3 and FrenArtChunk4 with exact STOP-prefixed art runtimes, and FrenArtIndex pins their code hashes. Contracts.protected.t.sol scans the entire runtime, including data after STOP, and rejects 234 positions in chunk 4. These bytes are unreachable art data, not executable delegate calls or self-destructs. Consequently the required unmodified launch cannot pass the protected admission check. Changing this runtime to satisfy the scan would violate the brief and cause FrenRenderer.BadArt. An upstream resolution of the admission policy versus exact-art requirement is needed; passing the repository tests does not establish launch admission.","line":1162,"path":"src/FrenArtChunks.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {FrenArtChunk3, FrenArtChunk4} from \"src/FrenArtChunks.sol\";\n\ncontract Launch2AdmissionProof is Test {\n    function test_RequiredLaunch2ArtMustPassSuppliedAdmissionScan() public {\n        address[2] memory applications = [address(new FrenArtChunk3()), address(new FrenArtChunk4())];\n        for (uint256 i; i < applications.length; ++i) {\n            bytes memory code = applications[i].code;\n            assertGt(code.length, 0, \"missing runtime\");\n            assertLe(code.length, 24_576, \"runtime exceeds EIP-170\");\n            // Exact traversal from Contracts.protected.t.sol; notably it scans past STOP.\n            for (uint256 j; j < code.length; ++j) {\n                uint8 op = uint8(code[j]);\n                if (op >= 0x60 && op <= 0x7f) {\n                    j += op - 0x5f;\n                    continue;\n                }\n                if (op == 0xf4 || op == 0xf2 || op == 0xff) {\n                    emit log_named_uint(\"chunk\", i + 3);\n                    emit log_named_uint(\"runtime offset\", j);\n                    emit log_named_uint(\"rejected byte\", op);\n                }\n                assertTrue(op != 0xf4 && op != 0xf2 && op != 0xff, \"forbidden application opcode\");\n            }\n        }\n    }\n}","reproduction":"Save the proof as test/scratch/Launch2AdmissionProof.t.sol and run forge test --match-path test/scratch/Launch2AdmissionProof.t.sol -vv. It deploys FrenArtChunk3 followed by FrenArtChunk4 without arguments or value, then applies the exact protected runtime traversal. Expected: the required launch artifacts satisfy admission. Actual: chunk 3 passes; chunk 4 fails with forbidden application opcode at runtime offset 3912, byte 244 (0xf4). Locally reproduced with solc 0.8.26 and Forge 1.8.3 using --offline --out test/scratch/out --cache-path test/scratch/cache. Runtime sizes are 23479 and 20539 bytes. This is an incompatibility with the supplied checker, not a claim that execution reaches that byte.","severity":"medium","title":"Required chunk 4 runtime cannot pass the supplied admission scan"}],"hash":"78288b5dcee21e61456e028f1ba2ff3ff8c434ee7b5c53f6c82ced9e022828a4","nodeId":"451faae4-c5e1-481a-8519-49a01b1e6f0b","outcome":"completed","summary":"Added deployment failure, art integrity, renderer rejection, and stateful invariant tests.\n\nOffline `forge build` and `forge test` pass: **24 tests**, including **16,384 random handler calls**.\n\nReported the unresolved chunk 4 admission blocker, with a reproduced failing proof, in `.imd-findings.json`.","treeHash":"caee43f9c10062b837518cb15406fcaf4d74c7f8","usage":{"cachedInputTokens":944128,"inputTokens":75185,"model":"gpt-6-astra","outputTokens":15783,"runtime":"codex","turns":6,"wallClockMs":552479}},{"artifacts":[],"attempt":2,"bundleHash":null,"device":"f20ec62b0213db3f","findings":[{"citation":"resolved","description":"Area: Flow Gap (execution x periphery x first principles) and Economic Security (dependency failure blocks the launch). FrenArtChunk4's constructor returns STOP followed by 20,538 bytes of art (runtime 20,539 bytes, keccak 0x4412839e...45a5aa, the hash FrenArtIndex pins). The three coat layers (index entries 39-41, chunk offsets 3896..6409) paint with palette slot 244 = 0xf4, the renderer's SLOT0 coat shade. The protected floor (Contracts.protected.t.sol, test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes) walks the whole runtime linearly, skipping only PUSH immediates, and asserts no byte is 0xf4, 0xf2 or 0xff. It does not stop at the leading STOP, so it reads art as code: 234 positions in FrenArtChunk4 are 0xf4 outside a PUSH immediate (raw count of 0xf4 in the runtime is also 234; there is no 0xf2 or 0xff). The quoted line is the 62nd hex line of FrenArtChunk4 and holds runtime bytes 3904..3967; its 9th byte (runtime offset 3912) is the first hit. FrenArtChunk3 has none of the three byte values at all and passes alone. Because a launch is one factory transaction and one rehearsal, FrenArtChunk4's failure rejects launch 2 as a whole, exactly as the task states it ('FrenArtChunk3 and FrenArtChunk4, in that order, no constructor arguments'). Nothing in the repository can change this while the chunk keeps its code hash: the scan is a pure function of the runtime bytes, and the runtime bytes are fixed by FrenArtIndex.CHUNK_HASHES[3]. The bytes are not a real capability: execution of any call into the chunk starts at pc 0, which is STOP, so no byte after it can ever run (I traced: plain call, call with value and calldata 0xdeadbeef all return success with empty data and unchanged code hash). The floor's guarantee (no DELEGATECALL/CALLCODE/SELFDESTRUCT) holds in substance and fails in form, and the form is the gate. Economics: launch 2 measured at 9,758,684 gas with a minimal CREATE2 factory under --isolate (calldata 53,284 bytes, 3,334 zero; 8,803,600 of it is code deposit), i.e. about 0.0098 ETH per gwei of gas price, and it buys nothing by itself: the chunks only have value once launch 3's FrenRenderer is constructed over them. Launch 1 (chunks 1 and 2: 0 hits) passes the floor today, launch 2 fails it (this finding), and launch 3 fails it the same way (FrenArtChunk7: 14 hits, first at offset 7671 = 0xf2). So broadcasting launch 1, or launch 2 under a one-off exception, before all three rehearse clean strands that launch's gas: FrenRenderer's constructor reverts BadArt unless all seven code hashes are present, so no partial set can be used. The current tree records the blocker instead of removing it: test/FrenArtLaunch2.t.sol:49 asserts `assertEq(count4, 234);`, so `forge test` is green (11 passed) while the launch is inadmissible, and that test will have to be inverted by whichever fix is chosen. Fix needs a scope decision by the requester, because both routes leave this assignment's write scope: (a) keep the art bytes and have the launch policy accept a runtime whose first byte is 0x00 (STOP) as non-executable data (sound: there is no entry other than pc 0), applied to launch 3's FrenArtChunk7 as well; or (b) regenerate chunks 4 and 7 in script/art/chunks.py with a framing the scan cannot misread (for example each 32 art bytes behind a 0x7f PUSH32 byte, +1/32 size, the renderer's _entry un-framing on read), which changes those two code hashes in FrenArtIndex and the renderer in launch 3 and contradicts the brief's 'do not change them'. Chunks 1, 2, 3, 5, 6 need no change under either route. The attached proof mirrors the floor's traversal; it passes under route (b). Under route (a) the floor itself changes and the proof's scan should be updated to the new floor.","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 {FrenArtChunk3, FrenArtChunk4} from \"src/FrenArtChunks.sol\";\n\n/// @notice Launch 2 (FrenArtChunk3, then FrenArtChunk4, no constructor arguments) against the traversal of the\n///         evm_contracts protected floor (Contracts.protected.t.sol): runtime present, at most 24,576 bytes, and no\n///         0xf4 / 0xf2 / 0xff byte outside a PUSH immediate. Fails today on FrenArtChunk4.\ncontract Launch2ProtectedFloorTest is Test {\n    function _forbidden(bytes memory code) internal pure returns (uint256 count, uint256 first) {\n        for (uint256 j; j < code.length; ++j) {\n            uint8 op = uint8(code[j]);\n            if (op >= 0x60 && op <= 0x7f) {\n                j += op - 0x5f;\n                continue;\n            }\n            if (op == 0xf4 || op == 0xf2 || op == 0xff) {\n                if (count == 0) first = j;\n                ++count;\n            }\n        }\n    }\n\n    function _check(address app, string memory name) internal {\n        bytes memory code = app.code;\n        assertGt(code.length, 0, \"missing runtime\");\n        assertLe(code.length, 24_576, \"runtime exceeds EIP-170\");\n        (uint256 count, uint256 first) = _forbidden(code);\n        emit log_named_uint(string.concat(name, \": forbidden positions\"), count);\n        emit log_named_uint(string.concat(name, \": first forbidden runtime offset\"), first);\n        assertEq(count, 0, string.concat(name, \": forbidden application opcode on the protected floor's scan\"));\n    }\n\n    function test_Launch2Chunk3PassesTheProtectedFloorScan() public {\n        _check(address(new FrenArtChunk3()), \"FrenArtChunk3\");\n    }\n\n    function test_Launch2Chunk4PassesTheProtectedFloorScan() public {\n        _check(address(new FrenArtChunk4()), \"FrenArtChunk4\");\n    }\n}","reproduction":"1) forge build. 2) Copy .imd/reads/protected/evm_contracts/Contracts.protected.t.sol unchanged into test/scratch/ and run it with IMD_PROJECT_FACTORY=0x00000000000000000000000000000000000F4C70 IMD_PROJECT_CHAIN_ID=1 IMD_PROJECT_COUNT=2, IMD_PROJECT_CODE_0 = bytecode.object of out/FrenArtChunks.sol/FrenArtChunk3.json (28,320 bytes with solc 0.8.26), IMD_PROJECT_SALT_0 = 0x00..03, IMD_PROJECT_ADDRESS_0 = its CREATE2 address (0xe89f007a7A8F0b39694b4C8989f6769975326993), IMD_PROJECT_CODE_1 = FrenArtChunk4's bytecode.object (24,814 bytes), IMD_PROJECT_SALT_1 = 0x00..04, IMD_PROJECT_ADDRESS_1 = 0x2E9fb97671F670f9Af8Fa779B01aDf1f75056394. Expected: setUp deploys both and test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes passes. Actual: both deploy with the predicted addresses, then '[FAIL: forbidden application opcode]'. Failing input: FrenArtChunk4 runtime, offset 3912, byte 0xf4 (then 3922, 3932, ... 234 positions in all, every one inside coat0/coat1/coat2 at chunk offsets 3896..6409). With IMD_PROJECT_COUNT=1 and only FrenArtChunk3 the scan finds 0 positions. Or run the attached proof: forge test --match-path test/scratch/Launch2ProtectedFloor.t.sol -vv -> test_Launch2Chunk3PassesTheProtectedFloorScan passes, test_Launch2Chunk4PassesTheProtectedFloorScan fails with 'FrenArtChunk4: forbidden application opcode on the protected floor's scan: 234 != 0' (first forbidden runtime offset: 3912).","severity":"high","snippet":"            hex\"f82f00060001f802f401f52f00050001f804f401f52e00050001f805f401f52d00040001f806f401f52d00040001f805f401f801f401f52c00030001f801f70a\"","title":"Launch 2 cannot pass the evm_contracts protected floor: FrenArtChunk4's runtime has 234 bytes of 0xf4 (DELEGATECALL) on the floor's scan, first at runtime offset 3912"},{"citation":"resolved","description":"Area: Flow Gap (execution x periphery) and Invariant (interface guarantee: attested runtime == deployed runtime). Each chunk's constructor ends by returning its own literal as the contract's code (the quoted line, FrenArtChunk3; the same statement is FrenArtChunk4's line 1487), so the code the chain stores never comes from the compiler's runtime object. The build therefore records, as deployedBytecode for FrenArtChunk3 and for FrenArtChunk4 alike, the 16 bytes 0x5f80fdfea164736f6c634300081a000a (PUSH0 DUP1 REVERT INVALID plus the solc 0.8.26 CBOR tag), keccak 0x19735bdf4d52c6f889cfd85f70fad899c9f4372c41ff8aa853bf043831e21b36, identical for all seven chunks. On chain FrenArtChunk3 is 23,479 bytes with code hash 0xd73ecfd95e853d3bf20224d02e30889477ac2627bc1970c5e6b0ca5ef202c9a8 and FrenArtChunk4 is 20,539 bytes with 0x4412839e8ffb01f255ce07ec70fc6c55a67a78f4365ae2a71eaa4f4d8645a5aa. The launch pipeline's ReleaseAttestation is described as binding each contract's creation and runtime hashes. For this launch the creation hash does bind the art (the art is inside the creation code: 0xda935d79...74d770 for chunk 3, 0xd4675a94...c7d657 for chunk 4 with solc 0.8.26), but a runtime hash read from the artifact binds nothing: it is one value for both contracts and equals neither deployed code. Two concrete outcomes, depending on a service step I could not read from here: if any step after broadcast compares deployed code (or explorer runtime-match verification) with the artifact runtime, launch 2 is reported as a mismatch after about 9.76M gas has been spent; if no step compares it, the attested runtime hash is silently meaningless for these two contracts and only the creation hash and FrenRenderer's own constructor check (launch 3) tie the deployment to the art. This is not fixable in the chunk source without changing what the brief fixes (a data contract's code cannot be the compiler's runtime object). What is needed is on the service side: take the runtime hash and size of each chunk from the rehearsal's deployed code (they equal FrenArtIndex.CHUNK_HASHES[2..3] and CHUNK_SIZES[2..3]) and verify the explorer listing by creation code, and confirm which attestation field the deployer and the publication step actually compare. Unverified part: whether such a comparison exists; the mismatch itself is reproduced below.","line":1155,"path":"src/FrenArtChunks.sol","reproduction":"forge build; jq -r .deployedBytecode.object out/FrenArtChunks.sol/FrenArtChunk3.json and .../FrenArtChunk4.json both print 0x5f80fdfea164736f6c634300081a000a (16 bytes). In a Foundry test: keccak256(vm.getDeployedCode(\"FrenArtChunks.sol:FrenArtChunk3\")) == address(new FrenArtChunk3()).codehash. Expected (what a runtime-hash binding assumes): equal. Actual: 0x19735bdf4d52c6f889cfd85f70fad899c9f4372c41ff8aa853bf043831e21b36 != 0xd73ecfd95e853d3bf20224d02e30889477ac2627bc1970c5e6b0ca5ef202c9a8 (16 bytes vs 23,479 bytes). Same for FrenArtChunk4: artifact hash 0x19735bdf...1b36 vs deployed 0x4412839e...45a5aa (16 vs 20,539 bytes). I ran this assertion in a scratch test and it failed with exactly these values.","severity":"low","snippet":"            return(add(code, 32), mload(code))","title":"The compiler's runtime artifact for FrenArtChunk3/4 is a 16-byte stub, not the art that lands on chain: an attested or verified 'runtime hash' taken from the build cannot match (and is the same value "},{"citation":"resolved","description":"Not a defect; the coverage rows the review brief asks for. Entry points of launch 2 and of what consumes it:\n- FrenArtChunk3.constructor() -- holds: nonpayable, no arguments, returns STOP + 23,478 art bytes; runtime 23,479 <= 24,576 (EIP-170), creation code 28,320 <= 49,152 (EIP-3860), first byte 0x00 (not 0xEF); code hash equals FrenArtIndex.CHUNK_HASHES[2], size equals CHUNK_SIZES[2]; 0 forbidden positions; passes the unmodified protected floor when rehearsed alone.\n- FrenArtChunk3 runtime (any selector, any calldata, with or without value) -- holds: pc 0 is STOP, so every call succeeds with empty return data and no state change. It accepts ETH and has no way to return it; that is the already recorded and tested trust note (test_Launch2RetainsDocumentedEthSink), self-inflicted only, not re-reported.\n- FrenArtChunk4.constructor() -- finding 1: the code it returns (20,539 bytes, hash equals CHUNK_HASHES[3], size equals CHUNK_SIZES[3], creation code 24,814 bytes) fails the protected floor's opcode scan.\n- FrenArtChunk4 runtime -- holds for behaviour (same as chunk 3: STOP at pc 0, the 0xf4 bytes are unreachable); finding 1 for admission.\n- Both constructors, build artifact vs chain -- finding 2.\n- FrenRenderer.constructor(c1..c7) (launch 3, takes launch 2's addresses as static words) -- holds for this area: a wrong, empty, zero or reordered address for c3/c4 has a different EXTCODEHASH and reverts BadArt, so a bad hand-off between launches fails closed and cannot produce a renderer over other art; an identical copy of a chunk deployed by anyone else is the same art and harmless.\n- FrenRenderer._entry reads into chunks 3 and 4 (reached from canvas, silhouette, bmp, tokenURI, pendingURI) -- holds: index entries 25-36 tile chunk 3 exactly (0..23,478) and entries 37-60 tile chunk 4 exactly (0..20,538), no gap or overlap, every 1+off+len <= code size; each of the 36 layers equals its script/art/data/layers/*.bin file byte for byte, has a well-formed header and rows whose runs sum to the layer width, no zero-length run, x0+w <= 120 and y0+h <= 120.\nGuide items checked: dependency failure (finding 1), value flows (none: no token, owner, fee, oracle, approval or payable path; the only value path is the ETH sink above), atomic extraction and griefing (no state to manipulate; the chunks cannot be destroyed or changed), sentinel addresses (zero/empty address fails the hash check), shared capacity (the 2^24 gas transaction cap: launch 2 measured 9,758,684 gas with a minimal CREATE2 factory under --isolate, EIP-7623 floor 2,052,340, against the repository's 11,738,744 budget and the 16,777,216 cap), conservation and coupling invariants (hash, size, index tiling, source-file equality as above), view/write divergence (none: nothing writes), multi-step end state across the three launches (folded into finding 1).\nNot reached: the real IMD factory (its salts, access control, bookkeeping gas and what it does when a CREATE2 address is occupied), the policy's gasCeilingWei value, the service's attestation and deployer code (finding 2's open question), creation code produced by solc versions other than 0.8.26 (the runtime is the literal and does not depend on the compiler; creation bytes and therefore CREATE2 addresses do), and launch 1 and launch 3 beyond the points where they touch launch 2. Tools run: forge 1.8.3 build and tests with solc 0.8.26, the unmodified protected floor, a Python parse of the generated sources; no Slither, Mythril, fork or network.","line":784,"path":"src/FrenArtChunks.sol","reproduction":"forge test (11 passed) for the hash, size, value-rejection and ETH-sink rows; the unmodified Contracts.protected.t.sol with IMD_PROJECT_COUNT=1 and FrenArtChunk3's creation code (salt 0x..03, address 0xe89f007a7A8F0b39694b4C8989f6769975326993 under factory 0x00000000000000000000000000000000000F4C70) passes; parsing src/FrenArtIndex.sol INDEX against the hex literals of FrenArtChunk3/4 and script/art/data/layers gives the tiling and equality stated above.","severity":"info","snippet":"contract FrenArtChunk3 {","title":"Coverage record for launch 2 (Economic Security, Invariant, Flow Gap): what was traced and held, what was not reachable"}],"hash":"82b233f6afac6a430949c64f74b143e5157ed51a58687ff2aa0d4e76ac3d0ee7","nodeId":"804d4eeb-e8e5-40a0-bc21-f71bdfb2c4d5","outcome":"completed","summary":"The review is written to `.imd-findings.json`: one high finding, one low finding and a coverage record. No repository file was changed; the findings file is the only new path.\n\n## Findings\n\n1. **High — launch 2 cannot pass the protected floor.** `FrenArtChunk4`'s runtime has 234 bytes of `0xf4` (palette slot 244, used by the three coat layers) that the floor's opcode scan reads as DELEGATECALL, first at runtime offset 3912 (`src/FrenArtChunks.sol:1226`).\n   - I ran the unmodified `Contracts.protected.t.sol` against both chunks: they deploy at the predicted addresses, then the test fails with `forbidden application opcode`. `FrenArtChunk3` alone passes.\n   - The bytes can never execute, because the code starts with STOP, but the scan does not stop there and the scan is the gate.\n   - The existing test at `test/FrenArtLaunch2.t.sol:49` asserts the 234 hits, so `forge test` is green while the launch is blocked.\n   - A proof test is attached; it fails today on chunk 4 only.\n\n2. **Low — the build's runtime artifact is not what lands on chain.** For both chunks the compiler's `deployedBytecode` is the same 16-byte stub, while the deployed code is 23,479 and 20,539 bytes with the hashes `FrenArtIndex` pins. A runtime hash taken from the artifact for attestation or explorer verification cannot match. I could not see whether any service step makes that comparison; the mismatch itself is reproduced.\n\n3. **Info — coverage record.** One row per entry point, plus the guide items checked and what was not reached.\n\n## Decision for you\n\nFinding 1 has no fix inside this assignment's scope, because the scan depends only on the runtime bytes and those are fixed by the pinned code hash. The two routes are:\n\n- **Policy exception:** accept a runtime whose first byte is STOP as non-executable data. The art and hashes stay as they are, and launch 3's `FrenArtChunk7` needs the same exception (14 hits).\n- **Re-encode chunks 4 and 7:** frame the art so the scan cannot misread it. This changes two code hashes in `FrenArtIndex` and the renderer's read path, which contradicts the brief's \"do not change them\".\n\nThe attached proof passes only under the second route; under the first, the floor itself changes and the proof's scan would need updating.\n\nUntil all three launches rehearse clean, broadcasting any one of them strands its gas: launch 2 measured about 9.76M gas, and the renderer refuses any partial set of chunks.\n\n## What held\n\n- **Hashes and sizes:** both chunks' deployed code matches the pinned hash and size in `FrenArtIndex`.\n- **Index and art data:** the index entries tile each chunk exactly, and all 36 layers equal their source files byte for byte and are well-formed.\n- **Hand-off to launch 3:** a wrong, empty or reordered chunk address makes the renderer's constructor revert.\n- **Gas:** launch 2 fits under the repository's 11.74M budget and the 2^24 transaction cap.\n- **ETH sink:** the chunks accept ETH and cannot return it. This is already documented and tested, so I did not re-report it.\n\nNot reached: the real IMD factory, the policy's gas ceiling, the service's attestation and deployer code, and creation code from compilers other than solc 0.8.26.","treeHash":null,"usage":{"cachedInputTokens":1358800,"inputTokens":30,"model":"claude-fable-5-1","outputTokens":43254,"runtime":"claude","turns":19,"wallClockMs":899818}},{"artifacts":[],"attempt":1,"bundleHash":"8c1a0ca37ae831fa0da425c7d8a251d72244636d9f09db80ddf3a1625eaf11ec","device":"c0710fe928a45237","findings":[{"description":"Reproduced the pre-existing launch admission blocker. The supplied Contracts.protected.t.sol scans the complete runtime, skipping PUSH operands but continuing after STOP. FrenArtChunk4 returns the exact required 20,539-byte runtime, whose hash is 0x4412839e8ffb01f255ce07ec70fc6c55a67a78f4365ae2a71eaa4f4d8645a5aa. That scan rejects 234 positions in its art payload, beginning with 0xf4 at zero-based runtime offset 3912. These bytes are unreachable data after STOP, not an executable delegatecall vulnerability. FrenArtChunk3 passes the same scan. As a result, the requested pair cannot satisfy the supplied admission policy even though deployment and the ordinary application tests succeed. Altering the payload would violate the task and cause the renderer code-hash check to reject it. Resolving admission requires an upstream policy/specification decision; no test-only change can fix the incompatibility, and no passing test was added to assert that rejection is correct.","line":1162,"path":"src/FrenArtChunks.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {FrenArtChunk3, FrenArtChunk4} from \"src/FrenArtChunks.sol\";\n\ncontract Launch2AdmissionProof is Test {\n    function test_RequestedLaunchPassesProtectedAdmissionScan() public {\n        address[2] memory chunks = [address(new FrenArtChunk3()), address(new FrenArtChunk4())];\n        for (uint256 i; i < chunks.length; ++i) {\n            bytes memory code = chunks[i].code;\n            assertGt(code.length, 0, \"missing runtime\");\n            assertLe(code.length, 24_576, \"runtime exceeds EIP-170\");\n            uint256 forbidden;\n            uint256 firstOffset;\n            uint256 firstOpcode;\n            // The supplied Contracts.protected.t.sol scans even after STOP and skips PUSH data.\n            for (uint256 j; j < code.length; ++j) {\n                uint8 op = uint8(code[j]);\n                if (op >= 0x60 && op <= 0x7f) {\n                    j += op - 0x5f;\n                    continue;\n                }\n                if (op == 0xf4 || op == 0xf2 || op == 0xff) {\n                    if (forbidden == 0) {\n                        firstOffset = j;\n                        firstOpcode = op;\n                    }\n                    ++forbidden;\n                }\n            }\n            emit log_named_uint(\"chunk\", i + 3);\n            emit log_named_uint(\"forbidden positions\", forbidden);\n            emit log_named_uint(\"first forbidden offset\", firstOffset);\n            emit log_named_uint(\"first forbidden opcode\", firstOpcode);\n            assertEq(forbidden, 0, \"requested art fails protected admission\");\n        }\n    }\n}","reproduction":"Save the proof below as test/scratch/Launch2AdmissionProof.t.sol and run forge test --offline --out test/scratch/out --cache-path test/scratch/cache --match-path test/scratch/Launch2AdmissionProof.t.sol -vv. It deploys FrenArtChunk3 then FrenArtChunk4 without constructor arguments or value and applies the supplied scan. Expected: zero forbidden positions for both requested applications. Actual: chunk 3 has zero; chunk 4 has 234, first at offset 3912 with opcode 244 (0xf4). Locally reproduced failure: requested art fails protected admission: 234 != 0. This proof intentionally encodes the supplied policy; an upstream policy revision must update that policy expectation rather than change the pinned art.","severity":"medium","title":"Required launch-2 art is incompatible with the supplied admission scan"}],"hash":"82ffb08562bf1b0996a7ae1a16f70b1e9c62dc0d53b3b531a8fd81c1bc1a023a","nodeId":"451faae4-c5e1-481a-8519-49a01b1e6f0b","outcome":"completed","summary":"Expanded invariant tests to cover full-balance transfers and failed calls from depleted actors.\n\n`forge build` and `forge test` pass: **25 tests**, including 16,384 invariant calls.\n\nReported the existing chunk-4 admission blocker with a reproduced failing proof in `.imd-findings.json`. Admission remains unresolved; production contracts are unchanged.","treeHash":"42591b7cd25d9274e8610ba5247b4fcb47c19f33","usage":{"cachedInputTokens":983168,"inputTokens":70663,"model":"gpt-6-astra","outputTokens":8978,"runtime":"codex","turns":5,"wallClockMs":356659}},{"artifacts":[],"attempt":2,"bundleHash":null,"device":"dff6c0d3de4aa913","findings":[{"citation":"resolved","description":"Boundary: the protected floor (Contracts.protected.t.sol, test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes) walks every byte of each deployed runtime, skips only PUSH immediates, and fails on 0xf4, 0xf2 or 0xff. Assumption in this launch: bytes after the leading STOP are data and nobody reads them as code. Actual: the scan does not stop at STOP, so data bytes count.\n\nFrenArtChunk4's runtime (20,539 bytes, keccak 4412839e...a5aa) has exactly 234 bytes equal to 0xf4, the first at runtime offset 3912 (this source line, 9th byte). None sits inside a PUSH immediate (raw count 234 = scanned count 234). All 234 are the colour byte of a run in the three coat layers, 78 each: coat0 (art offset 3896, length 838), coat1 (4734, 838), coat2 (5572, 838). The value is palette index 244, which src/FrenRenderer.sol:31 defines as SLOT0, the first coat-shade slot (`uint256 internal constant SLOT0 = 244;`). So the numbering of the recolour slots is what collides with the DELEGATECALL opcode value; no run count and no other layer contributes. FrenArtChunk3 (23,479 bytes) has zero such bytes and passes the same floor on its own; its faces only use slots 250 and 251.\n\nImpact: launch 2 as specified (FrenArtChunk3, FrenArtChunk4, exact bytes) is rejected at admission. FrenRenderer's constructor needs chunk 4's exact code hash, so launch 3 cannot produce a renderer either, and the chunks of launch 1 have nothing to read them. The bytes are unreachable (every call halts at byte 0), so this is an admission failure, not an exploitable DELEGATECALL.\n\nStatus: this is already recorded as unresolved in ADAPTATION.md (imported finding b7f5588e...) and README.md; this review reproduced it independently and it still holds. The repository's own suite stays green only because test/FrenArtLaunch2.t.sol:49 asserts the rejection (`assertEq(count4, 234);`), so a passing `forge test` says nothing about admission.\n\nNo fix exists inside the brief: the code hash pins every byte, and the scan result is a function of those bytes. It needs a scope decision, one of: (a) the protected floor exempts runtimes whose first byte is 0x00, which have no reachable code; or (b) the art is re-exported with the coat slot at 244 moved to a free index (252..254 are unused by all 69 layers), which changes 234 bytes of chunk 4, its hash in FrenArtIndex.CHUNK_HASHES, SLOT0 handling in FrenRenderer and the reference renderer, i.e. launch 3 material. Option (b) does not help chunk 7 (launch 3), whose 14 rejected bytes are palette colour components. The attached proof encodes the floor as it stands, so it passes only once chunk 4's runtime is free of scanned 0xf4/0xf2/0xff bytes.","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 {FrenArtChunk3, FrenArtChunk4} from \"src/FrenArtChunks.sol\";\n\n/// @dev Launch 2 exactly as requested (FrenArtChunk3, then FrenArtChunk4, no constructor arguments, no value), then\n///      the protected floor's runtime check, copied from Contracts.protected.t.sol\n///      (test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes): same traversal, same PUSH skipping, same bytes.\ncontract Launch2ProtectedFloorTest is Test {\n    address[] private applications;\n\n    function setUp() public {\n        applications.push(address(new FrenArtChunk3()));\n        applications.push(address(new FrenArtChunk4()));\n    }\n\n    function test_launch2RuntimeIsPresentBoundedAndHasNoEscapeOpcodes() public view {\n        for (uint256 i; i < applications.length; ++i) {\n            bytes memory code = applications[i].code;\n            assertGt(code.length, 0, \"missing runtime\");\n            assertLe(code.length, 24_576, \"runtime exceeds EIP-170\");\n            for (uint256 j; j < code.length; ++j) {\n                uint8 op = uint8(code[j]);\n                if (op >= 0x60 && op <= 0x7f) {\n                    j += op - 0x5f;\n                    continue;\n                }\n                assertTrue(op != 0xf4 && op != 0xf2 && op != 0xff, \"forbidden application opcode\");\n            }\n        }\n    }\n}","reproduction":"State: launch 2 exactly as requested, no constructor arguments, zero value. Two reproductions were run.\n1) The supplied protected floor unchanged, with IMD_PROJECT_COUNT=2, IMD_PROJECT_CODE_0/1 = the compiled creation code of FrenArtChunk3/FrenArtChunk4 (28,320 and 24,814 bytes, solc 0.8.26), salts 3 and 4 and the matching CREATE2 addresses: setUp deploys both, then test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes fails with `forbidden application opcode`. With IMD_PROJECT_COUNT=1 (chunk 3 only) the same test passes.\n2) The attached proof (`forge test --match-path test/scratch/Launch2ProtectedFloor.t.sol`): `new FrenArtChunk3()`, `new FrenArtChunk4()`, then the floor's loop. Expected: pass. Actual: `[FAIL: forbidden application opcode]`, first at applications[1].code[3912] == 0xf4.\nByte census of the seven runtimes under the floor's traversal: chunks 1, 2, 3, 5, 6 = 0 hits; chunk 4 = 234 (all 0xf4); chunk 7 = 14 (11 x 0xff, 2 x 0xf4, 1 x 0xf2).","severity":"high","snippet":"            hex\"f82f00060001f802f401f52f00050001f804f401f52e00050001f805f401f52d00040001f806f401f52d00040001f805f401f801f401f52c00030001f801f70a\"","title":"Launch 2 cannot pass the protected floor: FrenArtChunk4's runtime holds 234 bytes of 0xf4 (colour index 244 = SLOT0), each read as DELEGATECALL"},{"citation":"resolved","description":"Not a defect; the coverage record the review asks for. Entry points of this launch and what was traced from this area:\n- FrenArtChunk3 constructor: holds. Runtime 23,479 bytes (<= 24,576, EIP-170), initcode 28,320 (<= 49,152, EIP-3860), nonpayable, returns exactly the literal; first byte 0x00.\n- FrenArtChunk3 runtime (any call, any calldata or value): holds. Halts at byte 0; zero bytes rejected by the floor. ETH sent to it stays there, as ADAPTATION.md already documents.\n- FrenArtChunk4 constructor: holds. Runtime 20,539 bytes, initcode 24,814, same shape.\n- FrenArtChunk4 runtime: finding 1.\nChecked with numbers, all clean: the bytes in src/FrenArtChunks.sol equal script/art/data for all 70 index entries; in every chunk the entries are contiguous from offset 0 and end exactly at code length - 1 (no slack, no overlap), so the renderer's guard `p.code.length < 1 + off + len` is met with equality at face36 (1+21560+1918 = 23,479) and bg1 (1+16068+4470 = 20,539); CHUNK_SIZES and the doc comments (23478 / 20538 art bytes) agree. Every layer in chunks 3 and 4 (face25..face38, coat0..2, hat0..1, item0..14, bg0..1) decodes with each row's runs summing exactly to its width, no zero-length run, no trailing bytes, and only colours 0..192 or slots 244..251. Their boxes lie inside the 84x84 window (x 18..102, y 26..110) with exact fits at item1/item5 (x1 = 102) and hat1 (y0 = 26); both backgrounds are 120x120 at (0,0), which is exactly the 84 + 36 the seed window needs. The _entry masks (byte 0, bytes 1-2, bytes 3-4) match the 5-byte layout. Gas for launch 2 through a minimal CREATE2 factory: 9,807,395 execution including 8,803,600 code deposit, plus 812,536 calldata (49,950 nonzero and 3,334 zero bytes) and 21,000 intrinsic, about 10.64M, under the test's 11,738,744 budget and the 16,777,216 cap; the EIP-7623 floor (2,052,340) does not bind.\nNot reached: the real IMD factory's own overhead and the policy's gasCeilingWei; whether the attestation service compares on-chain code with the compiler's nominal runtime artifact (16 bytes for these contracts, not the art); worst-case tokenURI gas over all combos (one sample measures 12,987,095); chunks 1, 2, 5, 6, 7 and FrenRenderer beyond how they read chunks 3 and 4. FrenArtIndex.CHUNK_SIZES is described as checked by the renderer but is only read by the test; the hash check makes that harmless.","line":784,"path":"src/FrenArtChunks.sol","reproduction":"No failing input: this entry records what was exercised. `forge test` on the tree as given: 11 passed, 0 failed (solc 0.8.26, Forge 1.8.3). The supplied protected floor with chunk 3 alone passes; with chunks 3 and 4 it fails as in finding 1.","severity":"info","snippet":"contract FrenArtChunk3 {","title":"Coverage: Math Precision, Boundary and Numerical Gap passes over launch 2 (FrenArtChunk3, FrenArtChunk4); no other defect found"}],"hash":"ae832a38041c80892effeb41699277504826cf5032420dbee554b6669a052922","nodeId":"ccd401cc-3c07-40bc-8314-01cc8a1adfc2","outcome":"completed","summary":"The review is written to `.imd-findings.json`: one high finding and one info entry recording coverage. No tracked file was changed, and the scratch test directory is removed.\n\n## Finding 1 (high): launch 2 cannot pass the protected floor\n\n`FrenArtChunk4`'s runtime contains 234 bytes of `0xf4`, which the protected floor reads as DELEGATECALL because it scans past the leading STOP.\n\n- **Where:** the first is at runtime offset 3912 (`src/FrenArtChunks.sol:1226`).\n- **Cause:** all 234 are the colour byte of a run in the three coat layers, 78 each. The value is palette index 244, which `src/FrenRenderer.sol:31` defines as `SLOT0`, the first coat-shade slot.\n- **Chunk 3:** `FrenArtChunk3` has no such bytes and passes the floor on its own.\n- **Impact:** launch 2 is rejected at admission, and because the renderer needs chunk 4's exact code hash, launch 3 cannot produce a renderer either. The bytes are unreachable, so this is an admission failure, not an exploitable call.\n- **Reproduced two ways:** the supplied protected floor run unchanged with both chunks fails with `forbidden application opcode`. The attached proof test fails the same way.\n- **Already known:** `ADAPTATION.md` and `README.md` record this as unresolved. The repository's suite is green only because `test/FrenArtLaunch2.t.sol:49` asserts the rejection.\n\nNo fix exists inside the brief, since the code hash pins every byte. It needs a scope decision:\n\n- **Exempt at the floor:** the protected floor skips runtimes whose first byte is `0x00`, which have no reachable code.\n- **Re-export the art:** move the coat slot at 244 to a free index (252–254 are unused). This changes chunk 4's hash, the index and the renderer, and does not help chunk 7, whose rejected bytes are palette colours.\n\nThe attached proof encodes the floor as it stands, so it only passes if chunk 4's bytes change — under the first option it would still fail.\n\n## Coverage (info entry)\n\nEverything else in the Math Precision, Boundary and Numerical Gap passes held for chunks 3 and 4:\n\n- **Constructors and sizes:** runtimes are 23,479 and 20,539 bytes and initcode 28,320 and 24,814, all within limits.\n- **Index boundaries:** the Solidity bytes equal the art data for all 70 entries, and entries are contiguous and end exactly at the last code byte.\n- **Layer data:** every layer in both chunks decodes with rows summing exactly to width, no zero-length runs, no trailing bytes and no stray colour indices. All layer boxes fit the 84x84 window, and both backgrounds are the full 120x120.\n- **Gas:** launch 2 through a minimal CREATE2 factory costs about 10.64M, under the test's 11.74M budget and the 16.78M transaction cap.\n\nNot reached:\n\n- the real factory's overhead and the policy gas ceiling;\n- whether the attestation service compares on-chain code with the compiler's nominal 16-byte runtime artifact;\n- worst-case `tokenURI` gas across all combos;\n- the other chunks and the renderer beyond how they read chunks 3 and 4.\n\nThe existing suite passes 11 of 11 on the tree as given.","treeHash":null,"usage":{"cachedInputTokens":1189267,"inputTokens":28,"model":"claude-fable-5-1","outputTokens":36349,"runtime":"claude","turns":17,"wallClockMs":781977}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"357c46e3781993d4","findings":[{"citation":"resolved","description":"Launch 2 deploys FrenArtChunk3 and FrenArtChunk4 with no arguments; each constructor returns a STOP byte followed by the raw art as the contract's runtime. The pinned protected floor (.imd/reads/protected/evm_contracts/Contracts.protected.t.sol, test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes) walks every byte of each deployed runtime, skips only PUSH immediates (0x60..0x7f), and asserts no 0xf4 (DELEGATECALL), 0xf2 (CALLCODE) or 0xff (SELFDESTRUCT). It does not stop at the leading STOP, so the art bytes after it are read as opcodes. FrenArtChunk4's runtime contains 234 such bytes, all 0xf4, the first at runtime offset 3912 (this line, byte 8 of the 64-byte literal row 61 of chunk 4). Root cause: 0xf4 = 244 is palette slot SLOT0 (src/FrenRenderer.sol:31, the first coat shade), and every coat layer (coat0/coat1/coat2, index entries 39-41 at art offsets 3896, 4734, 5572 in chunk 4) encodes that placeholder in 78 runs each; a run is (count, index) and no count byte before them is a PUSH, so the scanner sees all 234. FrenArtChunk3 has zero. The execution-trace argument that these bytes are unreachable is correct (pc 0 halts), but it is not what the admission check enforces: with the exact code hashes the renderer demands (src/FrenArtIndex.sol CHUNK_HASHES), the runtime bytes cannot change, so the launch as specified is rejected before the factory transaction is ever sent. ADAPTATION.md records this as reproduced and unresolved; it remains the blocking defect of this launch. Launch 3's FrenArtChunk7 has the same class of problem (14 visible 0xf2/0xff bytes, first at offset 7671, in bg9/palette data). Resolution needs a decision outside the chunk code: either (a) the launch policy's scan treats a runtime whose first byte is STOP as having no reachable code after it (preserves the exact art and hashes the brief requires), or (b) the art kit export and script/art/chunks.py are regenerated so that no scanner-visible 0xf2/0xf4/0xff byte lands in any chunk, e.g. moving the eight placeholder slots from 244..251 to unused palette indices outside {0xf2,0xf4,0xff} (the palette has 193 colours, so 193..241 are free) and renumbering FrenRenderer.SLOT0 to match; that changes every chunk hash, FrenArtIndex, and the renderer across all three launches, and the palette bytes in chunk 7 still need the same treatment.","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 {FrenArtChunk3, FrenArtChunk4} from \"src/FrenArtChunks.sol\";\n\n/// @notice Launch 2 as the factory deploys it (constructors only, no arguments, no value), checked with the exact\n///         runtime traversal of the pinned protected floor (Contracts.protected.t.sol,\n///         test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes). The floor walks the whole runtime, skipping\n///         only PUSH immediates; it does not stop at the leading STOP, so the art bytes after it are read as opcodes.\n///         FrenArtChunk4's coat layers contain palette index 244 (0xf4 = DELEGATECALL) at 234 scanner-visible\n///         positions, so the floor rejects the launch. Fails on the tree as it is; passes once launch 2's runtime\n///         bytes carry no scanner-visible 0xf4 / 0xf2 / 0xff.\ncontract Launch2AdmissionScanTest is Test {\n    function _scan(bytes memory code) internal pure returns (uint256 count, uint256 first) {\n        for (uint256 j; j < code.length; ++j) {\n            uint8 op = uint8(code[j]);\n            if (op >= 0x60 && op <= 0x7f) {\n                j += op - 0x5f;\n                continue;\n            }\n            if (op == 0xf4 || op == 0xf2 || op == 0xff) {\n                if (count == 0) first = j;\n                ++count;\n            }\n        }\n    }\n\n    function _check(address app, string memory name) internal {\n        bytes memory code = app.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        (uint256 count, uint256 first) = _scan(code);\n        emit log_named_uint(string.concat(name, \" scanner-visible forbidden bytes\"), count);\n        emit log_named_uint(string.concat(name, \" first at runtime offset\"), first);\n        assertEq(count, 0, string.concat(name, \": protected floor rejects a forbidden application opcode\"));\n    }\n\n    function test_Launch2RuntimePassesTheProtectedOpcodeScan() public {\n        address c3 = address(new FrenArtChunk3());\n        address c4 = address(new FrenArtChunk4());\n        _check(c3, \"FrenArtChunk3\");\n        _check(c4, \"FrenArtChunk4\");\n    }\n}","reproduction":"State: a fresh EVM. Calls: new FrenArtChunk3(); new FrenArtChunk4() (or the factory's create2 of their creation code with any salt and zero value). Then run the protected floor's traversal over FrenArtChunk4's deployed code: for j in 0..len, skip PUSH immediates, flag 0xf4/0xf2/0xff. Expected (for admission): 0 flagged positions for both chunks. Actual: FrenArtChunk3 0; FrenArtChunk4 234, first at runtime offset 3912 where code[3912] == 0xf4, so the protected test reverts with 'forbidden application opcode' and the launch is not admitted. The attached test fails with 'FrenArtChunk4: protected floor rejects a forbidden application opcode: 234 != 0'.","severity":"high","snippet":"            hex\"f82f00060001f802f401f52f00050001f804f401f52e00050001f805f401f52d00040001f806f401f52d00040001f805f401f801f401f52c00030001f801f70a\"","title":"FrenArtChunk4's runtime fails the protected floor's opcode scan (234 scanner-visible 0xf4 bytes), so launch 2 cannot be admitted as specified"},{"citation":"resolved","description":"The launch-2 suite asserts that chunk 4 carries exactly 234 scanner-visible forbidden bytes with the first at offset 3912. This encodes the defect of the high finding as a requirement rather than guarding the property the launch actually needs (zero scanner-visible 0xf2/0xf4/0xff in each launch-2 runtime). Whoever regenerates the art to clear admission will see 'forge test' fail on this assertion and on the pinned hashes in test_Launch2PreservesExactRuntimeAndFactoryAddresses, which is expected for the hashes but misleading here: the suite then reports the fixed state as broken. The same test file also fixes the chunk-7 count (14 at 7671) for a launch outside this one.","line":49,"path":"test/FrenArtLaunch2.t.sol","reproduction":"State: regenerate src/FrenArtChunks.sol with any art-side fix to the high finding (for example remapping the coat-shade placeholder away from 0xf4) so that FrenArtChunk4's runtime has 0 scanner-visible forbidden bytes. Run forge test --match-test test_ExactLaunch2ArtIsRejectedByCurrentProtectedScan. Expected: a suite that passes when launch 2 is admissible. Actual: the test fails with '0 != 234' at this line even though the launch is now admissible. On the current tree the assertion passes only because the blocker is present.","severity":"low","snippet":"        assertEq(count4, 234);\n        assertEq(first4, 3912);","title":"test_ExactLaunch2ArtIsRejectedByCurrentProtectedScan pins the admission blocker as the expected state, so any art-side fix turns the project's own suite red"}],"hash":"b592fe361e151ad700e473390c6a5194e2f649e9c1194910e33da31db994591e","nodeId":"661dce9c-a9d3-4d68-a04b-8a364e987cbd","outcome":"completed","summary":"The review is complete. The findings file holds two findings, and no tracked file was modified (the findings file and test/scratch/ are untracked and ignored by git status as expected).\n\n**Outcome.** Launch 2's code is correct as data, but it cannot be admitted as specified. One high finding with a failing proof test, one low finding about the test suite.\n\n**Findings written to .imd-findings.json**\n\n- **High: FrenArtChunk4 fails the protected opcode scan.** The pinned protected floor walks the whole runtime, skipping only PUSH immediates, and never stops at the leading STOP. Chunk 4's runtime has 234 scanner-visible DELEGATECALL bytes, the first at offset 3912. Root cause: palette placeholder 244 is the first coat-shade slot and also 0xf4, and all three coat layers in chunk 4 use it in 78 runs each. Chunk 3 is clean. Because the renderer pins exact code hashes, the bytes cannot change, so the conflict needs either a policy-side scan that honours a leading STOP, or a regeneration of the art kit export with placeholder slots moved off 0xf2/0xf4/0xff, which changes all three launches. The proof test in test/scratch/Launch2AdmissionScan.t.sol fails on this tree with the stated message. Chunk 7 in launch 3 has the same class of problem and is noted inside the finding.\n- **Low: the launch-2 suite pins the blocker.** The assertion at test/FrenArtLaunch2.t.sol:49 requires exactly 234 forbidden bytes, so any art-side fix turns the project's own tests red.\n\n**What I verified and found sound**\n\n- Every one of the 70 indexed entries extracted from the deployed chunks equals the art kit's layer or palette file, byte for byte.\n- Code hashes and sizes of all seven deployed chunks match FrenArtIndex, and each runtime starts with STOP.\n- Every layer in chunks 3 and 4 parses as well-formed run-length rows that consume exactly their indexed length, so the renderer never reads past a layer.\n- Every face, coat, shirt, eye, hat, item and background, plus boundary seeds and silhouettes, renders identically to the reference renderer.\n- Constructors are nonpayable, argument-free, use no msg.sender, and initcode sizes (28,320 and 24,814 bytes) sit under the EIP-3860 limit.\n\n**Coverage rows**\n\n| Entry point | Verdict | Reason |\n|---|---|---|\n| FrenArtChunk3 constructor | holds | Returns the literal; value rejected; runtime hash matches the index; zero scanner hits |\n| FrenArtChunk4 constructor | finding 1 | Deploys correctly but its runtime is rejected by the admission scan |\n| FrenArtChunk3/4 runtime (any call, receive) | holds, trust note | STOP at pc 0; any call succeeds and ETH sent by mistake is stranded, a documented self-harm only property, not reported |\n| FrenRenderer constructor hash check | holds | Rejects any chunk whose codehash differs; verified against launch-2 chunks |\n| FrenRenderer._entry reads from chunks 3 and 4 | holds | Bounds check against code length, offsets verified against files |\n| Chunks 1, 2, 5, 6, 7 and renderer views | holds for data integrity; chunk 7 admission noted | Outside my launch, integrity verified in passing |\n\nNot reached: the deployer's real gas ceiling and the factory transaction simulation, which need the service's policy values.","treeHash":null,"usage":{"cachedInputTokens":1508063,"inputTokens":578,"model":"claude-fable-5-1","outputTokens":31687,"runtime":"claude","turns":26,"wallClockMs":710998}},{"artifacts":[],"attempt":1,"bundleHash":"7ae9b077a2225f89dc12f4192cf295ea71197f6f1b3739cf950180943847cf8f","device":"b312209aac1edeae","findings":[],"hash":"ba653510ca8ab4a6fb72dd4385b81c60f321251d68763850f170ef2cb46e5154","nodeId":"381a1cbf-29f0-4e18-8c87-26d015769979","outcome":"completed","summary":"Launch admission remains blocked: the scanner rejects 234 unreachable art bytes that the brief requires preserving.\n\nRecorded all six findings in [.imd-responses.json](/root/nft5/.identitymd/work/fe768074-11d6-47ad-81bb-91960cbb9fdf/381a1cbf-29f0-4e18-8c87-26d015769979/.imd-responses.json) and updated ADAPTATION.md. Disputed the incompatible local repair requirement; contracts remain unchanged.\n\n`forge build` passed; all 11 project tests passed. Both reviewer proofs and the protected admission check still fail as reported. Deployment requires an upstream policy resolution.","treeHash":"e79eea0a515bf2efda5fb260a5f4b0620bcaa528","usage":{"cachedInputTokens":672384,"inputTokens":64267,"model":"gpt-6-astra","outputTokens":7492,"runtime":"codex","turns":4,"wallClockMs":247247}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"47f3603854a893a3","findings":[],"hash":"ca0ca0d7c820fe091526d2deaba4c185b6d8dce9e730cf18443c36d0a02cf07d","nodeId":"ccd401cc-3c07-40bc-8314-01cc8a1adfc2","outcome":"failed","summary":"dependency did not apply: fatal: transport 'file' not allowed\n","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":null,"outputTokens":0,"runtime":"claude","turns":0,"wallClockMs":1047}},{"artifacts":[],"attempt":2,"bundleHash":"9e63fda277be74b4dcbbfb9760a11cace4854ed5f91865970eaca7b191210798","device":"d25fbf67753e5494","findings":[],"hash":"d449e8234c2cebbad1017328f2ed32bf050f482d3c07f93315e506ed53af0517","nodeId":"c34ec7cf-fc45-4b34-8f07-6a55b594e444","outcome":"completed","summary":"Updated only [launch.json](/home/imd-worker/.identitymd/work/fe768074-11d6-47ad-81bb-91960cbb9fdf/c34ec7cf-fc45-4b34-8f07-6a55b594e444/launch.json), preserving `FrenArtChunk3`, then `FrenArtChunk4`, with empty constructor arguments and clarifying deployment notes.\n\nManifest checks and `forge build` passed; `forge test` passed all 11 tests.\n\nThe documented protected-scanner conflict with chunk 4’s unreachable art bytes remains unresolved within the manifest-only scope.","treeHash":"f4375d3d3a8f526df0761faa66e2cdd4cc8f1578","usage":{"cachedInputTokens":381568,"inputTokens":36153,"model":"gpt-6-astra","outputTokens":4239,"runtime":"codex","turns":5,"wallClockMs":238901}},{"artifacts":[],"attempt":1,"bundleHash":"b7cf5c6a97e0d78606df7c9f3a05507ceba92e1d34a35f0ce7f31cdf84d11b55","device":"43eaeedfc1287bf1","findings":[],"hash":"dedf0bf271c12bcdb580a5208814c26ffaa452d046f02692e4d83713c42b22c9","nodeId":"381a1cbf-29f0-4e18-8c87-26d015769979","outcome":"completed","summary":"Added all six finding responses to [.imd-responses.json](/home/imd4/.identitymd/work/fe768074-11d6-47ad-81bb-91960cbb9fdf/381a1cbf-29f0-4e18-8c87-26d015769979/.imd-responses.json) and updated `ADAPTATION.md`. Contracts remain unchanged.\n\n`forge build` and all 11 project tests pass.\n\nLaunch admission remains blocked: both proofs reproduce chunk 4’s 234 rejected bytes. A local repair conflicts with the exact-art requirement; resolution requires an upstream policy or scope decision.","treeHash":"fba9666d6f4a73158149529062ea15cf4dd7eba8","usage":{"cachedInputTokens":922368,"inputTokens":53061,"model":"gpt-6-astra","outputTokens":8439,"runtime":"codex","turns":6,"wallClockMs":306248}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"c0f94d5c3d395bef","findings":[],"hash":"e7d6b77c38ef927b5e45f57aa7ef3c3ffbec650278a4f9fe81e717d1f047e6d2","nodeId":"c34ec7cf-fc45-4b34-8f07-6a55b594e444","outcome":"failed","summary":"the task produced no changes; the agent's last message was: [launch.json](/home/imd3/.identitymd/work/fe768074-11d6-47ad-81bb-91960cbb9fdf/c34ec7cf-fc45-4b34-8f07-6a55b594e444/launch.json) already correctly lists `FrenArtChunk3`, then `FrenArtChunk4`, with empty constructor arguments. No revision was needed.\n\n- Manifest validation and `forge build` passed.\n- `forge test`: all 11 repository tests passed.\n- The protected harness fails on chunk 4’s unreachable art bytes after `STOP`. This cannot be resolved within the manifest-only scope.\n\nNo submitted files changed.","treeHash":null,"usage":{"cachedInputTokens":651264,"inputTokens":32142,"model":"gpt-6-astra","outputTokens":5912,"runtime":"codex","turns":6,"wallClockMs":259240}},{"artifacts":[],"attempt":1,"bundleHash":"e1efe007b225a48d04b177f605f9405207c8321d5c32e84ae808602e7fe1a5ce","device":"ea5566a759ea17b3","findings":[],"hash":"e84dc12844453fd7b97736e3465654a2bc49efc405cd99241e67a1f1136d2135","nodeId":"381a1cbf-29f0-4e18-8c87-26d015769979","outcome":"completed","summary":"Launch remains blocked: the protected scan rejects 234 positions in chunk 4’s art data. Fixing that would violate your requirement to preserve its exact bytes and hash.\n\nProduction code is unchanged. I corrected the gas-budget test, added five regression tests, and documented all findings in [ADAPTATION.md](/home/imd-worker/.identitymd/work/fe768074-11d6-47ad-81bb-91960cbb9fdf/381a1cbf-29f0-4e18-8c87-26d015769979/ADAPTATION.md).\n\n`forge build` passed; `forge test` passed all 11 tests. The protected admission check still fails.","treeHash":"6033ad1af059a943e3ffb843c81c5c0ba7125c45","usage":{"cachedInputTokens":1538432,"inputTokens":78054,"model":"gpt-6-astra","outputTokens":17065,"runtime":"codex","turns":8,"wallClockMs":682648}}],"verification":[{"checks":[{"durationMs":71047,"exitCode":0,"name":"build","output":"Compiling 37 files with Solc 0.8.30\nSolc 0.8.30 finished in 70.78s\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:143:21\n    │\n143 │                 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:144:54\n    │\n144 │                     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:221:41\n    │\n221 │         _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:221:61\n    │\n221 │         _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:222:79\n    │\n222 │         _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:222:92\n    │\n222 │         _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:223:36\n    │\n223 │         _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:223:49\n    │\n223 │         _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:226:55\n    │\n226 │         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:226:68\n    │\n226 │         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:228:57\n    │\n228 │         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:228:70\n    │\n228 │         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:25\n    │\n239 │             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:240:40\n    │\n240 │             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:248:32\n    │\n248 │                     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:249:36\n    │\n249 │                     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:251:29\n    │\n251 │                     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:251:44\n    │\n251 │                     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:252:36\n    │\n252 │                     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:253:65\n    │\n253 │                     for (int256 xx = a; xx < b; ++xx) 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:253:87\n    │\n253 │                     for (int256 xx = a; xx < b; ++xx) 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:261:56\n    │\n261 │         for (uint256 i; i < n; ++i) 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\n","passed":true},{"durationMs":3559,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 8 tests for test/FrenArtLaunch2Data.t.sol:FrenArtLaunch2DataTest\n[PASS] testFuzz_RendererRejectsAnySingleByteCorruption(bool,uint256,uint8) (runs: 1000, μ: 44844, ~: 45547)\nLogs:\n  Bound result 1702\n  Bound result 1\n\n[PASS] test_EveryLaunch2LayerMatchesItsOriginalBinaryAndCoversAllPayloadBytes() (gas: 451325)\n[PASS] test_RendererRejectsCorruptedFirstAndLastBytesEvenWithCorrectSize() (gas: 36864)\n[PASS] test_RendererRejectsMissingEOAAndOtherLaunchChunksInBothSlots() (gas: 24909)\n[PASS] test_RendererRejectsSwappedOrDuplicatedLaunch2Chunks() (gas: 20263)\n[PASS] test_RendererRejectsTruncatedAndAppendedRuntime() (gas: 49240)\n[PASS] test_RendererReportsMissingWhenLaunch2DataIsUnavailableAtReadTime() (gas: 3735735)\n[PASS] test_RendererUsesLaunch2ChunksInTheirSpecifiedSlots() (gas: 19587)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 37.07ms (58.09ms CPU time)\n\nRan 9 tests for test/FrenArtLaunch2.t.sol:FrenArtLaunch2Test\n[PASS] testFuzz_NonzeroDeploymentValueRollsBackAndSaltCanBeRetried(uint256,uint256) (runs: 1000, μ: 10873067, ~: 10872816)\nLogs:\n  Bound result 1\n  Bound result 244\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n\n[PASS] test_DeploymentValueBoundaries() (gas: 21768265)\nLogs:\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n\n[PASS] test_DuplicateCreate2CannotReplaceEitherChunk() (gas: 229360)\n[PASS] test_Launch2ConstructorsRejectValue() (gas: 1029575)\n[PASS] test_Launch2PreservesExactRuntimeAndFactoryAddresses() (gas: 112001)\n[PASS] test_Launch2RetainsDocumentedEthSink() (gas: 120391)\n[PASS] test_RejectedDeploymentPreservesPrefundingAndCanBeRetried() (gas: 10867459)\nLogs:\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n\n[PASS] test_SameSaltForDifferentChunksProducesDistinctCorrectAddresses() (gas: 9964518)\nLogs:\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n\n[PASS] test_ZeroValueDeploymentWorksAtPrefundedAddresses() (gas: 9894165)\nLogs:\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 147.22ms (154.68ms CPU time)\n\nRan 6 tests for test/FrenRenderer.t.sol:FrenRendererTest\n[PASS] test_LaunchesFitTransactions() (gas: 60894)\nLogs:\n  launch 1 gas budget (with calldata and allowance): 12614648\n  launch 2 gas budget (with calldata and allowance): 11731672\n  launch 3 gas budget (with calldata and allowance): 15501064\n\n[PASS] test_MatchesTheReference() (gas: 54321184)\n[PASS] test_RejectsCombosOutsideTheArt() (gas: 11029957)\n[PASS] test_SameAsTheLaunchRenderer() (gas: 912530422)\n[PASS] test_TakesOnlyThisArt() (gas: 19364)\n[PASS] test_TokenURIIsCheapEnoughToRead() (gas: 12987078)\nLogs:\n  tokenURI gas: 12981115\n\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 2.53s (2.75s CPU time)\n\nRan 3 tests for test/FrenArtLaunch2Invariant.t.sol:FrenArtLaunch2InvariantTest\n[PASS]\nFrenArtLaunch2InvariantTest invariants:\n[PASS] invariant_EthConservedAcrossActorsAndBothChunks\n[PASS] invariant_RuntimeRemainsExactAfterEveryCallSequence\n FrenArtLaunch2InvariantTest invariants (runs: 256, calls: 16384, reverts: 0)\n\n╭--------------------+-----------------------+-------+---------+----------╮\n| Contract           | Selector              | Calls | Reverts | Discards |\n+=========================================================================+\n| Launch2CallHandler | callChunk             | 5310  | 0       | 0        |\n|--------------------+-----------------------+-------+---------+----------|\n| Launch2CallHandler | insufficientFundsCall | 5591  | 0       | 0        |\n|--------------------+-----------------------+-------+---------+----------|\n| Launch2CallHandler | staticProbe           | 5483  | 0       | 0        |\n╰--------------------+-----------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 29\n  Bound result 0\n  Bound result 1\n  Bound result 4059\n  Bound result 0\n  Bound result 0\n  Bound result 10\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 828417\n  Bound result 1\n  Bound result 0\n  Bound result 6323\n  Bound result 0\n  Bound result 2\n  Bound result 101\n  Bound result 1\n  Bound result 0\n  Bound result 3925\n  Bound result 0\n  Bound result 1\n  Bound result 2506\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 2\n  Bound result 0\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 2\n  Bound result 6815744\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 2\n  Bound result 52\n  Bound result 0\n  Bound result 1\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 24\n  Bound result 0\n  Bound result 2\n  Bound result 425586787646968237735\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 161122133888489375508\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 2304\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 6405\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 18\n  Bound result 0\n  Bound result 2\n  Bound result 2687075371\n  Bound result 0\n  Bound result 0\n  Bound result 565\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 2\n  Bound result 155450001823505726585\n  Bound result 1\n  Bound result 1\n  Bound result 999999999999999156277\n  Bound result 1\n  Bound result 0\n  Bound result 107477463\n  Bound result 0\n  Bound result 0\n  Bound result 16384\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 2\n\n[PASS] test_EmptyCalldataSelectorsAndValueEdges() (gas: 1363960)\nLogs:\n  Bound result 0\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 2\n  Bound result 1000000000000000000\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 2\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 2\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 1000000000000000000\n  Bound result 1\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 2\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 2\n\n[PASS] test_FullBalanceThenEmptyActorCallsConserveEth() (gas: 2548392)\nLogs:\n  Bound result 0\n  Bound result 0\n  Bound result 500000000000000000000\n  Bound result 1\n  Bound result 0\n  Bound result 500000000000000000000\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 1\n  Bound result 0\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 1\n  Bound result 500000000000000000000\n  Bound result 0\n  Bound result 1\n  Bound result 500000000000000000000\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 0\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 2\n  Bound result 500000000000000000000\n  Bound result 1\n  Bound result 2\n  Bound result 500000000000000000000\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 2\n  Bound result 0\n  Bound result 1\n  Bound result 2\n\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 3.38s (3.38s CPU time)\n\nRan 4 test suites in 3.39s (6.10s CPU time): 26 tests passed, 0 failed, 0 skipped (26 total tests)\n","passed":true},{"durationMs":98,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":185,\"README.md\":51,\"foundry.toml\":22,\"script/art/chunks.py\":88,\"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,\"src/FrenArtChunks.sol\":2298,\"src/FrenArtIndex.sol\":32,\"src/FrenRenderer.sol\":285,\"test/FrenArtLaunch2.t.sol\":183,\"test/FrenArtLaunch2Data.t.sol\":158,\"test/FrenArtLaunch2Invariant.t.sol\":167,\"test/FrenRenderer.t.sol\":186,\"test/ref/FrenRendererRef.sol\":313},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"1b1fde72e78678a024bc01494448d507535b7ea76de633e3f61ccfe162ff27a3","verifiedTreeHash":"45ad299fe07eaa6a698693823e1708f7d4350bff","verifierVersion":"0.1.0+94826a22"},{"checks":[{"durationMs":29432,"exitCode":0,"name":"build","output":"Compiling 35 files with Solc 0.8.30\nSolc 0.8.30 finished in 29.33s\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:144:54\n    │\n144 │                     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:143:21\n    │\n143 │                 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:221:41\n    │\n221 │         _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:221:61\n    │\n221 │         _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:222:79\n    │\n222 │         _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:222:92\n    │\n222 │         _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:223:36\n    │\n223 │         _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:223:49\n    │\n223 │         _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:226:55\n    │\n226 │         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:226:68\n    │\n226 │         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:228:57\n    │\n228 │         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:228:70\n    │\n228 │         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:25\n    │\n239 │             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:240:40\n    │\n240 │             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:248:32\n    │\n248 │                     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:249:36\n    │\n249 │                     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:251:29\n    │\n251 │                     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:251:44\n    │\n251 │                     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:252:36\n    │\n252 │                     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:253:65\n    │\n253 │                     for (int256 xx = a; xx < b; ++xx) 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:253:87\n    │\n253 │                     for (int256 xx = a; xx < b; ++xx) 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:261:56\n    │\n261 │         for (uint256 i; i < n; ++i) 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\n","passed":true},{"durationMs":1448,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 5 tests for test/FrenArtLaunch2.t.sol:FrenArtLaunch2Test\n[PASS] test_Chunk7AlsoHasTheReportedAdmissionBlocker() (gas: 4792593)\n[PASS] test_ExactLaunch2ArtIsRejectedByCurrentProtectedScan() (gas: 14689176)\n[PASS] test_Launch2ConstructorsRejectValue() (gas: 1029478)\n[PASS] test_Launch2PreservesExactRuntimeAndFactoryAddresses() (gas: 111978)\n[PASS] test_Launch2RetainsDocumentedEthSink() (gas: 120360)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 1.35s (30.50ms CPU time)\n\nRan 6 tests for test/FrenRenderer.t.sol:FrenRendererTest\n[PASS] test_LaunchesFitTransactions() (gas: 60894)\nLogs:\n  launch 1 gas budget (with calldata and allowance): 12614648\n  launch 2 gas budget (with calldata and allowance): 11731672\n  launch 3 gas budget (with calldata and allowance): 15501064\n\n[PASS] test_MatchesTheReference() (gas: 54321184)\n[PASS] test_RejectsCombosOutsideTheArt() (gas: 11029957)\n[PASS] test_SameAsTheLaunchRenderer() (gas: 913046892)\n[PASS] test_TakesOnlyThisArt() (gas: 19364)\n[PASS] test_TokenURIIsCheapEnoughToRead() (gas: 12987078)\nLogs:\n  tokenURI gas: 12981115\n\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 1.35s (1.46s CPU time)\n\nRan 2 test suites in 1.35s (2.71s CPU time): 11 tests passed, 0 failed, 0 skipped (11 total tests)\n","passed":true},{"durationMs":46,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":185,\"README.md\":51,\"foundry.toml\":22,\"launch.json\":14,\"script/art/chunks.py\":88,\"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,\"src/FrenArtChunks.sol\":2298,\"src/FrenArtIndex.sol\":32,\"src/FrenRenderer.sol\":285,\"test/FrenArtLaunch2.t.sol\":120,\"test/FrenRenderer.t.sol\":186,\"test/ref/FrenRendererRef.sol\":313},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"2ce84c2a8e19de93fedbce0e420e9b4f624751d275ae9355ffdfd3b948d8faff","verifiedTreeHash":"b537a979026cfdb09dd10016cb44ce6cf899b66d","verifierVersion":"0.1.0+94826a22"},{"checks":[{"durationMs":33360,"exitCode":0,"name":"build","output":"Compiling 35 files with Solc 0.8.30\nSolc 0.8.30 finished in 33.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:143:21\n    │\n143 │                 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:144:54\n    │\n144 │                     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:221:41\n    │\n221 │         _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:221:61\n    │\n221 │         _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:222:79\n    │\n222 │         _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:222:92\n    │\n222 │         _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:223:36\n    │\n223 │         _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:223:49\n    │\n223 │         _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:226:55\n    │\n226 │         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:226:68\n    │\n226 │         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:228:57\n    │\n228 │         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:228:70\n    │\n228 │         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:25\n    │\n239 │             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:240:40\n    │\n240 │             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:248:32\n    │\n248 │                     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:249:36\n    │\n249 │                     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:251:29\n    │\n251 │                     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:251:44\n    │\n251 │                     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:252:36\n    │\n252 │                     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:253:65\n    │\n253 │                     for (int256 xx = a; xx < b; ++xx) 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:253:87\n    │\n253 │                     for (int256 xx = a; xx < b; ++xx) 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:261:56\n    │\n261 │         for (uint256 i; i < n; ++i) 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\n","passed":true},{"durationMs":1513,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 5 tests for test/FrenArtLaunch2.t.sol:FrenArtLaunch2Test\n[PASS] test_Chunk7AlsoHasTheReportedAdmissionBlocker() (gas: 4792593)\n[PASS] test_ExactLaunch2ArtIsRejectedByCurrentProtectedScan() (gas: 14689176)\n[PASS] test_Launch2ConstructorsRejectValue() (gas: 1029478)\n[PASS] test_Launch2PreservesExactRuntimeAndFactoryAddresses() (gas: 111978)\n[PASS] test_Launch2RetainsDocumentedEthSink() (gas: 120360)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 29.35ms (34.47ms CPU time)\n\nRan 6 tests for test/FrenRenderer.t.sol:FrenRendererTest\n[PASS] test_LaunchesFitTransactions() (gas: 60894)\nLogs:\n  launch 1 gas budget (with calldata and allowance): 12614648\n  launch 2 gas budget (with calldata and allowance): 11731672\n  launch 3 gas budget (with calldata and allowance): 15501064\n\n[PASS] test_MatchesTheReference() (gas: 54321184)\n[PASS] test_RejectsCombosOutsideTheArt() (gas: 11029957)\n[PASS] test_SameAsTheLaunchRenderer() (gas: 913046892)\n[PASS] test_TakesOnlyThisArt() (gas: 19364)\n[PASS] test_TokenURIIsCheapEnoughToRead() (gas: 12987078)\nLogs:\n  tokenURI gas: 12981115\n\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 1.38s (1.51s CPU time)\n\nRan 2 test suites in 1.38s (1.40s CPU time): 11 tests passed, 0 failed, 0 skipped (11 total tests)\n","passed":true},{"durationMs":86,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":85,\"README.md\":51,\"foundry.toml\":22,\"launch.json\":14,\"script/art/chunks.py\":88,\"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,\"src/FrenArtChunks.sol\":2298,\"src/FrenArtIndex.sol\":32,\"src/FrenRenderer.sol\":285,\"test/FrenArtLaunch2.t.sol\":120,\"test/FrenRenderer.t.sol\":186,\"test/ref/FrenRendererRef.sol\":313},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"5dbf4f87b477c93cb294565c43cf16fa070af9f905bbe5a239433e834374cf25","verifiedTreeHash":"1217bd57db3579bfbceeaac34d9eed041cbd41b1","verifierVersion":"0.1.0+e6140b7a"},{"checks":[{"durationMs":83584,"exitCode":0,"name":"build","output":"Compiling 37 files with Solc 0.8.30\nSolc 0.8.30 finished in 83.27s\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:144:54\n    │\n144 │                     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:143:21\n    │\n143 │                 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:221:41\n    │\n221 │         _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:221:61\n    │\n221 │         _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:222:79\n    │\n222 │         _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:222:92\n    │\n222 │         _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:223:36\n    │\n223 │         _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:223:49\n    │\n223 │         _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:226:55\n    │\n226 │         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:226:68\n    │\n226 │         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:228:57\n    │\n228 │         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:228:70\n    │\n228 │         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:25\n    │\n239 │             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:240:40\n    │\n240 │             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:248:32\n    │\n248 │                     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:249:36\n    │\n249 │                     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:251:29\n    │\n251 │                     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:251:44\n    │\n251 │                     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:252:36\n    │\n252 │                     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:253:65\n    │\n253 │                     for (int256 xx = a; xx < b; ++xx) 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:253:87\n    │\n253 │                     for (int256 xx = a; xx < b; ++xx) 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:261:56\n    │\n261 │         for (uint256 i; i < n; ++i) 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\n","passed":true},{"durationMs":5093,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 8 tests for test/FrenArtLaunch2Data.t.sol:FrenArtLaunch2DataTest\n[PASS] testFuzz_RendererRejectsAnySingleByteCorruption(bool,uint256,uint8) (runs: 1000, μ: 44836, ~: 45547)\nLogs:\n  Bound result 1058\n  Bound result 1\n\n[PASS] test_EveryLaunch2LayerMatchesItsOriginalBinaryAndCoversAllPayloadBytes() (gas: 451325)\n[PASS] test_RendererRejectsCorruptedFirstAndLastBytesEvenWithCorrectSize() (gas: 36864)\n[PASS] test_RendererRejectsMissingEOAAndOtherLaunchChunksInBothSlots() (gas: 24909)\n[PASS] test_RendererRejectsSwappedOrDuplicatedLaunch2Chunks() (gas: 20263)\n[PASS] test_RendererRejectsTruncatedAndAppendedRuntime() (gas: 49240)\n[PASS] test_RendererReportsMissingWhenLaunch2DataIsUnavailableAtReadTime() (gas: 3735735)\n[PASS] test_RendererUsesLaunch2ChunksInTheirSpecifiedSlots() (gas: 19587)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 144.49ms (217.11ms CPU time)\n\nRan 8 tests for test/FrenArtLaunch2.t.sol:FrenArtLaunch2Test\n[PASS] testFuzz_NonzeroDeploymentValueRollsBackAndSaltCanBeRetried(uint256,uint256) (runs: 1000, μ: 10873063, ~: 10872887)\nLogs:\n  Bound result 2052737143933426469978479097748976603533644871679587\n  Bound result 115792089237316195423570985008687907853269984665640564039457584007913129639935\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n\n[PASS] test_DeploymentValueBoundaries() (gas: 21768020)\nLogs:\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n\n[PASS] test_DuplicateCreate2CannotReplaceEitherChunk() (gas: 229361)\n[PASS] test_Launch2ConstructorsRejectValue() (gas: 1029575)\n[PASS] test_Launch2PreservesExactRuntimeAndFactoryAddresses() (gas: 112001)\n[PASS] test_Launch2RetainsDocumentedEthSink() (gas: 120391)\n[PASS] test_SameSaltForDifferentChunksProducesDistinctCorrectAddresses() (gas: 9964519)\nLogs:\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n\n[PASS] test_ZeroValueDeploymentWorksAtPrefundedAddresses() (gas: 9894165)\nLogs:\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 435.09ms (470.76ms CPU time)\n\nRan 6 tests for test/FrenRenderer.t.sol:FrenRendererTest\n[PASS] test_LaunchesFitTransactions() (gas: 60894)\nLogs:\n  launch 1 gas budget (with calldata and allowance): 12614648\n  launch 2 gas budget (with calldata and allowance): 11731672\n  launch 3 gas budget (with calldata and allowance): 15501064\n\n[PASS] test_MatchesTheReference() (gas: 54321184)\n[PASS] test_RejectsCombosOutsideTheArt() (gas: 11029957)\n[PASS] test_SameAsTheLaunchRenderer() (gas: 912530446)\n[PASS] test_TakesOnlyThisArt() (gas: 19364)\n[PASS] test_TokenURIIsCheapEnoughToRead() (gas: 12987078)\nLogs:\n  tokenURI gas: 12981115\n\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 3.74s (4.23s CPU time)\n\nRan 2 tests for test/FrenArtLaunch2Invariant.t.sol:FrenArtLaunch2InvariantTest\n[PASS]\nFrenArtLaunch2InvariantTest invariants:\n[PASS] invariant_EthConservedAcrossActorsAndBothChunks\n[PASS] invariant_RuntimeRemainsExactAfterEveryCallSequence\n FrenArtLaunch2InvariantTest invariants (runs: 256, calls: 16384, reverts: 0)\n\n╭--------------------+-----------------------+-------+---------+----------╮\n| Contract           | Selector              | Calls | Reverts | Discards |\n+=========================================================================+\n| Launch2CallHandler | callChunk             | 5368  | 0       | 0        |\n|--------------------+-----------------------+-------+---------+----------|\n| Launch2CallHandler | insufficientFundsCall | 5510  | 0       | 0        |\n|--------------------+-----------------------+-------+---------+----------|\n| Launch2CallHandler | staticProbe           | 5506  | 0       | 0        |\n╰--------------------+-----------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 14\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 2\n  Bound result 3415\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 1\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 66622159246574885\n  Bound result 0\n  Bound result 0\n  Bound result 52\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 607773535309637339\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 8000000\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 0\n  Bound result 8410\n  Bound result 1\n  Bound result 0\n  Bound result 24576\n  Bound result 1\n  Bound result 0\n  Bound result 102\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 1446\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 101\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 548883277760758126\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 860739116233275379\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 2\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 89\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 1389142\n  Bound result 0\n  Bound result 2\n  Bound result 2048\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 146552179359089266\n  Bound result 0\n  Bound result 2\n  Bound result 24289079\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 2000000\n  Bound result 1\n  Bound result 0\n  Bound result 7864320\n  Bound result 0\n  Bound result 2\n  Bound result 16\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 0\n  Bound result 0\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 12\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 18\n\n[PASS] test_EmptyCalldataSelectorsAndValueEdges() (gas: 1364619)\nLogs:\n  Bound result 0\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 2\n  Bound result 1000000000000000000\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 2\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 2\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 1000000000000000000\n  Bound result 1\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 2\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 2\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.79s (4.77s CPU time)\n\nRan 4 test suites in 4.79s (9.11s CPU time): 24 tests passed, 0 failed, 0 skipped (24 total tests)\n","passed":true},{"durationMs":132,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":85,\"README.md\":51,\"foundry.toml\":22,\"script/art/chunks.py\":88,\"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,\"src/FrenArtChunks.sol\":2298,\"src/FrenArtIndex.sol\":32,\"src/FrenRenderer.sol\":285,\"test/FrenArtLaunch2.t.sol\":158,\"test/FrenArtLaunch2Data.t.sol\":158,\"test/FrenArtLaunch2Invariant.t.sol\":145,\"test/FrenRenderer.t.sol\":186,\"test/ref/FrenRendererRef.sol\":313},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"78288b5dcee21e61456e028f1ba2ff3ff8c434ee7b5c53f6c82ced9e022828a4","verifiedTreeHash":"caee43f9c10062b837518cb15406fcaf4d74c7f8","verifierVersion":"0.1.0+e6140b7a"},{"checks":[{"durationMs":35228,"exitCode":0,"name":"build","output":"Compiling 37 files with Solc 0.8.30\nSolc 0.8.30 finished in 35.10s\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:144:54\n    │\n144 │                     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:143:21\n    │\n143 │                 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:221:41\n    │\n221 │         _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:221:61\n    │\n221 │         _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:222:79\n    │\n222 │         _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:222:92\n    │\n222 │         _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:223:36\n    │\n223 │         _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:223:49\n    │\n223 │         _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:226:55\n    │\n226 │         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:226:68\n    │\n226 │         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:228:57\n    │\n228 │         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:228:70\n    │\n228 │         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:25\n    │\n239 │             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:240:40\n    │\n240 │             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:248:32\n    │\n248 │                     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:249:36\n    │\n249 │                     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:251:29\n    │\n251 │                     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:251:44\n    │\n251 │                     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:252:36\n    │\n252 │                     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:253:65\n    │\n253 │                     for (int256 xx = a; xx < b; ++xx) 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:253:87\n    │\n253 │                     for (int256 xx = a; xx < b; ++xx) 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:261:56\n    │\n261 │         for (uint256 i; i < n; ++i) 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\n","passed":true},{"durationMs":2048,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 8 tests for test/FrenArtLaunch2.t.sol:FrenArtLaunch2Test\n[PASS] testFuzz_NonzeroDeploymentValueRollsBackAndSaltCanBeRetried(uint256,uint256) (runs: 1000, μ: 10873015, ~: 10872839)\nLogs:\n  Bound result 1\n  Bound result 1366\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n\n[PASS] test_DeploymentValueBoundaries() (gas: 21768020)\nLogs:\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n\n[PASS] test_DuplicateCreate2CannotReplaceEitherChunk() (gas: 229361)\n[PASS] test_Launch2ConstructorsRejectValue() (gas: 1029575)\n[PASS] test_Launch2PreservesExactRuntimeAndFactoryAddresses() (gas: 112001)\n[PASS] test_Launch2RetainsDocumentedEthSink() (gas: 120391)\n[PASS] test_SameSaltForDifferentChunksProducesDistinctCorrectAddresses() (gas: 9964519)\nLogs:\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n\n[PASS] test_ZeroValueDeploymentWorksAtPrefundedAddresses() (gas: 9894165)\nLogs:\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n  computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.\n\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 95.46ms (101.67ms CPU time)\n\nRan 8 tests for test/FrenArtLaunch2Data.t.sol:FrenArtLaunch2DataTest\n[PASS] testFuzz_RendererRejectsAnySingleByteCorruption(bool,uint256,uint8) (runs: 1000, μ: 44825, ~: 45547)\nLogs:\n  Bound result 2670\n  Bound result 52\n\n[PASS] test_EveryLaunch2LayerMatchesItsOriginalBinaryAndCoversAllPayloadBytes() (gas: 451325)\n[PASS] test_RendererRejectsCorruptedFirstAndLastBytesEvenWithCorrectSize() (gas: 36864)\n[PASS] test_RendererRejectsMissingEOAAndOtherLaunchChunksInBothSlots() (gas: 24909)\n[PASS] test_RendererRejectsSwappedOrDuplicatedLaunch2Chunks() (gas: 20263)\n[PASS] test_RendererRejectsTruncatedAndAppendedRuntime() (gas: 49240)\n[PASS] test_RendererReportsMissingWhenLaunch2DataIsUnavailableAtReadTime() (gas: 3735735)\n[PASS] test_RendererUsesLaunch2ChunksInTheirSpecifiedSlots() (gas: 19587)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 1.50s (61.91ms CPU time)\n\nRan 6 tests for test/FrenRenderer.t.sol:FrenRendererTest\n[PASS] test_LaunchesFitTransactions() (gas: 60894)\nLogs:\n  launch 1 gas budget (with calldata and allowance): 12614648\n  launch 2 gas budget (with calldata and allowance): 11731672\n  launch 3 gas budget (with calldata and allowance): 15501064\n\n[PASS] test_MatchesTheReference() (gas: 54321184)\n[PASS] test_RejectsCombosOutsideTheArt() (gas: 11029957)\n[PASS] test_SameAsTheLaunchRenderer() (gas: 908967830)\n[PASS] test_TakesOnlyThisArt() (gas: 19364)\n[PASS] test_TokenURIIsCheapEnoughToRead() (gas: 12987078)\nLogs:\n  tokenURI gas: 12981115\n\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 1.50s (1.63s CPU time)\n\nRan 3 tests for test/FrenArtLaunch2Invariant.t.sol:FrenArtLaunch2InvariantTest\n[PASS]\nFrenArtLaunch2InvariantTest invariants:\n[PASS] invariant_EthConservedAcrossActorsAndBothChunks\n[PASS] invariant_RuntimeRemainsExactAfterEveryCallSequence\n FrenArtLaunch2InvariantTest invariants (runs: 256, calls: 16384, reverts: 0)\n\n╭--------------------+-----------------------+-------+---------+----------╮\n| Contract           | Selector              | Calls | Reverts | Discards |\n+=========================================================================+\n| Launch2CallHandler | callChunk             | 5607  | 0       | 0        |\n|--------------------+-----------------------+-------+---------+----------|\n| Launch2CallHandler | insufficientFundsCall | 5331  | 0       | 0        |\n|--------------------+-----------------------+-------+---------+----------|\n| Launch2CallHandler | staticProbe           | 5446  | 0       | 0        |\n╰--------------------+-----------------------+-------+---------+----------╯\n\nLogs:\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 0\n  Bound result 1\n  Bound result 2\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 2\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 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 3\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 247975740869367419208\n  Bound result 1\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 0\n  Bound result 8339\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 14\n  Bound result 0\n  Bound result 0\n  Bound result 696684778670112941295\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 19\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 2\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 29009435555360146999\n  Bound result 1\n  Bound result 2\n  Bound result 1990\n  Bound result 1\n  Bound result 2\n  Bound result 317170\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 7346\n  Bound result 0\n  Bound result 0\n  Bound result 5011\n  Bound result 0\n  Bound result 2\n  Bound result 659918\n  Bound result 1\n  Bound result 1\n  Bound result 2637\n  Bound result 0\n  Bound result 2\n  Bound result 528440157008867356637\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 1\n  Bound result 2921\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 828417\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 235693624198798146430\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 589\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 0\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\n[PASS] test_EmptyCalldataSelectorsAndValueEdges() (gas: 1363960)\nLogs:\n  Bound result 0\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 2\n  Bound result 1000000000000000000\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 2\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 2\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 1000000000000000000\n  Bound result 1\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 2\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 2\n\n[PASS] test_FullBalanceThenEmptyActorCallsConserveEth() (gas: 2548392)\nLogs:\n  Bound result 0\n  Bound result 0\n  Bound result 500000000000000000000\n  Bound result 1\n  Bound result 0\n  Bound result 500000000000000000000\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 1\n  Bound result 0\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 1\n  Bound result 500000000000000000000\n  Bound result 0\n  Bound result 1\n  Bound result 500000000000000000000\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 0\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 2\n  Bound result 500000000000000000000\n  Bound result 1\n  Bound result 2\n  Bound result 500000000000000000000\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 2\n  Bound result 0\n  Bound result 1\n  Bound result 2\n\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 1.95s (1.96s CPU time)\n\nRan 4 test suites in 1.96s (5.04s CPU time): 25 tests passed, 0 failed, 0 skipped (25 total tests)\n","passed":true},{"durationMs":60,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":137,\"README.md\":51,\"foundry.toml\":22,\"script/art/chunks.py\":88,\"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,\"src/FrenArtChunks.sol\":2298,\"src/FrenArtIndex.sol\":32,\"src/FrenRenderer.sol\":285,\"test/FrenArtLaunch2.t.sol\":158,\"test/FrenArtLaunch2Data.t.sol\":158,\"test/FrenArtLaunch2Invariant.t.sol\":167,\"test/FrenRenderer.t.sol\":186,\"test/ref/FrenRendererRef.sol\":313},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"82ffb08562bf1b0996a7ae1a16f70b1e9c62dc0d53b3b531a8fd81c1bc1a023a","verifiedTreeHash":"42591b7cd25d9274e8610ba5247b4fcb47c19f33","verifierVersion":"0.1.0+94826a22"},{"checks":[{"durationMs":27913,"exitCode":0,"name":"build","output":"Compiling 35 files with Solc 0.8.30\nSolc 0.8.30 finished in 27.81s\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:144:54\n    │\n144 │                     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:143:21\n    │\n143 │                 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:221:41\n    │\n221 │         _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:221:61\n    │\n221 │         _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:222:79\n    │\n222 │         _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:222:92\n    │\n222 │         _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:223:36\n    │\n223 │         _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:223:49\n    │\n223 │         _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:226:55\n    │\n226 │         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:226:68\n    │\n226 │         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:228:57\n    │\n228 │         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:228:70\n    │\n228 │         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:25\n    │\n239 │             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:240:40\n    │\n240 │             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:248:32\n    │\n248 │                     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:249:36\n    │\n249 │                     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:251:29\n    │\n251 │                     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:251:44\n    │\n251 │                     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:252:36\n    │\n252 │                     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:253:65\n    │\n253 │                     for (int256 xx = a; xx < b; ++xx) 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:253:87\n    │\n253 │                     for (int256 xx = a; xx < b; ++xx) 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:261:56\n    │\n261 │         for (uint256 i; i < n; ++i) 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\n","passed":true},{"durationMs":1524,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 5 tests for test/FrenArtLaunch2.t.sol:FrenArtLaunch2Test\n[PASS] test_Chunk7AlsoHasTheReportedAdmissionBlocker() (gas: 4792593)\n[PASS] test_ExactLaunch2ArtIsRejectedByCurrentProtectedScan() (gas: 14689176)\n[PASS] test_Launch2ConstructorsRejectValue() (gas: 1029478)\n[PASS] test_Launch2PreservesExactRuntimeAndFactoryAddresses() (gas: 111978)\n[PASS] test_Launch2RetainsDocumentedEthSink() (gas: 120360)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 1.40s (39.57ms CPU time)\n\nRan 6 tests for test/FrenRenderer.t.sol:FrenRendererTest\n[PASS] test_LaunchesFitTransactions() (gas: 60894)\nLogs:\n  launch 1 gas budget (with calldata and allowance): 12614648\n  launch 2 gas budget (with calldata and allowance): 11731672\n  launch 3 gas budget (with calldata and allowance): 15501064\n\n[PASS] test_MatchesTheReference() (gas: 54321184)\n[PASS] test_RejectsCombosOutsideTheArt() (gas: 11029957)\n[PASS] test_SameAsTheLaunchRenderer() (gas: 913046892)\n[PASS] test_TakesOnlyThisArt() (gas: 19364)\n[PASS] test_TokenURIIsCheapEnoughToRead() (gas: 12987078)\nLogs:\n  tokenURI gas: 12981115\n\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 1.40s (1.54s CPU time)\n\nRan 2 test suites in 1.41s (2.81s CPU time): 11 tests passed, 0 failed, 0 skipped (11 total tests)\n","passed":true},{"durationMs":44,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":137,\"README.md\":51,\"foundry.toml\":22,\"script/art/chunks.py\":88,\"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,\"src/FrenArtChunks.sol\":2298,\"src/FrenArtIndex.sol\":32,\"src/FrenRenderer.sol\":285,\"test/FrenArtLaunch2.t.sol\":120,\"test/FrenRenderer.t.sol\":186,\"test/ref/FrenRendererRef.sol\":313},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"ba653510ca8ab4a6fb72dd4385b81c60f321251d68763850f170ef2cb46e5154","verifiedTreeHash":"e79eea0a515bf2efda5fb260a5f4b0620bcaa528","verifierVersion":"0.1.0+94826a22"},{"checks":[{"durationMs":36837,"exitCode":0,"name":"build","output":"Compiling 35 files with Solc 0.8.30\nSolc 0.8.30 finished in 36.71s\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:144:54\n    │\n144 │                     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:143:21\n    │\n143 │                 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:221:41\n    │\n221 │         _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:221:61\n    │\n221 │         _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:222:79\n    │\n222 │         _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:222:92\n    │\n222 │         _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:223:36\n    │\n223 │         _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:223:49\n    │\n223 │         _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:226:55\n    │\n226 │         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:226:68\n    │\n226 │         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:228:57\n    │\n228 │         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:228:70\n    │\n228 │         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:25\n    │\n239 │             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:240:40\n    │\n240 │             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:248:32\n    │\n248 │                     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:249:36\n    │\n249 │                     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:251:29\n    │\n251 │                     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:251:44\n    │\n251 │                     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:252:36\n    │\n252 │                     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:253:65\n    │\n253 │                     for (int256 xx = a; xx < b; ++xx) 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:253:87\n    │\n253 │                     for (int256 xx = a; xx < b; ++xx) 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:261:56\n    │\n261 │         for (uint256 i; i < n; ++i) 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\n","passed":true},{"durationMs":1805,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 5 tests for test/FrenArtLaunch2.t.sol:FrenArtLaunch2Test\n[PASS] test_Chunk7AlsoHasTheReportedAdmissionBlocker() (gas: 4792593)\n[PASS] test_ExactLaunch2ArtIsRejectedByCurrentProtectedScan() (gas: 14689176)\n[PASS] test_Launch2ConstructorsRejectValue() (gas: 1029478)\n[PASS] test_Launch2PreservesExactRuntimeAndFactoryAddresses() (gas: 111978)\n[PASS] test_Launch2RetainsDocumentedEthSink() (gas: 120360)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 29.40ms (34.16ms CPU time)\n\nRan 6 tests for test/FrenRenderer.t.sol:FrenRendererTest\n[PASS] test_LaunchesFitTransactions() (gas: 60894)\nLogs:\n  launch 1 gas budget (with calldata and allowance): 12614648\n  launch 2 gas budget (with calldata and allowance): 11731672\n  launch 3 gas budget (with calldata and allowance): 15501064\n\n[PASS] test_MatchesTheReference() (gas: 54321184)\n[PASS] test_RejectsCombosOutsideTheArt() (gas: 11029957)\n[PASS] test_SameAsTheLaunchRenderer() (gas: 913046892)\n[PASS] test_TakesOnlyThisArt() (gas: 19364)\n[PASS] test_TokenURIIsCheapEnoughToRead() (gas: 12987078)\nLogs:\n  tokenURI gas: 12981115\n\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 1.62s (1.77s CPU time)\n\nRan 2 test suites in 1.62s (1.65s CPU time): 11 tests passed, 0 failed, 0 skipped (11 total tests)\n","passed":true},{"durationMs":101,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":137,\"README.md\":51,\"foundry.toml\":22,\"launch.json\":14,\"script/art/chunks.py\":88,\"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,\"src/FrenArtChunks.sol\":2298,\"src/FrenArtIndex.sol\":32,\"src/FrenRenderer.sol\":285,\"test/FrenArtLaunch2.t.sol\":120,\"test/FrenRenderer.t.sol\":186,\"test/ref/FrenRendererRef.sol\":313},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"d449e8234c2cebbad1017328f2ed32bf050f482d3c07f93315e506ed53af0517","verifiedTreeHash":"f4375d3d3a8f526df0761faa66e2cdd4cc8f1578","verifierVersion":"0.1.0+94826a22"},{"checks":[{"durationMs":30321,"exitCode":0,"name":"build","output":"Compiling 35 files with Solc 0.8.30\nSolc 0.8.30 finished in 30.20s\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:144:54\n    │\n144 │                     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:143:21\n    │\n143 │                 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:221:41\n    │\n221 │         _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:221:61\n    │\n221 │         _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:222:79\n    │\n222 │         _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:222:92\n    │\n222 │         _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:223:36\n    │\n223 │         _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:223:49\n    │\n223 │         _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:226:55\n    │\n226 │         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:226:68\n    │\n226 │         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:228:57\n    │\n228 │         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:228:70\n    │\n228 │         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:25\n    │\n239 │             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:240:40\n    │\n240 │             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:248:32\n    │\n248 │                     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:249:36\n    │\n249 │                     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:251:29\n    │\n251 │                     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:251:44\n    │\n251 │                     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:252:36\n    │\n252 │                     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:253:65\n    │\n253 │                     for (int256 xx = a; xx < b; ++xx) 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:253:87\n    │\n253 │                     for (int256 xx = a; xx < b; ++xx) 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:261:56\n    │\n261 │         for (uint256 i; i < n; ++i) 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\n","passed":true},{"durationMs":1482,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 5 tests for test/FrenArtLaunch2.t.sol:FrenArtLaunch2Test\n[PASS] test_Chunk7AlsoHasTheReportedAdmissionBlocker() (gas: 4792593)\n[PASS] test_ExactLaunch2ArtIsRejectedByCurrentProtectedScan() (gas: 14689176)\n[PASS] test_Launch2ConstructorsRejectValue() (gas: 1029478)\n[PASS] test_Launch2PreservesExactRuntimeAndFactoryAddresses() (gas: 111978)\n[PASS] test_Launch2RetainsDocumentedEthSink() (gas: 120360)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 1.39s (45.83ms CPU time)\n\nRan 6 tests for test/FrenRenderer.t.sol:FrenRendererTest\n[PASS] test_LaunchesFitTransactions() (gas: 60894)\nLogs:\n  launch 1 gas budget (with calldata and allowance): 12614648\n  launch 2 gas budget (with calldata and allowance): 11731672\n  launch 3 gas budget (with calldata and allowance): 15501064\n\n[PASS] test_MatchesTheReference() (gas: 54321184)\n[PASS] test_RejectsCombosOutsideTheArt() (gas: 11029957)\n[PASS] test_SameAsTheLaunchRenderer() (gas: 913046892)\n[PASS] test_TakesOnlyThisArt() (gas: 19364)\n[PASS] test_TokenURIIsCheapEnoughToRead() (gas: 12987078)\nLogs:\n  tokenURI gas: 12981115\n\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 1.39s (1.50s CPU time)\n\nRan 2 test suites in 1.39s (2.78s 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\":185,\"README.md\":51,\"foundry.toml\":22,\"script/art/chunks.py\":88,\"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,\"src/FrenArtChunks.sol\":2298,\"src/FrenArtIndex.sol\":32,\"src/FrenRenderer.sol\":285,\"test/FrenArtLaunch2.t.sol\":120,\"test/FrenRenderer.t.sol\":186,\"test/ref/FrenRendererRef.sol\":313},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"dedf0bf271c12bcdb580a5208814c26ffaa452d046f02692e4d83713c42b22c9","verifiedTreeHash":"fba9666d6f4a73158149529062ea15cf4dd7eba8","verifierVersion":"0.1.0+94826a22"},{"checks":[{"durationMs":33626,"exitCode":0,"name":"build","output":"Compiling 35 files with Solc 0.8.30\nSolc 0.8.30 finished in 33.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:143:21\n    │\n143 │                 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:144:54\n    │\n144 │                     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:221:41\n    │\n221 │         _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:221:61\n    │\n221 │         _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:222:79\n    │\n222 │         _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:222:92\n    │\n222 │         _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:223:36\n    │\n223 │         _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:223:49\n    │\n223 │         _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:226:55\n    │\n226 │         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:226:68\n    │\n226 │         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:228:57\n    │\n228 │         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:228:70\n    │\n228 │         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:25\n    │\n239 │             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:240:40\n    │\n240 │             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:248:32\n    │\n248 │                     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:249:36\n    │\n249 │                     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:251:29\n    │\n251 │                     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:251:44\n    │\n251 │                     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:252:36\n    │\n252 │                     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:253:65\n    │\n253 │                     for (int256 xx = a; xx < b; ++xx) 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:253:87\n    │\n253 │                     for (int256 xx = a; xx < b; ++xx) 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:261:56\n    │\n261 │         for (uint256 i; i < n; ++i) 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\n","passed":true},{"durationMs":1630,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 5 tests for test/FrenArtLaunch2.t.sol:FrenArtLaunch2Test\n[PASS] test_Chunk7AlsoHasTheReportedAdmissionBlocker() (gas: 4792593)\n[PASS] test_ExactLaunch2ArtIsRejectedByCurrentProtectedScan() (gas: 14689176)\n[PASS] test_Launch2ConstructorsRejectValue() (gas: 1029478)\n[PASS] test_Launch2PreservesExactRuntimeAndFactoryAddresses() (gas: 111978)\n[PASS] test_Launch2RetainsDocumentedEthSink() (gas: 120360)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 134.62ms (32.51ms CPU time)\n\nRan 6 tests for test/FrenRenderer.t.sol:FrenRendererTest\n[PASS] test_LaunchesFitTransactions() (gas: 60894)\nLogs:\n  launch 1 gas budget (with calldata and allowance): 12614648\n  launch 2 gas budget (with calldata and allowance): 11731672\n  launch 3 gas budget (with calldata and allowance): 15501064\n\n[PASS] test_MatchesTheReference() (gas: 54321184)\n[PASS] test_RejectsCombosOutsideTheArt() (gas: 11029957)\n[PASS] test_SameAsTheLaunchRenderer() (gas: 913046892)\n[PASS] test_TakesOnlyThisArt() (gas: 19364)\n[PASS] test_TokenURIIsCheapEnoughToRead() (gas: 12987078)\nLogs:\n  tokenURI gas: 12981115\n\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 1.51s (1.68s CPU time)\n\nRan 2 test suites in 1.51s (1.64s CPU time): 11 tests passed, 0 failed, 0 skipped (11 total tests)\n","passed":true},{"durationMs":63,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[],\"files\":{\".gitignore\":4,\"ADAPTATION.md\":85,\"README.md\":51,\"foundry.toml\":22,\"script/art/chunks.py\":88,\"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,\"src/FrenArtChunks.sol\":2298,\"src/FrenArtIndex.sol\":32,\"src/FrenRenderer.sol\":285,\"test/FrenArtLaunch2.t.sol\":120,\"test/FrenRenderer.t.sol\":186,\"test/ref/FrenRendererRef.sol\":313},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"e84dc12844453fd7b97736e3465654a2bc49efc405cd99241e67a1f1136d2135","verifiedTreeHash":"6033ad1af059a943e3ffb843c81c5c0ba7125c45","verifierVersion":"0.1.0+e6140b7a"}]}