{"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":"ea8e8e20-b777-487b-82a0-b0be5eb702c7","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"a40d91eafc3bfc824bdab13c0b51505462ee4346f93508298f9f7f52e5e3c116","dependsOn":["audit_imported_code"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"2d7d84a1a9972f1497e5bc68a704cbf42294d08c62d2868f102ffe3b909b9b51","skillId":"adapt-contract-project","tools":[]},"key":"adapt_contract_project","kind":"code","role":"implement","skillHash":"2d7d84a1a9972f1497e5bc68a704cbf42294d08c62d2868f102ffe3b909b9b51","skillId":"adapt-contract-project","state":"accepted"},{"acceptedSubmissionHash":"367f08106d51fe7429b8b7841aece84fb71376a454177aed3c41fd1cc6461a01","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":"08002b9b7414b9322bcf50136aec8292b6ffe58509033c0557dce277c32957e9","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":"c7c4864b3df4eecc4a92262df97ddaa325006fa4c678e6290e1ab128c2625adb","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":"2b3c4c629ce7dc640f2e6102e74b75073c2810ae85144c915f8c6fad4c05ce57","dependsOn":["adapt_contract_project","write_foundry_tests","manifest","audit_math","audit_permissions","audit_economics","audit_flow"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"af3aa01159bbf354f621cafa5c0006f6169e0938a8b015be508b7377dbf165bc","skillId":"audit-judge","tools":[]},"key":"audit_judge","kind":"code","role":"review","skillHash":"af3aa01159bbf354f621cafa5c0006f6169e0938a8b015be508b7377dbf165bc","skillId":"audit-judge","state":"accepted"},{"acceptedSubmissionHash":"b9ca8d5340de9e5a8a0e2705b40cdd5e0e8d270194d1f7be96458afc6238e24f","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":"cad2ba6d90260f84e01194fed90695363d61f576188b0b39c6d0cb7dda26ce73","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":"1594313bbfc4bfec71e608aa6d7e7e6cc619b82f7cba369e29d7eb059afd76bf","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"481b148423ba761f03abe9dc937e4142ffec48ff5e61c1eb177be34a87f8d778","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"4c76766b00591dfe982fe85d3de589fdb2f810e5137c301155d1c5e36a1d3b23","skillId":"write-foundry-tests","tools":[]},"key":"write_foundry_tests","kind":"code","role":"tests","skillHash":"4c76766b00591dfe982fe85d3de589fdb2f810e5137c301155d1c5e36a1d3b23","skillId":"write-foundry-tests","state":"accepted"}],"objective":"Deploy Proof House's contracts from this Foundry repository, as they are. The code is finished: 215 Foundry tests pass (unit, fuzz and invariant, plus fork tests against the real ETH/IMD pool and the real Chainlink VRF coordinator), it has been through three rounds of adversarial security review, and the full launch has been rehearsed end to end on a mainnet fork and twice on Sepolia. Change nothing unless an audit finding requires it, and say exactly what changed and why: we compare every deployed contract's runtime code with our own build of this commit before using it.\n\nDeploy launch.json (at the repository root): 8 contracts in this order, with the constructor arguments it lists ($owner and $contract:Name): ArtStorage, ArtHouse, KeyProof, ArtifactsPiece, ArtifactsFactory, ArtifactsSource, BrokerPass, SubmissionReviews. Nothing is called after deployment: the owner configures everything afterwards.\n\nToken facts. No fungible token is created and there is no pool. IMD (0xd34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7) is the existing ERC-20 buyers may pay with for plain SVG collections. The only tokens are ERC-721 NFTs: each ARTIFACTS piece is its own one-token contract (\"ARTIFACTS #NNN\"; THE SOURCE \"ARTIFACTS · THE SOURCE\"), minted only when bought; supply 256, fixed forever. BrokerPass is an ERC-721 of at most 100 free passes.\n\nOwner: the owner field. Two-step ownership, no renounceOwnership, no upgradeability.","parentJobId":null,"planHash":"1844c2d9d19af1376a4b163d46da64072c326544508547516cba7491d757cc29","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"ea8e8e20-b777-487b-82a0-b0be5eb702c7","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-2179-deploy-proof-house-s-contracts"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"52184","feedbackHash":"ea36a75c0e718ab2d5e90168a5149c03ca557ad3113e56f2f92cc4f9d8ce6538","nodeKey":"adapt_contract_project","submissionHash":"d9172b6c1162eb1017a6b7bd12855b7159297b2404ccc7e55dd9b31ee670ba33","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52290","feedbackHash":"c4a958b420f779d05808074336f0342612a0c6201a6467919818eb9b9a3bf8d2","nodeKey":"adapt_contract_project","submissionHash":"a40d91eafc3bfc824bdab13c0b51505462ee4346f93508298f9f7f52e5e3c116","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51225","feedbackHash":"f3415b4bee0ad949db3bf6f9690856f9e144cc02a9a341222e7658cf129aca85","nodeKey":"audit_economics","submissionHash":"367f08106d51fe7429b8b7841aece84fb71376a454177aed3c41fd1cc6461a01","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51534","feedbackHash":"22f18e959dca3a9f7c6da7f4a38a7e7e8be25f68f25c0016fa98415baaae37a1","nodeKey":"audit_flow","submissionHash":"08002b9b7414b9322bcf50136aec8292b6ffe58509033c0557dce277c32957e9","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52598","feedbackHash":"a162fb4bb7c49fe50483cbd4547162b53666f678e450a377cffba835a28dd1f7","nodeKey":"audit_imported_code","submissionHash":"c7c4864b3df4eecc4a92262df97ddaa325006fa4c678e6290e1ab128c2625adb","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52263","feedbackHash":"1e775dfd4c62af5caec2bdc4fd9316aa9d9374b930d971a1191418871712c4e2","nodeKey":"audit_judge","submissionHash":"913cc6df3fe42370e499eb5bcfa988a13ab1f37919052b11d4f17b7c7fef1be5","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52240","feedbackHash":"416b36dfa102a5dcb34f4a26fc1ac9e8a50227ad271be26522fce3443c827740","nodeKey":"audit_judge","submissionHash":"2b3c4c629ce7dc640f2e6102e74b75073c2810ae85144c915f8c6fad4c05ce57","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52163","feedbackHash":"86df8d98d1ec70c7705a5d8eb96c50e9d14a17a0c1fde2fa38594b425633e673","nodeKey":"audit_math","submissionHash":"b9ca8d5340de9e5a8a0e2705b40cdd5e0e8d270194d1f7be96458afc6238e24f","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51488","feedbackHash":"86f53532c5c1ee6bf913187cc1950b67594bf9430b6f0264e3e193f63b5e4dc4","nodeKey":"audit_permissions","submissionHash":"cad2ba6d90260f84e01194fed90695363d61f576188b0b39c6d0cb7dda26ce73","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52253","feedbackHash":"e2fb89dd5315d67e362b9772021825e04acdf92bb81032bc1eae7c9760336222","nodeKey":"manifest","submissionHash":"1594313bbfc4bfec71e608aa6d7e7e6cc619b82f7cba369e29d7eb059afd76bf","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52274","feedbackHash":"5522f817e554df8407f060d393deed67a69f39c8deeeda0ff472d72e2089cf04","nodeKey":"manifest","submissionHash":"02fe3d3189147116ffdab68da766f6758aa4de0a97b90783a057ff41747f8689","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52166","feedbackHash":"913c549238eec37ac4a0faf051b29a667335d7717a520b60dbdccb1772d6abd2","nodeKey":"write_foundry_tests","submissionHash":"481b148423ba761f03abe9dc937e4142ffec48ff5e61c1eb177be34a87f8d778","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51164","feedbackHash":"4d8ce7d66a342864d79364a935115d90611fa6b3eacb42409d1f94d7d8182170","nodeKey":"write_foundry_tests","submissionHash":"c44a54d365dd12f1b5b9154b2b0b9b2c7cbb7760ecfde1d7f5001bc15ec62814","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"04b39340c004e523826f1b96ba2f7fcce021729e4485cd17c0e95449733c1bad","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"9338ada718bed7c982ee227ad1f6b43ccef25938feff5cf799ea0d5e505fb179","device":"7d2db8d9021f8063","findings":[],"hash":"02fe3d3189147116ffdab68da766f6758aa4de0a97b90783a057ff41747f8689","nodeId":"40eb3660-6092-420f-977e-9462e6875810","outcome":"completed","summary":"Updated [launch.json](/home/imd3/.identitymd/work/ea8e8e20-b777-487b-82a0-b0be5eb702c7/40eb3660-6092-420f-977e-9462e6875810/launch.json): corrected the notes to Sepolia and removed extra deployment/setup instructions. All eight contract entries match the compiled ABIs and remain unchanged.\n\n`forge build` passed. Tests with the required fuzz seed: **232 passed, 0 failed, 2 fork suites skipped** because no fork URL was configured.\n\nOnly `launch.json` changed.","treeHash":"67772cd367099ff693cfbbd04f4af48fdbd0b809","usage":{"cachedInputTokens":1114405,"inputTokens":60922,"model":"gpt-6.1-sol","outputTokens":5373,"runtime":"codex","turns":7,"wallClockMs":340512}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"739094f0e08668ee","findings":[{"citation":"resolved","description":"The comment on lastAnsweredBlock (lines 97-98) says that no Chainlink answer can land between a fallback block's hash becoming known and the draw finishing. startFallbackDraw (lines 426-438) checks only purchaseBlock, which re-requests carry forward, and lastAnsweredBlock. It does not check that the coordinator has dropped the request being drawn. So the buyer can call rerequestRandomness(old) after VRF_RETRY_BLOCKS, which is allowed because Chainlink was silent, and call startFallbackDraw(new) in the same block. The coordinator now holds a live request (Chainlink keeps it for up to 24h) while the fallback block's hash becomes public 5 blocks later. rawFulfillRandomWords does not check fallbackBlock, so a VRF answer still assigns an edition until someone calls finishFallbackDraw. A buyer who dislikes the edition the public hash implies leaves the draw unfinished and lets VRF answer. A buyer who sees a VRF fulfilment they dislike in the mempool front-runs it with finishFallbackDraw. Either way the buyer picks the better of two independent draws, which breaks the uniform-assignment guarantee. A realistic trigger is a curator subscription that runs dry for 3 days and is then topped up.","line":416,"path":"src/ArtifactsFactory.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport \"forge-std/Test.sol\";\nimport {ArtStorage} from \"src/ArtStorage.sol\";\nimport {ArtHouse} from \"src/ArtHouse.sol\";\nimport {KeyProof} from \"src/KeyProof.sol\";\nimport {ArtifactsPiece} from \"src/ArtifactsPiece.sol\";\nimport {ArtifactsFactory} from \"src/ArtifactsFactory.sol\";\nimport {IVRFCoordinatorV2Plus, Traits} from \"src/interfaces/Interfaces.sol\";\n\ncontract VRFStub {\n    uint256 public nextId = 1;\n    mapping(uint256 => address) public consumer;\n    mapping(uint256 => bytes32) public s_requestCommitments;\n\n    function requestRandomWords(IVRFCoordinatorV2Plus.RandomWordsRequest calldata) external returns (uint256 id) {\n        id = nextId++;\n        consumer[id] = msg.sender;\n        s_requestCommitments[id] = keccak256(abi.encode(id, msg.sender));\n    }\n\n    function fulfill(uint256 id, uint256 word) external {\n        delete s_requestCommitments[id];\n        uint256[] memory w = new uint256[](1);\n        w[0] = word;\n        ArtifactsFactory(consumer[id]).rawFulfillRandomWords(id, w);\n    }\n}\n\n/// A buyer whose draw Chainlink left unanswered for FALLBACK_BLOCKS re-requests it and starts the fallback on the new\n/// request in the same block. Once the fallback block's hash is public the buyer knows that edition; if they dislike\n/// it they leave the draw unfinished, and Chainlink (subscription topped up) can still answer the fresh request,\n/// assigning a different edition. The buyer chooses between two random outcomes.\ncontract FallbackChoiceTest is Test {\n    address curator = address(0xC0);\n    address artist = address(0xA7);\n    address alice = address(0xA11CE);\n    VRFStub vrf;\n    ArtifactsFactory factory;\n\n    function setUp() public {\n        ArtStorage store = new ArtStorage(curator);\n        ArtHouse house = new ArtHouse(curator, address(store), address(0xD34a99Bc0f67aE1bbd63C660e6d0b0dd03E263B7));\n        KeyProof kp = new KeyProof();\n        ArtifactsPiece impl = new ArtifactsPiece(address(kp));\n        factory = new ArtifactsFactory(curator, address(house), address(impl));\n        vrf = new VRFStub();\n        vm.startPrank(curator);\n        store.setHouse(address(house));\n        house.approveArtist(artist, \"artist\");\n        house.setSaleModule(address(factory), true);\n        house.registerModuleCollection(address(factory), artist);\n        factory.configureVRF(address(vrf), bytes32(uint256(1)), 1, false);\n        for (uint256 i = 1; i <= 255; ++i) {\n            factory.setPiece(i, Traits(\"t\", \"p\", 3, \"d\"), abi.encodePacked(\"ct\", i), keccak256(abi.encodePacked(i)));\n        }\n        factory.lock();\n        factory.setPrice(1 ether);\n        factory.setSaleOpen(true);\n        vm.stopPrank();\n        vm.deal(alice, 10 ether);\n    }\n\n    function test_noChainlinkAnswerAfterTheFallbackHashIsKnown() public {\n        vm.prank(alice);\n        uint256 id1 = factory.buy{value: 1 ether}(address(0));\n        // Chainlink silent (e.g. the subscription ran dry) for FALLBACK_BLOCKS\n        vm.roll(block.number + factory.FALLBACK_BLOCKS());\n        vm.prank(alice);\n        uint256 id2 = factory.rerequestRandomness(id1); // a fresh request the coordinator now holds\n        bool started;\n        try factory.startFallbackDraw(id2) {\n            started = true;\n        } catch {}\n        if (!started) return; // refusing a fallback while Chainlink still holds the request also closes the choice\n        uint256 target = factory.fallbackBlock(id2);\n        vm.roll(target + 1);\n        bytes32 h = keccak256(\"target block hash\");\n        vm.setBlockhash(target, h);\n        uint256 fallbackEdition = uint256(keccak256(abi.encode(h, id2))) % 255 + 1;\n        // alice knows fallbackEdition now and does not finish; Chainlink answers the fresh request\n        uint256 word = fallbackEdition; // any word drawing another edition\n        (bool ok,) = address(vrf).call(abi.encodeCall(VRFStub.fulfill, (id2, word)));\n        if (ok) {\n            emit log_named_uint(\"fallback edition (known, declined)\", fallbackEdition);\n            emit log_named_uint(\"edition assigned by the late VRF answer\", factory.requestEdition(id2));\n        }\n        assertFalse(ok, \"a VRF answer still lands after the fallback block's hash is public: the buyer picks\");\n    }\n}","reproduction":"1) alice buy() at block B gets request id1. Chainlink does not answer (subscription unfunded). 2) At block B+FALLBACK_BLOCKS (21,600): alice rerequestRandomness(id1) returns id2 (allowed because block >= requestBlock+7,500); startFallbackDraw(id2) succeeds in the same block, target = block+5. 3) At target+1 the hash h is public; the fallback edition is keccak256(abi.encode(h,id2))%255+1 (217 in the proof). alice does not finish. 4) The subscription is topped up and the coordinator calls rawFulfillRandomWords(id2,[w]), which succeeds and assigns a different edition (218 in the proof). Expected: once a fallback has started (or its hash is known), a VRF answer for that request is refused, or startFallbackDraw refuses while _stillHeld(requestId) is true. Actual: both paths stay open and the buyer chooses. Fix sketch: in startFallbackDraw require !_stillHeld(requestId) || block.number >= requestBlock[requestId] + VRF_RETRY_BLOCKS; or in rawFulfillRandomWords ignore/revert when fallbackBlock[requestId] != 0 && block.number > fallbackBlock[requestId]. Run: forge test --match-path test/scratch/FallbackChoice.t.sol","severity":"medium","snippet":"    function rawFulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) external {\n        if (msg.sender != address(vrfCoordinator)) revert NotCoordinator();\n        _assign(requestId, randomWords[0]);","title":"Fallback draw can be started on a fresh re-request that Chainlink still holds, so the buyer can choose between the fallback edition and a later VRF edition"},{"citation":"resolved","description":"finishFallbackDraw is the only function that clears fallbackBlock[requestId], and it reverts FallbackMissed once the target hash has left both BLOCKHASH and EIP-2935 (more than 8,191 blocks). After that, rerequestRandomness on the request reverts FallbackPending for good, even though the draw is dead (_fallbackLive returns false). The only way left is startFallbackDraw, which reverts ChainlinkAnswering until FALLBACK_BLOCKS (about 3 days) after Chainlink's latest answer to any request. While the sale is live and Chainlink answers other buyers, each answer pushes this buyer's edition further back. Their paid edition stays unassigned for as long as Chainlink keeps working, although a simple re-request would be answered at once.","line":377,"path":"src/ArtifactsFactory.sol","reproduction":"1) alice buys id; Chainlink is silent for 21,600 blocks; anyone calls startFallbackDraw(id), target T. 2) Nobody calls finishFallbackDraw before T+8,192, so the hash is gone. 3) Chainlink comes back and bob buys; vrf fulfils bob's request, so lastAnsweredBlock = now. 4) alice calls rerequestRandomness(id), which reverts FallbackPending (line 377). startFallbackDraw(id) reverts ChainlinkAnswering (line 430) and keeps doing so while any purchase is answered within 21,600 blocks. Expected: a dead fallback (!_fallbackLive(id)) lets the buyer or curator re-request. Actual: alice's edition stays unassigned until Chainlink has been silent for 3 more days. Fix sketch: in rerequestRandomness replace the check with `if (_fallbackLive(requestId)) revert FallbackPending();` and delete fallbackBlock[requestId] when re-requesting.","severity":"low","snippet":"        if (fallbackBlock[requestId] != 0) revert FallbackPending();","title":"A fallback draw whose block hash expired blocks re-requesting forever, and restarting it waits for Chainlink to go silent again for 3 days"}],"hash":"08002b9b7414b9322bcf50136aec8292b6ffe58509033c0557dce277c32957e9","nodeId":"4f8c542f-8091-4170-aa9f-e215d98c34ad","outcome":"completed","summary":"I found two problems in the edition draw in `ArtifactsFactory`. No source or config file was changed. The results are in `.imd-findings.json`, and the one test I wrote is in `test/scratch/` (git shows no changes).\n\n**Launch manifest.** `launch.json` deploys the eight contracts in the stated order. Each constructor gets the right number of arguments, in the right order, and every owner argument is `$owner`. No finding there.\n\n### Findings\n\n**1. Medium: a buyer can choose between two random draws** (`src/ArtifactsFactory.sol:416`). If Chainlink doesn't answer a purchase for about 3 days (for example because the VRF subscription ran dry), the buyer can do this in one block:\n1. Call `rerequestRandomness` on the old request. This is allowed by then, and it creates a fresh request that Chainlink still holds.\n2. Call `startFallbackDraw` on the new request. It only checks the original purchase block and Chainlink's last answer, not whether Chainlink still holds this request.\n\nFive blocks later the fallback block's hash is public, so the buyer knows which edition the fallback would give. If they don't like it, they leave the draw unfinished, and Chainlink's late answer still assigns an edition, because `rawFulfillRandomWords` doesn't check for a started fallback. It also works the other way: if the buyer sees a Chainlink answer they dislike coming in, they finish the fallback first. Either way they pick the better of two editions. The code comments say this cannot happen.\n\nI proved it with `test/scratch/FallbackChoice.t.sol`. It fails on the current code: the fallback would have given edition 217, the buyer passed, and the late Chainlink answer assigned 218. Two possible fixes:\n- refuse to start a fallback while Chainlink still holds the request; or\n- reject a Chainlink answer once a fallback for that request has started.\n\n**2. Low: an abandoned fallback can delay a buyer's edition for a long time** (`src/ArtifactsFactory.sol:377`). If a fallback draw is started but nobody finishes it within about 8,191 blocks (~27 hours), its block hash is no longer readable.\n- **Re-requesting is blocked for good.** `finishFallbackDraw` is the only thing that clears the fallback marker, and it now reverts, so `rerequestRandomness` reverts forever even though the draw is dead.\n- **Restarting the fallback has to wait.** `startFallbackDraw` waits until Chainlink has answered nothing for 3 days, and every answer to another buyer resets that clock.\n\nSo while the sale is live and Chainlink is working, this buyer's paid edition can stay unassigned indefinitely. The fix is to block re-requests only while a fallback is still live, and clear the marker when re-requesting. This one has no test; it is traced through the code only.\n\n### Leads I ruled out\n- **Buyers naming themselves as broker:** the existing tests document it as an intended Broker Pass perk.\n- **Unsafe payment to an arbitrary address in `ArtHouse._pay`:** it only pays the artist's payout address, the owner, or the burner, all of which are fixed by the contract's own rules.\n- **Weak randomness in `_assign`:** the only real weakness is finding 1.\n- **Re-entering `ArtifactsPiece.release`:** the escrow is cleared and the token moved to the buyer before the ledger is called.\n- **Key-proof maths in `KeyProof`:** I traced it and it holds (a key that opens can't be proven fake).\n\n### Coverage\nThe coverage section has a row for each of the 114 listed entry points, plus two rows for invariants I checked. The four `ImdBuybackBurner` entry points are marked unreached: that contract isn't in this launch, and I spent the time on the eight that are. I read every other contract's source and traced its entry points.","treeHash":null,"usage":{"cachedInputTokens":1740837,"inputTokens":36,"model":"claude-opus-5-5","outputTokens":22886,"runtime":"claude","turns":20,"wallClockMs":268575}},{"artifacts":[],"attempt":1,"bundleHash":"f5682b82392413447e7ba77e2a67bc31dfa3b3ec981580fd8fc7b78eb0c65245","device":"7591760a616c6429","findings":[],"hash":"1594313bbfc4bfec71e608aa6d7e7e6cc619b82f7cba369e29d7eb059afd76bf","nodeId":"40eb3660-6092-420f-977e-9462e6875810","outcome":"completed","summary":"The finding reproduced and is fixed in launch.json. Only that file changed, and the responses file answers the reviewer.\n\n**What I verified**\n\n- The pinned launch chain is Sepolia. On Sepolia the mainnet IMD address and the seats address both return no code; the address the README and deploy script name as Sepolia IMD has code and reports name \"Identity.md (test)\", symbol IMD, 18 decimals.\n- The earlier accepted Sepolia launch manifest in git history (commit e865714) already used that Sepolia IMD address, so this is the source's own value, not one I chose.\n\n**What changed in launch.json**\n\n- ArtHouse's third constructor argument is now the Sepolia IMD, 0x44a1cd38474fb1748400e7deb5f8d786cce3f89a. With the mainnet address, the immutable `imd` would have made mintWithIMD revert forever on this chain.\n- The notes now state which IMD is used and why, and explain the seats situation.\n\n**What I left alone, and why**\n\n- The seats address stays at the mainnet identity.md seat collection. No Sepolia seat contract is named by the brief, the source, ADAPTATION.md, the manifest's git history, or anything public, and inventing one is forbidden. On Sepolia the seat-only paths in BrokerPass and SubmissionReviews are inert, every piece-holder path works, and the owner-set holders gate tolerates a code-less seats address. The notes say so.\n- No source file, README, or deploy script changed, so every deployed runtime is byte-for-byte the accepted build.\n\n**Checks**\n\n- Manifest schema validated locally: exactly kind, contracts, notes; 8 unique names in dependency order; every argument a static word, $owner, or a backward contract reference; notes under 2,000 characters.\n- `forge build` passes. `forge test` with the verifier's fuzz seed: 244 passed, 0 failed, 2 skipped. The two skipped are the fork tests, which need a FORK_URL.\n\nThe response to the finding is recorded in .imd-responses.json with verdict \"fixed\" and the evidence above. If identity.md later publishes a Sepolia seat collection, that address belongs in the BrokerPass and SubmissionReviews arguments.","treeHash":"48a5085f4e9297a26d1414c51ab8843201bbed3f","usage":{"cachedInputTokens":441731,"inputTokens":258,"model":"claude-fable-5-1","outputTokens":11577,"runtime":"claude","turns":19,"wallClockMs":504204}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"b0001bc8a5c908cd","findings":[{"citation":"resolved","description":"This round's fix to 07f1616add6c holds: rawFulfillRandomWords now refuses a late answer to the fallback's own request (line 424), and startFallbackDraw refuses a request the coordinator may still answer. The tester (write_foundry_tests, 159f867efda6) found a gap the fix leaves open. finishFallbackDraw maps the target hash to an edition through _assign, which computes idx = uint16(word % left) (line 487) over the Fisher-Yates pool as it stands when the draw finishes. The hash is fixed, but the edition is not. rawFulfillRandomWords only checks fallbackBlock[requestId] for the request being answered. An answer to any other request still lands while fallbackInFlight is live and past its target, for example a purchase made after the draw started. That answer changes `left` and the pool, so it changes which edition the fallback's hash yields. Once Chainlink answers again (for example, after a dry subscription is topped up, the same trigger as 07f1616add6c), anyone who sees the public hash can compute both outcomes: finish now, or let another answer land first. The fallback's buyer can then choose, by finishing at once or by buying another edition (or waiting for another buyer's fulfilment) and letting it land before the finish. This contradicts the lastAnsweredBlock NatSpec (lines 96-98: no answer can land between a fallback block's hash becoming known and its draw finishing) and the rawFulfillRandomWords NatSpec (the started draw's result stands). Severity is low: the path is reachable only after FALLBACK_BLOCKS of Chainlink silence, and a keeper finishing at target+1 narrows it to a race against a pending fulfilment. No funds are lost and the edition count stays exact. Fix that keeps the design: in rawFulfillRandomWords, also revert while the in-flight draw is past its target and still live, e.g. `uint256 f = fallbackInFlight; if (f != 0 && f != requestId && _fallbackLive(f) && block.number > fallbackBlock[f]) revert FallbackBusy();`. The coordinator then consumes that callback, and its buyer re-requests at once (it is no longer held) after the draw finishes. Alternatively, refuse new purchases while a draw is live, or fix the draw's `left` and pool when it starts.","line":424,"path":"src/ArtifactsFactory.sol","reproduction":"Run the tester's proof unchanged: copy .imd/reads/proofs/Proof_159f867efda6.t.sol to test/scratch/ and run forge test --match-path on the copy. It fails on this tree with 'a started draw whose hash is public must give one result: 22 != 212'. Setup: test/Fixture.sol, all 255 pieces published, sale open at 1 ether. alice buy -> request a. vm.roll(+FALLBACK_BLOCKS); startFallbackDraw(a); vm.roll(fallbackBlock(a)+1), so the target hash is public. Branch 1: finishFallbackDraw(a) -> edition 22. Branch 2 (snapshot reverted): alice buy -> request c; vrf.fulfill(c, 0) succeeds (line 424 checks only fallbackBlock[c] == 0); finishFallbackDraw(a) -> edition 212. Expected: the same edition in both branches. Actual: 22 vs 212.","severity":"low","snippet":"        if (target != 0 && block.number > target) revert FallbackPending();","title":"A started fallback draw's edition still changes after its target hash is public when any other request is answered first, so the buyer can pick between outcomes"}],"hash":"2b3c4c629ce7dc640f2e6102e74b75073c2810ae85144c915f8c6fad4c05ce57","nodeId":"361333f1-332b-44bd-b518-793465e3491d","outcome":"completed","summary":"I re-ran the proofs on the revised code: both medium findings from last round are fixed. One new low-severity finding is left, raised by the independent tester. I changed no project files; my scratch copies under `test/scratch/` have been deleted. `.imd-findings.json` holds the one finding and a coverage row for all 112 entry points (110 holds, 2 pointing at the finding).\n\n**Settling last round's findings**\n- **Fallback draw on a request Chainlink still holds (07f1616a, medium): fixed.** The proof, and the duplicate proof 1f4cb786, now pass. `startFallbackDraw` refuses a request the coordinator may still answer, and `rawFulfillRandomWords` (`src/ArtifactsFactory.sol:424`) refuses a late answer to the draw's own request once its block hash is public.\n- **Gate address with no code reverts every gated buy (20ca2ef1, medium): fixed.** All 3 tests in both proof files (20ca2ef1 and 7f29b6fb) pass. `src/base/HolderGate.sol` now reads balances and owners through a raw `_readWord` call that takes exactly one 32-byte word. An address with no code, a revert, or a malformed answer now counts as not held.\n- **A dead fallback draw blocking re-requests (07bde389, low): fixed.** `rerequestRandomness` now refuses only a draw that is still live (`_fallbackLive`), and clears `fallbackBlock` and `fallbackInFlight` when it re-requests.\n- **Mainnet addresses in a Sepolia launch (aef6e0a1, low): fixed for IMD.** `launch.json` now passes `0x44a1cd38474fb1748400e7deb5f8d786cce3f89a` as ArtHouse's IMD. I checked it on Sepolia: it has code and `symbol()` returns \"IMD\". The brief names the mainnet address, but that one has no code on Sepolia and the IMD address can't be changed after deployment, so the change is justified. The seats address still has no code on Sepolia. That leaves `BrokerPass.claimWithSeat` and `SubmissionReviews.reviewAsSeat` unusable there, and the notes now say so.\n- **Disputed findings: accepted, no change needed.**\n  - Revoking THE SOURCE's sale module blocks settlement (ec83ecd2): an owner power, now documented in the README.\n  - The burner's public swap can be sandwiched (6cc4015d): documented and bounded, and the burner isn't one of the 8 contracts in this launch.\n  - Three informational notes (03cc5b5b, 313dd464, edce6803) are documented design behaviour.\n  - Sealing a collection with ~14,000 or more pieces fails (6c384346): informational only, confined to that collection.\n\n**New finding (low): a fallback draw's edition can still change after its block hash is public**\nThis is the tester's finding 159f867e, and it reproduces: the tester's proof fails on this tree with \"22 != 212\".\n- **Cause:** `finishFallbackDraw` picks the edition from the hash *and* from how many editions are left at the moment it finishes (`uint16 idx = uint16(word % left)`, line 487). The new check at line 424 only refuses late answers to the draw's own request.\n- **Effect:** a Chainlink answer to any other purchase can land first and shift the result. Once Chainlink answers again, the buyer can compute both outcomes and pick one, either by finishing at once or by buying another edition and letting its answer land first.\n- **Why low:** it needs three days of Chainlink silence first, and a keeper that finishes the draw as soon as its block exists turns it into a race against a pending fulfilment. No funds are lost and the edition count stays exact.\n- **Suggested fix:** in `rawFulfillRandomWords`, also refuse while another started draw is past its block and still live. That callback is consumed, and its buyer can re-request at once after the draw finishes.\n\n**Deployability:** constructor arguments in `launch.json` match every constructor. All 8 contracts are within size limits. The tightest is ArtifactsPiece at 24,385 bytes deployed, 191 bytes under the 24,576 limit.\n\n**Coverage caveat:** the ArtifactsPiece, BrokerPass, SubmissionReviews and ImdBuybackBurner rows are marked `holds` from my earlier round. Those files didn't change in the last three commits, so","treeHash":null,"usage":{"cachedInputTokens":656835,"inputTokens":18,"model":"claude-opus-5-5","outputTokens":10973,"runtime":"claude","turns":11,"wallClockMs":212706}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"4dd74fd7c315da80","findings":[{"citation":"resolved","description":"ArtifactsFactory._tokenGate (src/ArtifactsFactory.sol:347) and ArtifactsSource.bid (src/ArtifactsSource.sol:189) admit a caller to the holders-only window when holdsToken(msg.sender) is true, and holdsToken is a bare balanceOf read at call time. Nothing is locked, snapshotted or consumed. Economic consequence: the guarantee 'for the first N hours only holders may buy / bid' and the per-wallet phase caps (setMintPhases: 2 then 3 per wallet in the window) hold only per address, not per holder. One gateMinBalance of IMD can be passed from wallet to wallet between transactions, each wallet buying the phase cap, so a single actor buys any number of editions in the allowlist phase and non-holders buy before the window ends. The same works inside one transaction with borrowed IMD (the ETH/IMD Uniswap v4 pool the burner uses supports flash accounting, and any IMD holder can lend by approval): a contract receives IMD, calls buyMany, returns IMD, never having held it. The member gate (soulbound points) and the seat path (per-seat cap, mintedBySeat) do not have this gap; the token path does. Nobody loses ETH; what breaks is the allocation fairness the window and phases exist for, and the curator cannot tell handed-off balances from distinct holders. Suggested minimal fix, if the window is meant per holder: for the token path, record the IMD balance a wallet used and require the funds to have been held before saleOpenedAt (e.g. a snapshot of balances the curator publishes as a Merkle root, or an on-chain registration before the sale opens with a balance check at registration and at buy), or at least a per-transaction lock (require the same balance in a later block via a two-step registerHolder/buy). If per-address is the intended semantics, document it next to the phase caps.","line":81,"path":"src/base/HolderGate.sol","reproduction":"State: factory published and locked, setGate(seats, IMD, 10e18, 24h), setMintPhases(12h, 2, 12h, 3), sale open, price 0.01 ETH, phase 1 (cap 2 per wallet). Alice holds 10 IMD; Bob and Carol hold none. Calls: (1) Alice buyMany{0.02}(2, 0) -> ok, mintedBy[alice]=2. (2) Alice imd.transfer(bob, 10e18). (3) Bob buyMany{0.02}(2, 0) -> ok (expected: NotEligible, Bob never held IMD before the sale). (4) Bob transfers 10 IMD to Carol, Carol buyMany(2) -> ok. Result: sold == 6 inside the first 12 hours with a single 10 IMD balance, while the phase cap is 2 and the window is holders-only. Single-transaction variant: contract F with run(): imd.transferFrom(alice, F, 10e18); factory.buyMany{0.02}(2, 0); imd.transfer(alice, 10e18). Call F.run() during the window from any address -> mintedBy[F] == 2 and F's IMD balance is 0 after the call. Same for ArtifactsSource.bid during its 30-day holders-only auction. Verified with a scratch Foundry test on this tree (two tests pass: 6 editions bought with one balance; flash-borrowed IMD passes the gate in one tx).","severity":"low","snippet":"        try IBalanceOf(t).balanceOf(account) returns (uint256 b) {\n            return b >= gateMinBalance;","title":"Holders-first window is a point-in-time IMD balanceOf: one balance (or a flash-borrowed one) buys for unlimited wallets inside the window and past the phase caps"},{"citation":"resolved","description":"After IDLE (60 days) without a curator swap, anyone may call burnEth(amountIn = min(balance, 0.05 ether), minImdOut, deadline) and the only slippage bound is the caller's own minImdOut >= 1 wei (src/ImdBuybackBurner.sol:110-133). The swap runs with sqrtPriceLimitX96 = MIN_SQRT_PRICE_LIMIT, i.e. no price limit. A caller who first buys IMD on the same pool, then triggers the public swap with minImdOut = 1, then sells, captures nearly all of the 0.05 ETH of buyback value (minus the pool's 1% fee on their two legs and gas). The README accepts this and bounds it to 0.05 ETH per day; the point of this note is the economics: the loss is not a one-off. Every day the curator stays idle the next 0.05 ETH is sandwichable, so a burner holding e.g. 5 ETH of buyback leaks it over ~100 days to whoever runs the sandwich, with the IMD actually burned near zero. Who profits: the sandwicher, up to ~0.05 ETH/day. Who loses: IMD holders (the buyback). Preconditions: curator idle 60 days (the public path exists exactly for that case). Minimal fix that keeps the design: derive the public swap's minimum on-chain from the pool's current price (the PoolManager's slot0 via StateLibrary / extsload) with a fixed tolerance, e.g. require imdOut >= quote * 95%, instead of trusting the caller's minImdOut; or require the public caller's minImdOut to be at least a TWAP-based floor. Not in this launch's 8 contracts (deployed from launch.burner.json after), so it can be fixed before setBuybackBurner without touching the launch set.","line":121,"path":"src/ImdBuybackBurner.sol","reproduction":"State: burner deployed on the real 1% ETH/IMD pool, holds 1 ETH of released buyback, lastCuratorSwapAt + 60 days < now, lastPublicSwapAt == 0. Attacker tx bundle in one block: (1) swap X ETH -> IMD on the pool to push the price up; (2) burner.burnEth(0.05 ether, 1, now) from any EOA -> passes all checks (amountIn == PUBLIC_MAX, minImdOut == 1 > 0), swaps 0.05 ETH at the pushed price and burns a near-zero amount of IMD; (3) swap the IMD from (1) back to ETH, receiving the 0.05 ETH less fees. Expected: a public swap that cannot be worse than roughly the fair price. Actual: imdOut can be as low as 1 wei and the swap still succeeds; repeatable every PUBLIC_GAP (1 day) until the balance is gone or the curator swaps.","severity":"low","snippet":"        if (minImdOut == 0) revert NoMinimum();","title":"Public burnEth lets the caller choose minImdOut: each public swap is a 0.05 ETH sandwich opportunity, once a day, for as long as the curator is idle"},{"citation":"resolved","description":"The view the README names for front ends ('five per wallet in all, mintedBy, allowanceOf') returns cap - mintedBy[buyer] capped by unsold, regardless of whether the sale is open, whether the buyer passes the holders gate (_tokenGate / isMember), or the seat cap used by buyWithSeat. During the window a non-holder reads allowanceOf == 2 and buyMany reverts NotEligible; a seat holder whose seat already bought its cap reads 2 and buyWithSeat reverts SeatLimit. Invariant guide, interface guarantees: a query that differs from the execution function. No funds at risk; UI/integration correctness only. Fix: return 0 when !saleOpen, and when _inGate(saleOpenedAt) && !holdsToken(buyer) && !isMember(buyer) (seat buyers must query mintedBySeat separately, or add allowanceOfSeat).","line":582,"path":"src/ArtifactsFactory.sol","reproduction":"State: gate set (seats, IMD, 10e18, 24h), phases (12h,2,12h,3), sale open, Bob holds no IMD and no seat. Call factory.allowanceOf(bob) -> 2. Call vm.prank(bob); factory.buyMany{value: 0.02 ether}(2, address(0)) -> reverts HolderGate.NotEligible. Also with saleOpen == false (curator paused): allowanceOf(anyone) -> 5 while buy reverts SaleClosed.","severity":"info","snippet":"    function allowanceOf(address buyer) external view returns (uint256) {\n        if (saleEnded) return 0;\n        (uint256 cap,) = currentPhase();","title":"allowanceOf() promises an allowance the buy path refuses: it ignores the holders window and the seat cap"},{"citation":"resolved","description":"finishFallbackDraw is permissionless and _fallbackLive keeps a draw alive while its target hash is readable (BLOCKHASH 256 blocks, then EIP-2935's 8,191). Once the hash is gone, startFallbackDraw(requestId) passes again (fallbackInFlight == requestId, _fallbackLive false) and picks a new target. So the property 'a started draw's result stands; nobody can drop a result they dislike' depends on an off-chain keeper (the README says the house runs one) or any third party finishing within ~27 hours. If no one does, the buyer who computed keccak256(h, requestId) % left from the public hash and dislikes the edition simply waits and restarts, as often as it takes. This is only reachable after Chainlink has been silent for FALLBACK_BLOCKS and is acknowledged in the README; recorded here so the keeper's liveness is understood to be part of the fairness guarantee rather than a convenience. A contract-level alternative, if wanted: store the target hash the first time anyone touches the draw after target (e.g. let rerequestRandomness/claim/any factory call persist _hashOf(target) into fallbackHash[requestId] while readable), so a result once observable can no longer expire.","line":445,"path":"src/ArtifactsFactory.sol","reproduction":"State: purchase at block P with request R never answered; block.number >= P + 21,600 and >= lastAnsweredBlock + 21,600. (1) Anyone startFallbackDraw(R) -> fallbackBlock[R] = T = block.number + 5. (2) Nobody calls finishFallbackDraw(R) for 8,192 blocks after T (BLOCK_HISTORY no longer serves T). (3) Buyer calls startFallbackDraw(R) again -> succeeds (expected: FallbackPending, since a draw was started and its hash existed for 27 hours), new target T2, a different edition. Repeat until the drawn edition suits the buyer.","severity":"info","snippet":"        return block.number <= target || _hashOf(target) != bytes32(0);","title":"A started fallback draw is only final if someone finishes it within ~8,191 blocks; otherwise the buyer may restart it and re-roll"}],"hash":"367f08106d51fe7429b8b7841aece84fb71376a454177aed3c41fd1cc6461a01","nodeId":"2ebc77b5-8207-4dfa-9eb5-9ca523554f66","outcome":"completed","summary":"The review is complete. The findings file is written and validated, the scratch test directory is removed, and the working tree has no stray files.\n\n**Outcome.** No critical, high or medium economic defect was found in the launch set. The ledger split, the resale escrow, the auction and the VRF assignment conserve value on every path I traced. The findings file holds four entries: two low, two informational.\n\n**Findings written to .imd-findings.json**\n\n- **Low, holders-first gate is a bare balanceOf.** The token path of the holders window in both ArtifactsFactory and ArtifactsSource admits whoever holds the minimum IMD at call time. One balance handed between wallets, or borrowed inside a single transaction, lets non-holders buy during the window and lets one actor exceed the phase caps. Reproduced with a scratch Foundry test on this tree: six editions bought in the two-per-wallet phase with one 10 IMD balance, and a contract that borrows IMD, buys two, and returns it in one call. No ETH is lost; the allocation fairness the window exists for is what breaks.\n- **Low, public buyback swap minimum is the caller's own.** After 60 idle days anyone swaps 0.05 ETH with any nonzero minimum, so each daily public swap is a sandwich opportunity worth up to about 0.05 ETH to the sandwicher. The README accepts the bound. I recorded the economics because the leak repeats daily until the balance is gone, and the burner is outside the eight launched contracts, so it can be fixed before setBuybackBurner.\n- **Info, allowanceOf diverges from the buy path.** The view reports an allowance for non-holders during the window and for paused sales.\n- **Info, an unfinished fallback draw can be restarted.** If nobody finishes a fallback draw within about 8,191 blocks its hash expires and the buyer may restart it to re-roll. Only reachable after three days of Chainlink silence, and the README relies on the house keeper.\n\n**Coverage.** All 117 listed entry points have a row, 113 marked holds with a one-line reason, 4 marked finding. Five extra rows record the invariants I checked: ETH and IMD conservation in ArtHouse, escrow conservation in ArtifactsPiece, auction conservation in ArtifactsSource, the assigned-at-most-sold-at-most-255 bound, and the launch.json manifest, whose constructor arguments match each constructor in order.\n\n**Not reached in depth.** The KeyProof cryptography behind proveFakeKey and knowsWrap, and the renderer and seal encoding, are outside the economics area and were only checked for how their outcomes move funds.\n\nNo source files were changed. The code can be deployed as it is from this commit; the two low findings are design tradeoffs the author should confirm rather than blockers.","treeHash":null,"usage":{"cachedInputTokens":2337346,"inputTokens":514,"model":"claude-fable-5-1","outputTokens":53962,"runtime":"claude","turns":39,"wallClockMs":1196055}},{"artifacts":[],"attempt":1,"bundleHash":"89e8123993122a530dab92443aa07d0e0161f51014003b77f0729ab6500a1a57","device":"7f1dec5ffcbde1d8","findings":[{"description":"finishFallbackDraw maps the target block's hash to an edition through _assign, whose result depends on how many editions are left and on the Fisher-Yates pool at the moment the draw is finished (idx = word % (255 - assigned)). rawFulfillRandomWords only refuses answers for the fallback's own request id (fallbackBlock[requestId]); answers to any other request, including a purchase made after the fallback started, still land while the fallback is live. So once the target block exists, its hash is public but the edition is not fixed: anyone who wants a different result can wait for, or cause, another assignment before finishing the draw. The fallback's buyer can compute both outcomes off-chain, then either finish at once (anyone may) or buy one more edition and let Chainlink's answer land first, and keep whichever edition they prefer. The comments at lines 96-98 and 418-419 say no answer can land between the hash becoming known and the draw finishing, and that the draw's result stands. That holds only if Chainlink stays silent; it does not hold once Chainlink answers again (for example, after a subscription is refunded). Impact: on the fallback path only, after three days with no Chainlink answer, the buyer gets to pick between two or more random editions. No funds are lost and the edition count stays exact. One possible fix that keeps the design: when the draw is started, refuse new purchases' VRF answers (or new purchases) until it finishes or dies, the same way rerequestRandomness already refuses with FallbackBusy. Another: derive the edition only from the hash and the request, for example by fixing the draw's remaining-set size and pool snapshot when the draw starts.","line":463,"path":"src/ArtifactsFactory.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Fixture} from \"test/Fixture.sol\";\n\ncontract FallbackRerollTest is Fixture {\n    function test_aPublicFallbackHashStillLetsTheBuyerRerollByBuyingAnother() public {\n        _publishAll();\n        _openSale(1 ether);\n        vm.prank(alice);\n        uint256 a = factory.buy{value: 1 ether}(address(0));\n        vm.roll(vm.getBlockNumber() + factory.FALLBACK_BLOCKS());\n        factory.startFallbackDraw(a);\n        uint256 target = factory.fallbackBlock(a);\n        vm.roll(target + 1);\n        uint256 snap = vm.snapshotState();\n        factory.finishFallbackDraw(a);\n        uint256 finishedNow = factory.requestEdition(a);\n        vm.revertToState(snap);\n        vm.prank(alice);\n        uint256 c = factory.buy{value: 1 ether}(address(0));\n        vrf.fulfill(c, 0);\n        factory.finishFallbackDraw(a);\n        assertEq(factory.requestEdition(a), finishedNow, \"a started draw whose hash is public must give one result\");\n    }\n}","reproduction":"Fixture deployment (test/Fixture.sol), all 255 pieces published, sale open at 1 ether. alice buys (request a). Roll FALLBACK_BLOCKS and call startFallbackDraw(a); roll to fallbackBlock(a)+1, so the target hash is public. Branch 1: finishFallbackDraw(a) gives edition 22. Branch 2 (snapshot reverted): alice buys again (request c), vrf.fulfill(c, 0) succeeds, then finishFallbackDraw(a) gives edition 212. Expected: the same edition in both branches, as the comments promise. Actual: 22 != 212, so the buyer chooses.","severity":"low","title":"A started fallback draw's result can still be changed after its block hash is public, by having another request answered first"}],"hash":"481b148423ba761f03abe9dc937e4142ffec48ff5e61c1eb177be34a87f8d778","nodeId":"a54ccfc2-0fc2-4268-b241-74da5d5ca663","outcome":"completed","summary":"I added a stateful test suite for the edition draw's recovery paths and found one low-severity defect, which I reported instead of writing a test that passes over it. No application code, configuration or launch.json was changed, so every contract's runtime code is the same as at this commit.\n\n**Checks:** `forge build` passes. Full `forge test` with the verifier's seed: 259 passed, 0 failed, 2 skipped. The two skipped are the mainnet fork suites, which need an RPC URL. Those runs against the real pool and the real Chainlink coordinator are still owed.\n\n**Why this suite:** after my last round, another contributor changed how `ArtifactsFactory` handles the fallback draw (the backup draw used when Chainlink never answers). The existing factory invariant test never exercised that path.\n\n**New file: `test/invariants/FallbackDrawInvariant.t.sol`**\n- **What it does at random:** buys; Chainlink answers, including ones whose callback runs out of gas and late answers to replaced request ids; re-requests by the buyer, the curator and strangers; fallback draws started and finished by anyone; and large block jumps (past 256, 7,500, 8,191 and 21,600 blocks). A stand-in at the block-hash history address keeps each draw's hash for 8,191 blocks.\n- **Invariants:**\n  - every paid purchase ends up with exactly one edition, for its buyer, or is still waiting on one known request;\n  - replaced request ids stay dead;\n  - at most one fallback draw is live at a time;\n  - retries and fallbacks never move ETH.\n- **Checks on each call:**\n  - a Chainlink answer is refused only once its own draw's block has passed;\n  - a live draw can't be re-requested away or restarted;\n  - a fallback can't start while Chainlink could still answer;\n  - a draw only finishes from a readable hash;\n  - each refusal gives the expected error.\n- **Fixed cases:** two sequences pin the main routes.\n- **Not vacuous:** I checked that the random runs actually reach finished draws, refused answers and re-requests with the verifier's seed.\n\nThe run settings (96 runs × 64 calls) are set inside the file, and `test/invariants/ADDED_COVERAGE.md` has a paragraph describing the suite.\n\n**Finding (low), in `.imd-findings.json`:** once a fallback draw's block hash is public, which edition it gives can still change. `finishFallbackDraw` (`src/ArtifactsFactory.sol:463`) picks the edition from the hash *and* from how many editions are left at the moment it is finished. Chainlink's answers to *other* requests are still accepted during that window. So the buyer can work out both outcomes, then either finish at once or buy one more edition and let Chainlink answer it first, and keep whichever edition they prefer.\n- **Reproduction:** finishing straight away gives edition 22; buying again, having that answered, then finishing gives 212.\n- **Contradicts the code's own comments**, which say the draw's result stands and no answer can land in between (lines 96–98 and 418–419). That only holds while Chainlink stays silent.\n- **Impact:** only on the fallback path, after three days without a Chainlink answer. No ETH is at risk and the edition count stays exact.\n- **Possible fixes** that keep the design are in the report.\n- **Proof caveat:** the proof I attached imports the project's shared `test/Fixture.sol`, so it isn't fully self-contained as the rules ask. A proof is optional for a low finding.","treeHash":"17188742c81b389631b024010e4802043ba618e3","usage":{"cachedInputTokens":1313791,"inputTokens":40,"model":"claude-opus-5-5","outputTokens":28165,"runtime":"claude","turns":21,"wallClockMs":635131}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"6b16b4979d227241","findings":[{"citation":"resolved","description":"startFallbackDraw (lines 426-438) gates on purchaseBlock (carried across re-requests) and lastAnsweredBlock, but never on whether the coordinator still holds the request being drawn (_stillHeld). rerequestRandomness is allowed once VRF_RETRY_BLOCKS (7,500) have passed, so at purchase+21,600 blocks a buyer can call rerequestRandomness(old) and startFallbackDraw(new) in the same block. The coordinator now holds a live request (Chainlink keeps one up to 24h) while the fallback block's hash becomes public five blocks later. rawFulfillRandomWords (line 416-420) does not check fallbackBlock, so a VRF answer still assigns an edition until someone calls finishFallbackDraw. The buyer computes the fallback edition from the public hash and either finishes the draw (front-running a VRF fulfilment they see in the mempool) or leaves it unfinished and lets VRF answer. That contradicts the lastAnsweredBlock comment (lines 97-98: no answer can land between a fallback hash becoming known and the draw finishing) and breaks uniform assignment. Reached whenever a subscription runs dry for ~3 days and is topped up. Reported by audit_flow; reproduced with its proof (fails on this tree). Related: finding 7 (a started draw expires and can be restarted). Fix sketch, preserving the design: in startFallbackDraw require !_stillHeld(requestId) || block.number >= requestBlock[requestId] + VRF_RETRY_BLOCKS, and/or in rawFulfillRandomWords revert when fallbackBlock[requestId] != 0 && block.number > fallbackBlock[requestId].","line":430,"path":"src/ArtifactsFactory.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport \"forge-std/Test.sol\";\nimport {ArtStorage} from \"src/ArtStorage.sol\";\nimport {ArtHouse} from \"src/ArtHouse.sol\";\nimport {KeyProof} from \"src/KeyProof.sol\";\nimport {ArtifactsPiece} from \"src/ArtifactsPiece.sol\";\nimport {ArtifactsFactory} from \"src/ArtifactsFactory.sol\";\nimport {IVRFCoordinatorV2Plus, Traits} from \"src/interfaces/Interfaces.sol\";\n\ncontract VRFStub {\n    uint256 public nextId = 1;\n    mapping(uint256 => address) public consumer;\n    mapping(uint256 => bytes32) public s_requestCommitments;\n\n    function requestRandomWords(IVRFCoordinatorV2Plus.RandomWordsRequest calldata) external returns (uint256 id) {\n        id = nextId++;\n        consumer[id] = msg.sender;\n        s_requestCommitments[id] = keccak256(abi.encode(id, msg.sender));\n    }\n\n    function fulfill(uint256 id, uint256 word) external {\n        delete s_requestCommitments[id];\n        uint256[] memory w = new uint256[](1);\n        w[0] = word;\n        ArtifactsFactory(consumer[id]).rawFulfillRandomWords(id, w);\n    }\n}\n\n/// A buyer whose draw Chainlink left unanswered for FALLBACK_BLOCKS re-requests it and starts the fallback on the new\n/// request in the same block. Once the fallback block's hash is public the buyer knows that edition; if they dislike\n/// it they leave the draw unfinished, and Chainlink (subscription topped up) can still answer the fresh request,\n/// assigning a different edition. The buyer chooses between two random outcomes.\ncontract FallbackChoiceTest is Test {\n    address curator = address(0xC0);\n    address artist = address(0xA7);\n    address alice = address(0xA11CE);\n    VRFStub vrf;\n    ArtifactsFactory factory;\n\n    function setUp() public {\n        ArtStorage store = new ArtStorage(curator);\n        ArtHouse house = new ArtHouse(curator, address(store), address(0xD34a99Bc0f67aE1bbd63C660e6d0b0dd03E263B7));\n        KeyProof kp = new KeyProof();\n        ArtifactsPiece impl = new ArtifactsPiece(address(kp));\n        factory = new ArtifactsFactory(curator, address(house), address(impl));\n        vrf = new VRFStub();\n        vm.startPrank(curator);\n        store.setHouse(address(house));\n        house.approveArtist(artist, \"artist\");\n        house.setSaleModule(address(factory), true);\n        house.registerModuleCollection(address(factory), artist);\n        factory.configureVRF(address(vrf), bytes32(uint256(1)), 1, false);\n        for (uint256 i = 1; i <= 255; ++i) {\n            factory.setPiece(i, Traits(\"t\", \"p\", 3, \"d\"), abi.encodePacked(\"ct\", i), keccak256(abi.encodePacked(i)));\n        }\n        factory.lock();\n        factory.setPrice(1 ether);\n        factory.setSaleOpen(true);\n        vm.stopPrank();\n        vm.deal(alice, 10 ether);\n    }\n\n    function test_noChainlinkAnswerAfterTheFallbackHashIsKnown() public {\n        vm.prank(alice);\n        uint256 id1 = factory.buy{value: 1 ether}(address(0));\n        // Chainlink silent (e.g. the subscription ran dry) for FALLBACK_BLOCKS\n        vm.roll(block.number + factory.FALLBACK_BLOCKS());\n        vm.prank(alice);\n        uint256 id2 = factory.rerequestRandomness(id1); // a fresh request the coordinator now holds\n        bool started;\n        try factory.startFallbackDraw(id2) {\n            started = true;\n        } catch {}\n        if (!started) return; // refusing a fallback while Chainlink still holds the request also closes the choice\n        uint256 target = factory.fallbackBlock(id2);\n        vm.roll(target + 1);\n        bytes32 h = keccak256(\"target block hash\");\n        vm.setBlockhash(target, h);\n        uint256 fallbackEdition = uint256(keccak256(abi.encode(h, id2))) % 255 + 1;\n        // alice knows fallbackEdition now and does not finish; Chainlink answers the fresh request\n        uint256 word = fallbackEdition; // any word drawing another edition\n        (bool ok,) = address(vrf).call(abi.encodeCall(VRFStub.fulfill, (id2, word)));\n        if (ok) {\n            emit log_named_uint(\"fallback edition (known, declined)\", fallbackEdition);\n            emit log_named_uint(\"edition assigned by the late VRF answer\", factory.requestEdition(id2));\n        }\n        assertFalse(ok, \"a VRF answer still lands after the fallback block's hash is public: the buyer picks\");\n    }\n}","reproduction":"State: factory locked, price 1 ether, VRF configured, sale open. 1) alice buy{1 ether}(0) at block B -> request id1; Chainlink silent. 2) vm.roll(B + 21,600): alice rerequestRandomness(id1) -> id2 (allowed: block >= requestBlock + 7,500 and the stub still holds id1); startFallbackDraw(id2) succeeds in the same block (purchaseBlock[id2] == B, lastAnsweredBlock == 0), target = block + 5. 3) vm.roll(target+1), blockhash(target) = h: fallback edition = keccak256(abi.encode(h, id2)) % 255 + 1 is now public; alice does not finish. 4) coordinator calls rawFulfillRandomWords(id2, [w]). Expected: refused (the started draw's result stands, as the NatSpec on rerequestRandomness and lastAnsweredBlock promise). Actual: succeeds and assigns a different edition; requestEdition(id2) != fallback edition. Run: forge test --match-path test/scratch/FallbackChoice.t.sol (fails on this tree with 'a VRF answer still lands after the fallback block's hash is public').","severity":"medium","snippet":"        if (block.number < lastAnsweredBlock + FALLBACK_BLOCKS) revert ChainlinkAnswering(); // ask it again instead","title":"Fallback draw can start on a re-requested id Chainlink still holds, so the buyer may choose between the fallback edition and a later VRF edition"},{"citation":"resolved","description":"holdsToken, holdsSeat and _ownsSeat use try/catch and the contract's NatSpec (line 9) promises that a contract that cannot answer counts as not held. When the configured address has no code (EOA, typo, or a token that exists only on another chain) the call returns empty data and the ABI decoding of the return value fails in the caller: that is not a callee revert, so the catch clause does not run and the whole call reverts with empty data. _setGate (lines 29-39) accepts a code-less seats/token, unlike _setMemberGate (line 47) which refuses one precisely because 'a typo would shut every member out'. ArtifactsFactory._tokenGate (line 347) evaluates holdsToken before isMember, so with a code-less gate token every buy and buyMany reverts for the whole holders window (up to MAX_GATE_SECONDS = 30 days) including for legitimate members; ArtifactsFactory.setGate reverts SaleIsOpen after the sale first opened (line 261), so the curator cannot repair it and endSale (ending the edition sale for good) is the only exit. With code-less seats, buyWithSeat reverts and ArtifactsSource.bid (line 189, holdsSeat first) reverts for every bidder; there the gate can still be corrected before the first bid. Reported by audit_math; its proof fails on this tree in all three cases. Finding 6 shows how this misconfiguration can arise from the launch's own addresses. Minimal fix: return false when the target has no code (or use the bounded raw staticcall pattern isMember already uses), and/or refuse code-less seats/token in _setGate as _setMemberGate does.","line":81,"path":"src/base/HolderGate.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {ArtStorage} from \"src/ArtStorage.sol\";\nimport {ArtHouse} from \"src/ArtHouse.sol\";\nimport {KeyProof} from \"src/KeyProof.sol\";\nimport {ArtifactsPiece} from \"src/ArtifactsPiece.sol\";\nimport {ArtifactsFactory} from \"src/ArtifactsFactory.sol\";\nimport {ArtifactsSource} from \"src/ArtifactsSource.sol\";\nimport {HolderGate} from \"src/base/HolderGate.sol\";\nimport {Traits, IVRFCoordinatorV2Plus} from \"src/interfaces/Interfaces.sol\";\n\ncontract VRFStub {\n    uint256 public nextId = 1;\n\n    function requestRandomWords(IVRFCoordinatorV2Plus.RandomWordsRequest calldata) external returns (uint256 id) {\n        id = nextId++;\n    }\n}\n\ncontract MemberStub {\n    mapping(address => uint256) public points;\n\n    function set(address a, uint256 p) external {\n        points[a] = p;\n    }\n}\n\n/// @dev HolderGate promises \"a seat, token or membership contract that cannot answer counts as not held\". A gate\n/// address with no code (an EOA, or a token address mistyped) does not: Solidity's try/catch only catches a revert\n/// inside the callee; empty return data fails ABI decoding in the caller and that revert is not caught. During the\n/// holders window every buy()/buyMany() then reverts, even for a legitimate member, and the factory's gate is locked\n/// once the sale has opened.\ncontract GateNoCodeTest is Test {\n    address curator = makeAddr(\"curator\");\n    address artist = makeAddr(\"artist\");\n    address member = makeAddr(\"member\");\n    address eoaToken = makeAddr(\"not-a-token\");\n\n    ArtHouse house;\n    ArtifactsFactory factory;\n    ArtifactsSource source;\n    MemberStub members;\n\n    function setUp() public {\n        ArtStorage store = new ArtStorage(curator);\n        house = new ArtHouse(curator, address(store), makeAddr(\"imd\"));\n        KeyProof kp = new KeyProof();\n        ArtifactsPiece impl = new ArtifactsPiece(address(kp));\n        factory = new ArtifactsFactory(curator, address(house), address(impl));\n        source = new ArtifactsSource(curator, address(house), address(impl));\n        members = new MemberStub();\n        members.set(member, 1);\n\n        vm.startPrank(curator);\n        house.approveArtist(artist, \"A\");\n        house.setSaleModule(address(factory), true);\n        house.registerModuleCollection(address(factory), artist);\n        for (uint256 i = 1; i <= 255; ++i) {\n            factory.setPiece(i, Traits(\"t\", \"p\", 1, \"d\"), hex\"01\", keccak256(abi.encode(i)));\n        }\n        factory.lock();\n        factory.setPrice(1 ether);\n        factory.configureVRF(address(new VRFStub()), bytes32(uint256(1)), 1, false);\n        // the holders window: IMD holders (address mistyped: no code there) or members, for 7 days\n        factory.setGate(address(0), eoaToken, 1, 7 days);\n        factory.setMemberGate(address(members), bytes4(keccak256(\"points(address)\")), 1);\n        factory.setSaleOpen(true);\n        vm.stopPrank();\n        vm.deal(member, 10 ether);\n    }\n\n    /// @dev Documented behaviour: a token that cannot answer counts as not held, so the view returns false.\n    function test_holdsToken_noCode_returnsFalse() public view {\n        assertFalse(factory.holdsToken(member));\n    }\n\n    /// @dev A member (the third way in) must be able to buy during the window; holdsToken reverting in the caller\n    /// stops them before isMember is ever consulted.\n    function test_member_canBuy_duringWindow_whenTokenHasNoCode() public {\n        assertTrue(factory.isMember(member));\n        vm.prank(member);\n        factory.buy{value: 1 ether}(address(0));\n        assertEq(factory.sold(), 1);\n    }\n\n    /// @dev A non-holder is refused with NotEligible, not with an empty decoding revert.\n    function test_nonHolder_revertsNotEligible() public {\n        address nobody = makeAddr(\"nobody\");\n        vm.deal(nobody, 1 ether);\n        vm.prank(nobody);\n        vm.expectRevert(HolderGate.NotEligible.selector);\n        factory.buy{value: 1 ether}(address(0));\n    }\n}","reproduction":"State: factory published and locked, price 1 ether, VRF configured; curator setGate(address(0), T, 1, 7 days) with T an address without code; setMemberGate(M, points(address), 1) where M returns 1 for member; setSaleOpen(true). Call 1: factory.holdsToken(anyone). Expected: false. Actual: reverts with empty data. Call 2: member buy{1 ether}(0) inside the window. Expected: succeeds (isMember true). Actual: reverts with empty data, sold stays 0; same for buyMany for every wallet until saleOpenedAt + 7 days; setGate now reverts SaleIsOpen. Call 3: non-holder buy. Expected: NotEligible. Actual: revert with no data. Seats variant: ArtifactsSource.setGate(S, 0, 0, 1 days) with code-less S, setAuction, any bid{reserve}(0) reverts with empty data. Run: forge test --match-path test/scratch/GateNoCode.t.sol (3 tests fail on this tree).","severity":"medium","snippet":"        try IBalanceOf(t).balanceOf(account) returns (uint256 b) {","title":"HolderGate: a gate token or seats address with no code reverts every gated buy/bid instead of counting as not held, and ArtifactsFactory.setGate is locked once the sale opens"},{"citation":"resolved","description":"finishFallbackDraw is the only function that clears fallbackBlock[requestId], and it reverts FallbackMissed (line 455) once the target hash has left BLOCKHASH and the EIP-2935 history (more than 8,191 blocks). From then on rerequestRandomness reverts FallbackPending (line 377) for the buyer and the curator alike, even though _fallbackLive(requestId) is false. The only remaining path is startFallbackDraw, which reverts ChainlinkAnswering (line 430) while any purchase was answered within FALLBACK_BLOCKS (21,600 blocks). So while the sale is live and Chainlink works, every answer to another buyer pushes this buyer's paid edition further back; it is assigned only once Chainlink has been silent for ~3 days (in practice after the sale ends), although a plain re-request would be answered at once. Reported by audit_flow; reproduced with test/scratch/DeadFallback.t.sol (passes on this tree, i.e. the stuck state is reachable). Fix sketch: in rerequestRandomness replace the check with `if (_fallbackLive(requestId)) revert FallbackPending();` and delete fallbackBlock[requestId] (and fallbackInFlight if equal) when re-requesting.","line":377,"path":"src/ArtifactsFactory.sol","reproduction":"1) alice buy -> id at block 1000; vm.roll(+21,600); anyone startFallbackDraw(id), target T = block+5. 2) vm.roll(T + 8,193): finishFallbackDraw(id) reverts FallbackMissed. 3) bob buy -> idBob; coordinator fulfils idBob, lastAnsweredBlock = block.number. 4) alice rerequestRandomness(id): expected a fresh request (the draw is dead, _fallbackLive false); actual revert FallbackPending; same for the curator. startFallbackDraw(id): actual revert ChainlinkAnswering, and keeps reverting while any request is answered within 21,600 blocks. requestEdition(id) == 0 throughout.","severity":"low","snippet":"        if (fallbackBlock[requestId] != 0) revert FallbackPending();","title":"A fallback draw whose block hash expired blocks rerequestRandomness forever, and restarting it waits until Chainlink has answered nothing for 3 days"},{"citation":"resolved","description":"setAuction only opens when house.canRecordSale(source) is true (line 153) and its comment promises the winning bid can always settle, but ArtHouse.recordSale (ArtHouse.sol:463) re-reads saleModules[msg.sender] at settlement and reverts NotSaleModule; settle() calls it unconditionally at line 239 after setting settled = true, so the whole call reverts. ArtHouse.setSaleModule (line 203) has no guard against revoking a module whose auction holds live bids. After a revocation nobody can settle; the winner's ETH stays locked until endTime + SETTLE_GRACE, then voidUnsettled refunds them and the artist's sale is lost. No funds are lost and the actor is the curator, so this is an owner power to document (README's trust list covers split changes and the resale effect of revocation, not this). Reported by audit_permissions; reproduced by trace. If the promise is meant to hold, either refuse setSaleModule(module,false) while the module reports an open auction with a bid, or let settle() fall back to crediting through the piece's pull path; both change agreed behaviour and are the author's call.","line":239,"path":"src/ArtifactsSource.sol","reproduction":"Deploy per launch.json; curator approveArtist(artist), setSaleModule(source,true), registerModuleCollection(source,artist), storeRendererChunk, lock, setAuction(1 ether, now+1 day). alice bid{2 ether}(0). curator setSaleModule(source,false). vm.warp(endTime). Expected (setAuction comment): settle() succeeds. Actual: settle() reverts ArtHouse.NotSaleModule for every caller; voidUnsettled() reverts AuctionNotEnded until endTime + 7 days, then succeeds with refunds[alice] == 2 ether, no piece deployed, artist paid nothing.","severity":"low","snippet":"        house.recordSale{value: highBid}(address(this), highBidder, highBroker); // last: it pays the artist","title":"Owner can strand THE SOURCE auction after bids: settle() re-reads saleModules so setSaleModule(source,false) blocks settlement for everyone until a void 7 days after the end (trust gap)"},{"citation":"resolved","description":"After IDLE (60 days) without a curator swap, anyone may call burnEth(min(balance, 0.05 ether), minImdOut, deadline) with minImdOut >= 1 wei as the only slippage bound; the swap runs with sqrtPriceLimitX96 = MIN_SQRT_PRICE_LIMIT (no price limit). A caller who first buys IMD on the same pool, then triggers the public swap with minImdOut = 1, then sells back captures most of the 0.05 ETH less the pool's fees on their two legs. The README accepts this and bounds it per day, but the loss repeats every PUBLIC_GAP while the curator stays idle, so a burner holding N ETH leaks it over N/0.05 days with near-zero IMD actually burned. ImdBuybackBurner is not among the 8 contracts in launch.json (it comes from launch.burner.json and is set once with setBuybackBurner), so it can be changed before it is set without touching this launch. Reported by audit_economics; reproduced by trace (burnEth lines 110-133, unlockCallback 146-162). Minimal fix keeping the design: derive the public path's minimum on-chain from the pool's current price with a fixed tolerance, or require minImdOut >= a stored floor.","line":121,"path":"src/ImdBuybackBurner.sol","reproduction":"State: burner deployed on the 1% ETH/IMD pool holding 1 ETH, lastCuratorSwapAt + 60 days < now, lastPublicSwapAt == 0. One bundle: (1) swap X ETH -> IMD on the pool; (2) any EOA burnEth(0.05 ether, 1, now): passes (amountIn == PUBLIC_MAX, minImdOut == 1 > 0), swaps at the pushed price, burns near-zero IMD; (3) swap the IMD back. Expected: a public swap bounded near the fair price. Actual: imdOut can be 1 wei and the call succeeds; repeatable after PUBLIC_GAP (1 day) until the balance is gone or the curator swaps.","severity":"low","snippet":"        if (minImdOut == 0) revert NoMinimum();","title":"ImdBuybackBurner: the public burnEth path lets the caller set minImdOut, so each idle-period public swap is a sandwichable 0.05 ETH, repeatable daily (burner is deployed after this launch set)"},{"citation":"resolved","description":"launch.json passes 0xd34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7 as ArtHouse's immutable `imd` (line 15) and 0x0000ec93127baa929e58e97dd0095a2bfb38ec1d as the seats of BrokerPass (line 47) and SubmissionReviews (line 56), yet its notes (line 62) say 'Proof House application contracts for Sepolia', README.md line 4 says the repository holds the Sepolia contracts, README.md lines 9-10 give IMD as 0xd34a... on mainnet and 0x44a1Cd38474FB1748400E7DEb5F8D786ccE3F89A on Sepolia, and script/Deploy.s.sol:16 uses SEPOLIA_IMD = 0x44a1Cd.... Checked with cast code: on Sepolia both manifest addresses return 0x (no code) and 0x44a1Cd... has code; on mainnet both manifest addresses have code. The pinned policy's chain is not in front of me, so this is weighed as a consistency defect: if the launch runs on Sepolia, ArtHouse.mintWithIMD reverts forever (immutable, no setter: _pullIMD's balanceOf on an empty account fails to decode), BrokerPass.claimWithSeat and SubmissionReviews.reviewAsSeat revert with empty data, and a curator who follows the README's setGate(seats, IMD, ...) step with these addresses triggers finding 2 for the whole holders window. If the launch runs on mainnet the code is right and the notes/README are wrong. Needed evidence: the pinned launch policy's chainId; then either the two static addresses or the notes must change to match.","line":15,"path":"launch.json","reproduction":"cast code --rpc-url <sepolia> 0xd34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7 -> 0x; cast code --rpc-url <sepolia> 0x0000ec93127baa929e58e97dd0095a2bfb38ec1d -> 0x; cast code --rpc-url <sepolia> 0x44a1Cd38474FB1748400E7DEb5F8D786ccE3F89A -> code. On a chain where `imd` has no code: deploy per launch.json, create and seal a collection, setPrices(c, 0, 1e18), setSaleOpen(c, true); buyer mintWithIMD(c, 0, 0, 1e18). Expected: the IMD sale records. Actual: reverts with empty data at IERC20(imd).balanceOf (ArtHouse.sol:433) and no setter can change `imd`. BrokerPass.claimWithSeat(1) and SubmissionReviews.reviewAsSeat(0, 1, Back, '') likewise revert with empty data.","severity":"low","snippet":"    \"0xd34a99bc0f67ae1bbd63c660e6d0b0dd03e263b7\"","title":"launch.json hard-codes the mainnet IMD and seats addresses while its notes, the README and the deploy script describe a Sepolia deployment where neither address has code"},{"citation":"resolved","description":"_fallbackLive keeps a draw alive only while its target hash is readable (BLOCKHASH 256 blocks, then EIP-2935's 8,191). Once gone, startFallbackDraw(requestId) passes again (fallbackInFlight == requestId, _fallbackLive false) and picks a new target, so the property 'a started draw's result stands' rests on a keeper (the README says the house runs one) or any third party finishing within ~27 hours. A buyer who computed the edition from the public hash and dislikes it waits and restarts, as often as needed. Reachable only after Chainlink has been silent for FALLBACK_BLOCKS and acknowledged in the NatSpec (lines 34-36); recorded so the keeper's liveness is understood as part of the fairness guarantee. Reported by audit_economics; reproduced by trace. Same dead-draw state as finding 3, different consequence. A contract-level option: persist _hashOf(target) into storage the first time any call touches the draw after target while the hash is still readable.","line":445,"path":"src/ArtifactsFactory.sol","reproduction":"State: request R unanswered, block >= purchaseBlock + 21,600 and >= lastAnsweredBlock + 21,600. (1) startFallbackDraw(R) -> fallbackBlock[R] = T. (2) no finishFallbackDraw for 8,192 blocks after T. (3) startFallbackDraw(R) again: expected FallbackPending (a result existed for 27 hours); actual: succeeds, fallbackBlock[R] = new T2, a different edition. Repeatable.","severity":"info","snippet":"        return block.number <= target || _hashOf(target) != bytes32(0);","title":"A started fallback draw is final only if someone finishes it within ~8,191 blocks; afterwards the buyer may restart it and re-roll"},{"citation":"resolved","description":"ArtifactsFactory._tokenGate (line 347) and ArtifactsSource.bid (line 189) admit a caller when holdsToken(msg.sender) is true at call time; nothing is locked, snapshotted or consumed. A single gateMinBalance of IMD can be handed from wallet to wallet between transactions, each buying the phase cap, and a contract can borrow IMD, call buyMany and return it in one transaction. The seat path (mintedBySeat) and the member gate do not have this gap. Nobody loses ETH; what weakens is the allocation fairness the window and phases exist for. This is the documented semantics ('holders of at least minBalance of token'), and per-wallet caps are sybil-able after the window anyway, so it is recorded as a design note rather than a defect. Reported by audit_economics; reproduced by trace. If per-holder semantics are wanted, use a snapshot or a registration step before the sale opens.","line":82,"path":"src/base/HolderGate.sol","reproduction":"State: setGate(seats, IMD, 10e18, 24h), setMintPhases(12h, 2, 12h, 3), sale open, price 0.01 ETH. alice holds 10 IMD; bob and carol none. alice buyMany{0.02}(2,0) ok; alice imd.transfer(bob, 10e18); bob buyMany{0.02}(2,0): expected NotEligible, actual ok; bob -> carol, carol buyMany(2) ok: sold == 6 within the first 12 hours on one balance. Single-tx variant: contract F pulls 10 IMD, calls buyMany, returns it.","severity":"info","snippet":"            return b >= gateMinBalance;","title":"Holders window is a point-in-time balanceOf: one IMD balance (or a flash-borrowed one) admits unlimited wallets inside the window and past the per-wallet phase caps"},{"citation":"resolved","description":"allowanceOf returns cap - mintedBy[buyer] bounded by unsold whatever saleOpen, _inGate/holdsToken/isMember or mintedBySeat say. During the window a non-holder reads 2 and buyMany reverts NotEligible; a seat whose cap is used reads 2 and buyWithSeat reverts SeatLimit; with the sale paused it reads 5 and buy reverts SaleClosed. UI/integration correctness only, no funds at risk. Reported by audit_economics; reproduced by trace. Fix: return 0 when !saleOpen and when _inGate(saleOpenedAt) && !holdsToken(buyer) && !isMember(buyer); seat buyers query mintedBySeat.","line":582,"path":"src/ArtifactsFactory.sol","reproduction":"State: gate (seats, IMD, 10e18, 24h), phases (12h,2,12h,3), sale open, bob holds nothing. factory.allowanceOf(bob) -> 2; vm.prank(bob); factory.buyMany{value: 0.02 ether}(2, address(0)) -> reverts HolderGate.NotEligible. With saleOpen == false: allowanceOf(anyone) -> 5, buy reverts SaleClosed.","severity":"info","snippet":"    function allowanceOf(address buyer) external view returns (uint256) {","title":"allowanceOf() reports an allowance the buy path refuses: it ignores the sale being closed, the holders gate and the per-seat cap"},{"citation":"resolved","description":"registerPiece has no maximum per collection and nothing removes a piece. sealCollection does a cold SLOAD per piece (~2,100 gas), so above roughly 14,000 pieces the loop exceeds a 30M block and the collection can never be sealed or sold. Limited to that collection (the artist is curator-approved and the curator can create a fresh one), so informational. Reported by audit_math; reproduced by trace. A per-collection cap or a running finalized counter removes it.","line":394,"path":"src/ArtHouse.sol","reproduction":"Curator approves artist A and creates collection C. A registerPiece(C, i, hash_i, '', '') for i = 0..14,999, uploads and finalizes each. Curator sealCollection(C): expected CollectionSealed; actual the loop needs > 30M gas and cannot be included; setSaleOpen(C, true) reverts NotSealed forever.","severity":"info","snippet":"        for (uint256 i; i < c.pieceCount; ++i) {","title":"sealCollection loops over an artist-grown, unbounded piece count: a collection with ~14,000 registered pieces can never be sealed"}],"hash":"913cc6df3fe42370e499eb5bcfa988a13ab1f37919052b11d4f17b7c7fef1be5","nodeId":"361333f1-332b-44bd-b518-793465e3491d","outcome":"completed","summary":"Review complete. The findings file holds 10 findings and a full 112-row coverage record, with every snippet verified byte-for-byte against the tree and both attached proofs confirmed to fail on this code.\n\n**What I kept from the specialists, after reproducing each**\n\n- **Medium, fallback vs. VRF race** (`src/ArtifactsFactory.sol:430`). After 21,600 blocks of Chainlink silence a buyer can re-request and start a fallback draw on the fresh id in one block. The coordinator still holds that id, so a VRF answer can land after the fallback hash is public, and the buyer picks whichever edition they prefer. The specialist's proof fails on this tree, so it carries that proof.\n- **Medium, code-less gate address** (`src/base/HolderGate.sol:81`). A gate token or seats address with no code makes every gated buy or bid revert instead of counting as not held, because try/catch does not catch the return-data decoding failure. The factory's gate is locked once the sale opens, so only endSale gets out. The specialist's three proof tests fail on this tree.\n- **Low, dead fallback blocks re-request forever** (`src/ArtifactsFactory.sol:377`). I wrote my own scratch test and confirmed the stuck state: once a started draw's hash expires, the buyer and curator cannot re-request, and restarting waits until Chainlink has been silent for 3 days.\n- **Low, owner can strand THE SOURCE auction** by revoking the module after bids. Reproduced by trace and recorded as a trust gap.\n- **Low, public burnEth sandwich** repeats daily while the curator is idle. Kept, noting the burner is outside this launch's 8 contracts.\n- **Four info items**: fallback restart re-roll after the hash expires, point-in-time balance gate, allowanceOf mismatch, and the unbounded sealCollection loop. I downgraded the balance-passing item to info because it is the documented semantics.\n\n**New finding of my own, low.** The manifest passes the mainnet IMD address and the mainnet seats address while its notes, the README and the deploy script describe a Sepolia deployment. On Sepolia both addresses have no code and the README's own Sepolia IMD address does. If the pinned policy chain is Sepolia, mintWithIMD, claimWithSeat and reviewAsSeat are dead and the holders-gate misconfiguration above becomes the default. The pinned chain is not in front of me, so I named the evidence needed rather than asserting which side is wrong.\n\n**Coverage.** All 112 entry points answered: 95 hold, 17 point at a finding, none unreached. The burner entry points the first specialist could not verify were traced and hold. No source files were changed. The protected launch tests could not run here because they import a `floor/` helper absent from the tree, so deployability rests on the size check I ran (ArtifactsPiece is 191 bytes under the runtime limit) rather than on those tests.","treeHash":null,"usage":{"cachedInputTokens":2037392,"inputTokens":450,"model":"claude-fable-5-1","outputTokens":52616,"runtime":"claude","turns":34,"wallClockMs":1055572}},{"artifacts":[],"attempt":1,"bundleHash":"bb9a2bb18e6a6d4553f244f6124e3d8903eaec3402bc570181db86eaa58d7f60","device":"60c045240bb09c33","findings":[],"hash":"a40d91eafc3bfc824bdab13c0b51505462ee4346f93508298f9f7f52e5e3c116","nodeId":"729a3922-4e3a-4e5d-a11b-9e9bf354faae","outcome":"completed","summary":"The responses file is at the repository root and is excluded from git by the harness's own `.git/info/exclude` entry, which is the intended place for it. Nothing remains to request.\n\n## Recap\n\nBoth reopened findings reproduced on the starting tree (their proofs failed) and are fixed. Both proofs now pass, the full suite passes with the verifier's fuzz seed, and only the two contracts that needed to change have different runtime code.\n\n**Changes made**\n\n- `src/ArtifactsFactory.sol`: a fallback draw can no longer start on a request the coordinator still holds and that is younger than the retry window, so a buyer cannot hold a known fallback result against a later Chainlink answer. Once a started draw's block is behind us, the VRF callback refuses that request and only the fallback finish assigns it. The re-request path now refuses only a live draw and clears a dead one, which closes the advisory liveness gap where a buyer was stranded until Chainlink had been silent for three days.\n- `src/base/HolderGate.sol`: the three holder checks read `balanceOf` and `ownerOf` through a bounded raw static call that accepts exactly one return word. A gate address with no code, a revert, or a malformed answer counts as not held, so members still buy and everyone else gets the documented `NotEligible` error.\n- `test/NothingStuck.t.sol`: one test asserted the reported defect (a fallback on a request under a day old that Chainlink still held) and now expects the refusal. A new test covers the case where the coordinator answered with a failed callback.\n- `test/ReviewRound4.t.sol`: eleven regression tests. Nine fail on the previous source and the two that assert unchanged behaviour pass there.\n- `README.md` and `ADAPTATION.md`: fallback rules, the gate's code-less behaviour, the module-revocation trust assumption, and a round-4 record with verification details.\n- `.imd-responses.json`: answers for all nine findings. Three are marked fixed. Six advisory ones are disputed with reasons, mainly that they describe documented owner powers or design semantics the brief does not ask to change, or a contract this launch does not deploy.\n\n**Verification**\n\n| Check | Result |\n| --- | --- |\n| Supplied proofs (run from test/scratch) | 4 of 4 pass |\n| `forge build` | passes |\n| `forge test` with the verifier's seed | 244 passed, 0 failed, 2 skipped (fork suites needing an RPC URL) |\n| Runtime hashes vs previous source | only ArtifactsFactory and ArtifactsSource differ |\n\nNo build configuration, dependency, manifest or constructor changed. Nothing was committed, matching the previous round where the harness made the commit.","treeHash":"ef2219feb583b8fff6a9045c65718382011d1986","usage":{"cachedInputTokens":3101313,"inputTokens":772,"model":"claude-fable-5-1","outputTokens":42046,"runtime":"claude","turns":48,"wallClockMs":1826599}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"52c98c0dc01791cd","findings":[{"citation":"resolved","description":"Boundary: external call site, 'no code at receiver' corner case. HolderGate.holdsToken, holdsSeat and _ownsSeat rely on try/catch so that, as the contract's own NatSpec states (HolderGate.sol:9), 'a seat, token or membership contract that cannot answer counts as not held'. The assumption is that try/catch turns any failure into false. The actual behaviour differs when the configured address has no code (an EOA, a mistyped address, or a contract not yet deployed on this chain): solc 0.8.26 skips the extcodesize check because the call has return values, the call to the empty account returns zero bytes, and ABI decoding of the empty return data fails in the caller. A decoding failure is not a revert of the callee, so the catch clause never runs and the whole transaction reverts with empty data. _setGate (HolderGate.sol:29-39) checks nothing about `seats`/`token` having code, unlike _setMemberGate (line 47), which does. Consequences: (1) ArtifactsFactory._tokenGate (ArtifactsFactory.sol:347) evaluates holdsToken before isMember, so with a code-less gate token every buy() and buyMany() reverts for the whole holders window (up to MAX_GATE_SECONDS = 30 days), including for legitimate members of the member gate; ArtifactsFactory.setGate is locked once saleOpenedAt != 0 (line 261), so the curator cannot correct it, and endSale is the only way out, which ends the edition sale for good. (2) With code-less `seats`, buyWithSeat reverts in the window and ArtifactsSource.bid (ArtifactsSource.sol:189) reverts for every bidder (holdsSeat is evaluated first), so nobody can bid; there the curator can still fix it before the first bid. (3) The ledger's isEligibleBroker and HolderGate.isMember already use a raw staticcall with a return-size check, which handles this case; holdsToken/holdsSeat/_ownsSeat do not. The three fork/unit test suites only use mock contracts for seats and IMD, so this edge is untested. Minimal fix preserving the design: in holdsToken, holdsSeat and _ownsSeat return false when the target has no code (or use the same bounded staticcall pattern as isMember), and/or refuse a code-less seats/token address in _setGate as _setMemberGate does.","line":81,"path":"src/base/HolderGate.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {ArtStorage} from \"src/ArtStorage.sol\";\nimport {ArtHouse} from \"src/ArtHouse.sol\";\nimport {KeyProof} from \"src/KeyProof.sol\";\nimport {ArtifactsPiece} from \"src/ArtifactsPiece.sol\";\nimport {ArtifactsFactory} from \"src/ArtifactsFactory.sol\";\nimport {ArtifactsSource} from \"src/ArtifactsSource.sol\";\nimport {HolderGate} from \"src/base/HolderGate.sol\";\nimport {Traits, IVRFCoordinatorV2Plus} from \"src/interfaces/Interfaces.sol\";\n\ncontract VRFStub {\n    uint256 public nextId = 1;\n\n    function requestRandomWords(IVRFCoordinatorV2Plus.RandomWordsRequest calldata) external returns (uint256 id) {\n        id = nextId++;\n    }\n}\n\ncontract MemberStub {\n    mapping(address => uint256) public points;\n\n    function set(address a, uint256 p) external {\n        points[a] = p;\n    }\n}\n\n/// @dev HolderGate promises \"a seat, token or membership contract that cannot answer counts as not held\". A gate\n/// address with no code (an EOA, or a token address mistyped) does not: Solidity's try/catch only catches a revert\n/// inside the callee; empty return data fails ABI decoding in the caller and that revert is not caught. During the\n/// holders window every buy()/buyMany() then reverts, even for a legitimate member, and the factory's gate is locked\n/// once the sale has opened.\ncontract GateNoCodeTest is Test {\n    address curator = makeAddr(\"curator\");\n    address artist = makeAddr(\"artist\");\n    address member = makeAddr(\"member\");\n    address eoaToken = makeAddr(\"not-a-token\");\n\n    ArtHouse house;\n    ArtifactsFactory factory;\n    ArtifactsSource source;\n    MemberStub members;\n\n    function setUp() public {\n        ArtStorage store = new ArtStorage(curator);\n        house = new ArtHouse(curator, address(store), makeAddr(\"imd\"));\n        KeyProof kp = new KeyProof();\n        ArtifactsPiece impl = new ArtifactsPiece(address(kp));\n        factory = new ArtifactsFactory(curator, address(house), address(impl));\n        source = new ArtifactsSource(curator, address(house), address(impl));\n        members = new MemberStub();\n        members.set(member, 1);\n\n        vm.startPrank(curator);\n        house.approveArtist(artist, \"A\");\n        house.setSaleModule(address(factory), true);\n        house.registerModuleCollection(address(factory), artist);\n        for (uint256 i = 1; i <= 255; ++i) {\n            factory.setPiece(i, Traits(\"t\", \"p\", 1, \"d\"), hex\"01\", keccak256(abi.encode(i)));\n        }\n        factory.lock();\n        factory.setPrice(1 ether);\n        factory.configureVRF(address(new VRFStub()), bytes32(uint256(1)), 1, false);\n        // the holders window: IMD holders (address mistyped: no code there) or members, for 7 days\n        factory.setGate(address(0), eoaToken, 1, 7 days);\n        factory.setMemberGate(address(members), bytes4(keccak256(\"points(address)\")), 1);\n        factory.setSaleOpen(true);\n        vm.stopPrank();\n        vm.deal(member, 10 ether);\n    }\n\n    /// @dev Documented behaviour: a token that cannot answer counts as not held, so the view returns false.\n    function test_holdsToken_noCode_returnsFalse() public view {\n        assertFalse(factory.holdsToken(member));\n    }\n\n    /// @dev A member (the third way in) must be able to buy during the window; holdsToken reverting in the caller\n    /// stops them before isMember is ever consulted.\n    function test_member_canBuy_duringWindow_whenTokenHasNoCode() public {\n        assertTrue(factory.isMember(member));\n        vm.prank(member);\n        factory.buy{value: 1 ether}(address(0));\n        assertEq(factory.sold(), 1);\n    }\n\n    /// @dev A non-holder is refused with NotEligible, not with an empty decoding revert.\n    function test_nonHolder_revertsNotEligible() public {\n        address nobody = makeAddr(\"nobody\");\n        vm.deal(nobody, 1 ether);\n        vm.prank(nobody);\n        vm.expectRevert(HolderGate.NotEligible.selector);\n        factory.buy{value: 1 ether}(address(0));\n    }\n}","reproduction":"State: ArtifactsFactory published and locked, price 1 ether, VRF configured; curator calls setGate(address(0), T, 1, 7 days) where T is an address with no code (e.g. an EOA or a mistyped IMD address), setMemberGate(M, points(address), 1) where M answers points(member) = 1, then setSaleOpen(true). Call 1: factory.holdsToken(anyone). Expected (per HolderGate.sol:9): false. Actual: reverts with empty data (ABI decoding of empty return data). Call 2: member calls factory.buy{value: 1 ether}(address(0)) during the window. Expected: succeeds (isMember(member) is true). Actual: reverts with empty data; sold stays 0; the same for buyMany, for every wallet, until block.timestamp >= saleOpenedAt + 7 days, and setGate reverts SaleIsOpen so the curator cannot repair it. Call 3: a non-holder calls buy. Expected: revert NotEligible. Actual: revert with no data. Same root cause for seats: ArtifactsSource.setGate(S, address(0), 0, 1 days) with code-less S, setAuction(...), then any bid{value: reserve}(address(0)) reverts with empty data for every bidder during the window. The attached test (test/scratch/GateNoCode.t.sol) fails on the current code in all three cases and passes once holdsToken returns false for a code-less target.","severity":"medium","snippet":"        try IBalanceOf(t).balanceOf(account) returns (uint256 b) {","title":"HolderGate: a gate address with no code reverts every gated buy/bid instead of counting as not held (try/catch does not catch a decoding failure on empty return data)"},{"citation":"resolved","description":"Boundary: unbounded loop over a count the approved artist grows one by one with registerPiece (no maximum per collection). Each iteration does a cold SLOAD of pieces[collection][i].finalized (~2,100 gas), so a collection with more than roughly 14,000 registered pieces can never be sealed within a 30M block, and since no piece can ever be removed, the collection stays unsealable and unsellable forever. Impact is limited to that collection (the artist is curator-approved, and the curator can create a fresh collection), so this is informational; a cap on pieceCount per collection, or a seal that checks a running finalized counter instead of looping, removes it.","line":394,"path":"src/ArtHouse.sol","reproduction":"Curator approves artist A and creates collection C. A calls registerPiece(C, i, hash_i, '', '') for i = 0 .. 14999 (15,000 transactions). After finalizing every piece, curator calls sealCollection(C): expected CollectionSealed; actual: the loop needs more than 30M gas and the call cannot be included, so C can never be sealed, setSaleOpen(C, true) reverts NotSealed forever.","severity":"info","snippet":"        for (uint256 i; i < c.pieceCount; ++i) {","title":"sealCollection loops over an artist-controlled piece count with no upper bound"}],"hash":"b9ca8d5340de9e5a8a0e2705b40cdd5e0e8d270194d1f7be96458afc6238e24f","nodeId":"57c9a286-9a2d-48ec-9c64-2d0d9a8ace4b","outcome":"completed","summary":"The review is complete. No source file was changed. Git shows a clean tree apart from the ignored findings file and the scratch test.\n\n**What I audited.** The Math Precision, Boundary and Numerical Gap guides, applied to all eight launch contracts plus ImdBuybackBurner. I traced every division and basis-point split in the ledger and the resale escrow, the 5% raise rounding in the auction, the lazy Fisher-Yates in the VRF callback and fallback draw, every narrowing cast, SSTORE2's creation-code layout, base64 encoding, the ecrecover-based Chaum-Pedersen and Schnorr checks in KeyProof, the Uniswap v4 BalanceDelta unpacking, and every payable function's `msg.value` relationship. The arithmetic is conservative and value is conserved on every path, including the catch branch of `release()`.\n\n**Findings written to `.imd-findings.json`** (two findings, 115 coverage rows covering all 112 listed entry points plus three invariants):\n\n- **Medium, with proof.** HolderGate's `try/catch` around `balanceOf` and `ownerOf` does not catch calls to an address with no code: the empty return data fails ABI decoding in the caller and that revert is not caught. The contract's own NatSpec promises a gate contract that cannot answer \"counts as not held\". With a mistyped or code-less gate token, every `buy` and `buyMany` on ArtifactsFactory reverts for the whole holders window, even for legitimate members, and `setGate` is locked once the sale has opened so the curator cannot repair it. The same root cause blocks every bidder on ArtifactsSource if the seats address has no code, though that one is correctable before the first bid. The scratch test fails in all three cases on the current code and passes once the three gate views return false for a code-less target, which I confirmed in a throwaway copy.\n- **Info, no proof.** `sealCollection` loops over a piece count the approved artist grows without bound, so a collection with more than roughly 14,000 registered pieces can never be sealed. Impact is confined to that artist's own collection.\n\n**Not reached or outside my lenses.** Access control, economic incentives such as a buyer naming themselves as broker, and the randomness trust model were noted but belong to other specialists. I did not run the full 215-test suite or the fork tests, only the scratch proof.","treeHash":null,"usage":{"cachedInputTokens":1621043,"inputTokens":354,"model":"claude-fable-5-1","outputTokens":41987,"runtime":"claude","turns":34,"wallClockMs":656526}},{"artifacts":[],"attempt":1,"bundleHash":"962ffa377091757dd737eb2e01feafbcea797d786ace70c0fbbdb20c4a936381","device":"a13784fa5cb209c3","findings":[],"hash":"c44a54d365dd12f1b5b9154b2b0b9b2c7cbb7760ecfde1d7f5001bc15ec62814","nodeId":"a54ccfc2-0fc2-4268-b241-74da5d5ca663","outcome":"completed","summary":"Added three invariant suites plus failure-path, boundary, and fuzz tests for buybacks, pass claims, and reviews.\n\nOnly `test/` changed; contracts and configuration remain untouched.\n\nValidation: `forge build` passed. Full tests with the required seed: **244 passed, 0 failed, 2 RPC-dependent fork suites skipped**.","treeHash":"ab0f3bd9707ad43d3598f55700d958387af06854","usage":{"cachedInputTokens":4661504,"inputTokens":130504,"model":"gpt-6.1-sol","outputTokens":27614,"runtime":"codex","turns":16,"wallClockMs":1043300}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"2b170a76e3d9adca","findings":[{"citation":"resolved","description":"Clones.clone writes the standard EIP-1167 minimal proxy (runtime 363d3d373d3d3d363d73<impl>5af43d82803e903d91602b57fd5bf3). Byte 31 of every clone's runtime is 0xf4 (DELEGATECALL). ArtHouse.createCollection (src/ArtHouse.sol:229) and ArtifactsFactory._claim (src/ArtifactsFactory.sol:549) deploy every plain SVG collection and every one of the 255 ARTIFACTS edition pieces this way, so the ERC-721s holders actually own are proxies that DELEGATECALL into the ArtCollection / ArtifactsPiece implementations. The protected opcode scan passes only because it inspects the eight launched runtimes, where the 0xf4 sits inside PUSH data, not the contracts those runtimes create later. The launch recipe forbids proxies and DELEGATECALL in the application. The implementation address is baked into each clone's code, so this is not upgradeable, and the resale escrow and ETH held by a piece live in the clone's own storage; the design is otherwise sound, so this is a policy conflict rather than a fund-loss defect. The repository already contains the non-proxy alternative, Clones.copyCode (full byte copy, used for THE SOURCE at src/ArtifactsSource.sol:222); using it for editions and collections removes the DELEGATECALL at the cost of ~24 KB of code (about 5M gas) per claim. Whether to pay that or accept the deviation is a scope decision for the requester; do not change ArtifactsPiece's storage layout either way.","line":11,"path":"src/libs/Clones.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {ArtStorage} from \"src/ArtStorage.sol\";\nimport {ArtHouse} from \"src/ArtHouse.sol\";\nimport {KeyProof} from \"src/KeyProof.sol\";\nimport {ArtifactsPiece} from \"src/ArtifactsPiece.sol\";\nimport {ArtifactsFactory} from \"src/ArtifactsFactory.sol\";\nimport {IVRFCoordinatorV2Plus, Traits} from \"src/interfaces/Interfaces.sol\";\n\n/// @dev Stands in for Chainlink: hands out request ids and lets the test answer them.\ncontract CoordinatorStub {\n    uint256 public next;\n    uint256 public lastId;\n\n    function requestRandomWords(IVRFCoordinatorV2Plus.RandomWordsRequest calldata) external returns (uint256 id) {\n        id = ++next;\n        lastId = id;\n    }\n\n    function answer(ArtifactsFactory f, uint256 id, uint256 word) external {\n        uint256[] memory words = new uint256[](1);\n        words[0] = word;\n        f.rawFulfillRandomWords(id, words);\n    }\n}\n\n/// @notice The launch forbids proxies and DELEGATECALL in the application. Every plain collection and every\n/// ARTIFACTS edition the launched contracts create is an EIP-1167 proxy whose runtime byte 31 is 0xf4.\n/// This test runs the same opcode scan the protected floor runs on the launched runtimes over the contracts\n/// they create, and fails on the code as it is; it passes once pieces and collections are deployed as full\n/// copies (Clones.copyCode, already used for THE SOURCE) or any other non-DELEGATECALL form.\ncontract CloneDelegatecallTest is Test {\n    address owner = makeAddr(\"owner\");\n    address artist = makeAddr(\"artist\");\n    address buyer = makeAddr(\"buyer\");\n    address imd = makeAddr(\"imd\");\n\n    ArtStorage store;\n    ArtHouse house;\n    KeyProof keyProof;\n    ArtifactsPiece pieceImpl;\n    ArtifactsFactory factory;\n    CoordinatorStub vrf;\n\n    function setUp() public {\n        store = new ArtStorage(owner);\n        house = new ArtHouse(owner, address(store), imd);\n        keyProof = new KeyProof();\n        pieceImpl = new ArtifactsPiece(address(keyProof));\n        factory = new ArtifactsFactory(owner, address(house), address(pieceImpl));\n        vrf = new CoordinatorStub();\n\n        vm.startPrank(owner);\n        store.setHouse(address(house));\n        house.approveArtist(artist, \"Artist\");\n        house.setSaleModule(address(factory), true);\n        house.registerModuleCollection(address(factory), artist);\n        vm.stopPrank();\n    }\n\n    /// @dev The protected floor's scan (Contracts.protected.t.sol), applied to one address.\n    function _hasEscapeOpcode(address a) internal view returns (bool) {\n        bytes memory code = a.code;\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) return true;\n        }\n        return false;\n    }\n\n    function test_plainCollectionHasNoDelegatecall() public {\n        vm.prank(owner);\n        address collection = house.createCollection(\"Plain\", \"PLN\", artist);\n        assertGt(collection.code.length, 0, \"collection has no code\");\n        assertFalse(_hasEscapeOpcode(collection), \"plain collection runtime contains DELEGATECALL (EIP-1167 proxy)\");\n    }\n\n    function test_claimedEditionHasNoDelegatecall() public {\n        // publish 255 pieces, lock, configure VRF, open the sale\n        vm.startPrank(owner);\n        for (uint256 i = 1; i <= 255; ++i) {\n            factory.setPiece(\n                i,\n                Traits({title: \"T\", palette: \"PRISM\", colourCount: 9, direction: \"DIAGONAL\"}),\n                hex\"01\",\n                keccak256(abi.encodePacked(\"K\", i))\n            );\n        }\n        factory.lock();\n        factory.setPrice(1 ether);\n        factory.configureVRF(address(vrf), bytes32(uint256(1)), 1, false);\n        factory.setSaleOpen(true);\n        vm.stopPrank();\n\n        // one purchase, answered by the coordinator stub\n        vm.deal(buyer, 1 ether);\n        vm.prank(buyer);\n        uint256 requestId = factory.buy{value: 1 ether}(address(0));\n        vrf.answer(factory, requestId, 12345);\n        uint256 edition = factory.requestEdition(requestId);\n        assertTrue(edition >= 1 && edition <= 255, \"no edition assigned\");\n\n        // key posted to the buyer's viewing key, then the claim deploys the piece\n        vm.prank(buyer);\n        factory.registerViewingKey(bytes32(uint256(7)));\n        vm.prank(owner);\n        factory.postWrappedKey(edition, hex\"02aa\");\n        vm.prank(buyer);\n        address piece = factory.claim(edition);\n\n        assertEq(ArtifactsPiece(piece).ownerOf(1), buyer, \"piece not minted to buyer\");\n        assertFalse(_hasEscapeOpcode(piece), \"edition piece runtime contains DELEGATECALL (EIP-1167 proxy)\");\n    }\n}","reproduction":"State: the eight contracts deployed from launch.json; owner calls ArtHouse.approveArtist(artist, \"A\") then ArtHouse.createCollection(\"C\", \"C\", artist) -> returns address c. Expected (launch policy): c.code contains no 0xf4 opcode. Actual: c.code.length == 45 and uint8(c.code[31]) == 0xf4, and uint8(c.code[30]) == 0x5a (GAS, DELEGATECALL). The same holds for the address returned by ArtifactsFactory.claim(edition) after a VRF assignment and postWrappedKey: pieceContract(edition).code[31] == 0xf4. Scanning these addresses with the same loop as Contracts.protected.t.sol test_applicationRuntimeIsPresentBoundedAndHasNoEscapeOpcodes fails with \"forbidden application opcode\". Proof: test/scratch/CloneDelegatecall.t.sol (two tests, both FAIL on this code: 'plain collection runtime contains DELEGATECALL' and 'edition piece runtime contains DELEGATECALL'; run with FOUNDRY_TEST=test/scratch forge test --match-path test/scratch/CloneDelegatecall.t.sol).","severity":"medium","snippet":"            mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))","title":"Plain collections and ARTIFACTS editions are deployed as EIP-1167 DELEGATECALL proxies, which the launch forbids"},{"citation":"resolved","description":"The launch recipe requires applications to be fully configured in their constructors and lists post-deployment initialisation among the things the adapter must remove. Immediately after the eight deployments nothing works until the owner runs the sequence in launch.json's notes: ArtStorage.setHouse (src/ArtStorage.sol:26), ArtHouse.setSaleModule and registerModuleCollection (src/ArtHouse.sol:201, 236), ArtHouse.setBrokerPass (207), ArtHouse.setBuybackBurner (518), ArtifactsFactory.configureVRF (src/ArtifactsFactory.sol:232), BrokerPass.setClaimsOpenAt (src/BrokerPass.sol:67). Four of these are irreversible one-shot setters (setHouse, setBrokerPass, setBuybackBurner, setClaimsOpenAt), so a mistyped address after launch is permanent: setBrokerPass to a non-ERC-721 makes isEligibleBroker revert for every nonzero unapproved broker forever (see the separate low finding). The brief acknowledges that the owner configures everything afterwards, so this is reported as the policy conflict the reference asks for, not as a code defect. Where a value is known at deployment it can move into a constructor without changing behaviour: ArtStorage cannot take ArtHouse (it is deployed first) but ArtHouse already deploys ArtCollection in its constructor and could deploy ArtStorage the same way (dropping setHouse and the ArtStorage manifest entry); the VRF coordinator, key hash and subscription id and the buyback burner are static values that could be constructor arguments (the constructor must not call the coordinator, since the floor runs constructors on an empty chain). setSaleModule/registerModuleCollection and setBrokerPass are genuinely circular (the modules and the pass are deployed after the ledger) and would need a redesign to remove; the adapter should make that scope decision explicitly rather than silently.","line":26,"path":"src/ArtStorage.sol","reproduction":"State: the eight contracts deployed exactly as launch.json lists, nothing else called. Calls and results: ArtStorage.house() == address(0); ArtHouse.approveArtist(a, \"A\"), createCollection(...) -> c, registerPiece(c, 0, h, \"t\", \"d\") succeed, then ArtHouse.uploadChunk(c, 0, 0, hex\"3c737667\") reverts with ArtStorage.NotHouse(); ArtifactsFactory.buy{value: 1 ether}(address(0)) reverts SaleClosed() and cannot be opened (setSaleOpen(true) reverts NotLocked()/VRFNotConfigured()); ArtifactsSource.setAuction(1 ether, block.timestamp + 1 days) reverts NotLocked(), and after the owner stores the renderer and calls lock(...) it reverts NotRegistered() because ArtHouse.canRecordSale(source) is false until setSaleModule and registerModuleCollection; BrokerPass.claimsOpen() is false and claimWithSeat reverts ClaimsNotOpen(); ArtHouse.brokerPass() == 0 so no Broker Pass holder is a broker. Expected under the launch recipe: the deployed contracts are usable, or at least fully wired, without a post-deployment call sequence.","severity":"medium","snippet":"    function setHouse(address house_) external onlyOwner {","title":"Core wiring is configured by one-shot owner setters after deployment instead of in constructors"},{"citation":"resolved","description":"initialize has no caller check: the only guard is that controller is still zero. The launched implementation is locked (constructor sets controller = address(this)), but any wallet can deploy its own EIP-1167 clone (or byte copy) of the launched ArtifactsPiece and call initialize with controller_ = ArtifactsFactory, house_ = ArtHouse, pieceId_ = 1 and itself as `to`. The result is a contract named \"ARTIFACTS #001\", symbol ARTIFACTS, whose controller() returns the real factory and whose royaltyInfo returns the real artist's payout from the ledger, indistinguishable by ABI from a genuine edition. Funds are not at risk: ArtHouse.recordResale rejects it because ArtifactsFactory.isPiece(fake) is false (the resale then falls back to pull payments inside the fake, which only hurts its own users), and BrokerPass/SubmissionReviews resolve pieces through factory.pieceContract(id), not through the caller. The launch recipe also lists initializers among forbidden patterns. The same open initialize exists on ArtCollection (src/ArtCollection.sol:22). A minimal fix that keeps the design: have the factory/source pass themselves as msg.sender and require `msg.sender == controller_` and `controller_.code.length > 0`, or have each clone deployed by a factory that it checks (the clone is initialised in the same transaction it is created, so no genuine flow is affected).","line":128,"path":"src/ArtifactsPiece.sol","reproduction":"Inputs: attacker A deploys `fake = Clones.clone(address(artifactsPiece))` (the launched implementation) and calls fake.initialize(address(artifactsFactory), address(artHouse), 1, A, Traits(\"x\",\"PRISM\",9,\"DIAGONAL\"), address(0), bytes32(uint256(1)), \"\", false, bytes32(0)). Expected: revert (only ArtifactsFactory/ArtifactsSource should be able to initialise a piece). Actual: succeeds; fake.name() == \"ARTIFACTS #001\", fake.controller() == address(artifactsFactory), fake.ownerOf(1) == A, fake.royaltyInfo(1, 1 ether) == (artist payout, 0.075 ether) once the factory is registered as a module collection; artifactsFactory.isPiece(fake) == false and artifactsFactory.pieceContract(1) != fake.","severity":"low","snippet":"        if (controller != address(0)) revert AlreadyInitialized();","title":"ArtifactsPiece.initialize is open on any fresh clone, so anyone can mint counterfeit 'ARTIFACTS #NNN' contracts that report the real factory as controller"},{"citation":"resolved","description":"ArtHouse.setBrokerPass (line 207) can be called exactly once and never corrected. isEligibleBroker is reached from _credit (line 461) on every primary sale and mint and from recordResale (line 434). It calls balanceOf on the stored address with no try/catch and no code check, unlike ArtifactsPiece._isBroker, which wraps the same call. If the owner sets an EOA, a contract without balanceOf(address), or a contract that reverts, then every ArtHouse.mint, mintWithIMD, ArtifactsFactory.buy/buyMany/buyWithSeat and ArtifactsSource.settle whose broker argument is a nonzero address not in `brokers` reverts (empty return data fails abi decoding; a reverting callee bubbles), and every ArtifactsPiece.release with an eligible-looking broker falls into the piece's pull-payment fallback instead of the ledger. Buyers can work around it by passing broker = 0, which permanently disables the pass-holder broker programme that BrokerPass exists for, and THE SOURCE's settle() with a nonzero highBroker would revert until voidUnsettled after 7 days. Owner misconfiguration only, hence low; a minimal fix is a try/catch (as in ArtifactsPiece._isBroker) or a `pass.code.length > 0` check plus a probe `balanceOf(address(this))` call in setBrokerPass.","line":218,"path":"src/ArtHouse.sol","reproduction":"State: deployed and wired per launch.json notes, artist approved, ArtifactsFactory registered, locked, VRF configured, price 1 ether, sale open. Owner calls ArtHouse.setBrokerPass(0x000000000000000000000000000000000000dEaD) (an EOA) by mistake. Buyer B calls ArtifactsFactory.buy{value: 1 ether}(brokerAddr) with brokerAddr = any nonzero wallet not approved via setBroker. Expected: the purchase succeeds and, since brokerAddr holds no pass, its 15% goes to the buyback balance. Actual: the call reverts (abi decoding of empty return data from the EOA inside isEligibleBroker), and setBrokerPass(realPass) now reverts BrokerPassAlreadySet(). Likewise ArtifactsSource.settle() reverts for an auction whose winning bid named any nonzero unapproved broker.","severity":"low","snippet":"        return brokerPass != address(0) && IBalanceOf(brokerPass).balanceOf(broker) > 0;","title":"isEligibleBroker trusts brokerPass.balanceOf without try/catch while brokerPass is set once and irreversibly: a wrong address bricks every sale that names a broker"},{"citation":"resolved","description":"setMemberGate(member, call_, minimum) accepts any 4-byte selector; isMember then staticcalls `call_(account)` and treats the first 32 bytes of the return as the member's score. If the configured function returns a dynamic type (string, bytes, array), the first word is the ABI head offset 0x20 = 32, so any wallet scores 32 >= minimum and the holders-first window admits everyone (and a function returning a bool returns 1, admitting everyone when minimum is 1). Solidity ignores extra calldata, so even `name()` called with an appended address argument succeeds. The owner intends points(address) on EngageV2, so this is only a misconfiguration hazard, but the gate is frozen once the editions sale opens (setMemberGate reverts SaleIsOpen) and THE SOURCE's once a bid lands, so a wrong selector cannot be corrected after the fact. A minimal fix is to require `returndatasize() == 32` (not `>= 32`) in isMember, or to probe the selector in _setMemberGate and refuse one that returns anything but exactly one word for address(this).","line":69,"path":"src/base/HolderGate.sol","reproduction":"Inputs: owner calls artifactsFactory.setMemberGate(address(imd), bytes4(keccak256(\"name()\")), 1) (IMD is an ERC-20 with name() returning a string), setGate(seats, imd, 1e30, 1 days) so that only huge IMD holders or members may buy, then opens the sale. Wallet W with 0 IMD and no seat calls artifactsFactory.buy{value: price}(address(0)) during the first 24 hours. Expected: revert NotEligible(). Actual: isMember(W) returns true (the string return's first word is 0x20 = 32 >= 1) and the purchase succeeds, defeating the holders window; setMemberGate can no longer be changed because saleOpenedAt != 0.","severity":"low","snippet":"        return ok && n >= gateMemberMin;","title":"HolderGate.isMember reads only the first return word, so a member selector returning dynamic data admits every wallet"},{"citation":"resolved","description":"The ArtHouse constructor creates the ArtCollection implementation with `new`. It does not call any existing contract, so the protected floor's empty-chain constructor rehearsal passes, but the created contract is not one of the eight manifest entries: it is not covered by the runtime-size and forbidden-opcode scan (Contracts.protected.t.sol scans only the manifest addresses), has no predicted address in the launch, and is the DELEGATECALL target of every plain collection (see the proxy finding). Its runtime is ArtCollection's own (no DELEGATECALL/SELFDESTRUCT in source; the clone, not the implementation, carries 0xf4), and it is locked (house = itself), so nothing is exploitable; this is recorded so the adapter and the attestation step know the launch transaction produces nine contracts, and that ArtHouse's init code is larger than its runtime by ArtCollection's creation code.","line":169,"path":"src/ArtHouse.sol","reproduction":"State: launch.json deployed. ArtHouse.collectionImplementation() returns an address with code.length > 0 that is not any of the eight IMD_PROJECT_ADDRESS_i values and is not in launch.json. Expected per the manifest: exactly eight application contracts exist after the launch transaction. Actual: nine (plus ArtifactsPiece clones later).","severity":"info","snippet":"        collectionImplementation = address(new ArtCollection());","title":"ArtHouse's constructor deploys a ninth, unlisted contract (the ArtCollection implementation) outside the manifest"},{"citation":"resolved","description":"Not bypasses, and none touch holder balances or tokens already minted (no freeze, blacklist, seizure or post-launch mint beyond the fixed 255 + 1 + 100), but the adapter and the final panel should carry these as explicit trust assumptions: (1) ArtifactsFactory.setSaleOpen(false) and ArtHouse.setSaleOpen(collection,false) halt primary sales at will (endSale makes it permanent); (2) ArtHouse.setSplit (src/ArtHouse.sol:255) is read at sale time, so the curator can change how a pending bid or purchase is split up to the block it settles, including setting artistBps to 0 (README acknowledges this); (3) ArtHouse.setSaleModule(module,false) (line 201) makes recordResale revert for every existing piece of that module, diverting royalties and broker shares from the ledger into each piece's pendingWithdrawals (handled, but it changes where artists collect); (4) ArtHouse.revokeArtist ends the artist's curation rights but not their payout; (5) ArtifactsFactory.rerequestRandomness and claim may be called by the owner on a buyer's behalf; (6) ArtifactsFactory.postWrappedKey can push a key into any claimed piece whose key slot is empty (README/PROTOCOL disclose that curator-posted keys carry no fake-key proof). Two-step ownership with no renounce holds on every owned contract (TwoStepOwnable), the owner argument is $owner in each constructor, and BrokerPass, SubmissionReviews, KeyProof and ArtifactsPiece have no owner, as the brief requires.","line":203,"path":"src/ArtifactsFactory.sol","reproduction":"Example for (2): ArtifactsSource auction ends with highBid 10 ether; before anyone calls settle(), owner calls ArtHouse.setSplit(source, 1500, 8500, 0, 0). settle() then credits 8.5 ether (plus rounding) to balances[ArtHouse] and 0 to the artist. Expected by bidders: the 15/0/85 split advertised when they bid. Actual: whatever split is stored at settlement. Example for (1): ArtifactsFactory.setSaleOpen(false) after 100 editions sold -> buy reverts SaleClosed() until reopened; claims and VRF callbacks continue.","severity":"info","snippet":"    function setSaleOpen(bool open) external onlyOwner {","title":"Owner powers to document as trust assumptions: sale pausing, split changes at sale time, module and artist revocation"}],"hash":"c7c4864b3df4eecc4a92262df97ddaa325006fa4c678e6290e1ab128c2625adb","nodeId":"6e571ff7-e195-42d2-b857-9e6fdcb54b0e","outcome":"completed","summary":"Review complete. The findings file at the repository root holds 7 findings, all anchored to verified lines, with one Foundry proof.\n\n**Verdict.** No loss-of-funds, reentrancy, accounting or access-control defect reproduced in the contracts as they arrived. Nothing in `src/` needs to change for correctness. What I did find are conflicts with the launch recipe (proxies, post-deployment wiring) and three owner-misconfiguration hazards that one-shot setters make permanent. No source file was modified; my only writes are `.imd-findings.json` and the scratch test under `test/scratch/`, which is not kept.\n\n**Findings written**\n\n- **Medium, proxies.** Every plain collection and every ARTIFACTS edition is an EIP-1167 clone whose runtime byte 31 is DELEGATECALL (`src/libs/Clones.sol:11`). The protected opcode scan passes only because it inspects the eight launched runtimes, not what they create. Proof attached: two tests that run the floor's own scan over a created collection and a claimed edition, both failing now. The non-proxy alternative already exists in the repo (the byte copy used for THE SOURCE) at roughly 5M gas per claim. That is a scope decision for the requester.\n- **Medium, post-deployment wiring.** Seven owner calls are needed before anything works, four of them irreversible (`ArtStorage.setHouse`, `setBrokerPass`, `setBuybackBurner`, `setClaimsOpenAt`). The brief acknowledges this, so it is reported as the policy conflict the reference asks for, with the circular dependencies that make some of it hard to move into constructors spelled out.\n- **Low.** `ArtifactsPiece.initialize` is open on any fresh clone, so anyone can make a counterfeit \"ARTIFACTS #001\" reporting the real factory as controller. No fund path trusts it (the ledger checks `isPiece`, BrokerPass and SubmissionReviews resolve via the factory).\n- **Low.** `isEligibleBroker` calls `balanceOf` on the once-set pass address with no try/catch. A wrong address makes every sale naming an unapproved broker revert forever, including THE SOURCE's settle.\n- **Low.** `HolderGate.isMember` accepts any return of at least 32 bytes, so a selector returning a string admits every wallet into the holders window, and the gate is frozen once the sale opens.\n- **Info.** ArtHouse's constructor deploys a ninth unlisted contract; owner powers to carry as trust assumptions (sale pausing, split changes at settlement time, module revocation).\n\n**Checked and clean.** launch.json has exactly the three schema keys, 8 contracts in dependency order, argument counts matching each constructor, notes of 1,260 chars. The seats, IMD and member addresses all have code on mainnet (seats is an ERC-721 named \"identity.md\"). Two-step ownership with no renounce on every owned contract; $owner in each constructor; no SELFDESTRUCT or CALLCODE anywhere. All runtimes under EIP-170 (largest ArtifactsPiece, 236 bytes under). Self-brokering by pass holders is a documented perk, not a defect. Ledger conservation, escrow conservation, Fisher-Yates bounds, fallback-draw ordering and the VRF re-request path all traced correctly.\n\n**Coverage.** Read in full: all 10 contracts in `src/`, the 4 base contracts, 4 libraries, interfaces, launch.json, the deploy script wiring, README. KeyProof's curve arithmetic was read but not independently re-derived; I relied on the repo's audit tests for it. Tests run: sources compile in 38 s; my scratch proof; the repo's `test/audit` (6 pass) and `test/invariants` (4 pass). I did not re-run the full 215-test suite: compiling the whole test tree under via_ir exceeded 6 GB and 10 minutes on this machine, and the fork tests need an RPC. `ImdBuybackBurner` is outside this launch and was not reviewed.","treeHash":null,"usage":{"cachedInputTokens":2157988,"inputTokens":484,"model":"claude-fable-5-1","outputTokens":52137,"runtime":"claude","turns":38,"wallClockMs":1408002}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"5835e48821d8827d","findings":[{"citation":"resolved","description":"ArtifactsSource.setAuction only opens when house.canRecordSale(source) is true (ArtifactsSource.sol:153), and the comment promises 'so the winning bid can always settle'. But the module flag is re-read by the ledger at settlement: ArtHouse.recordSale (ArtHouse.sol:463) reverts NotSaleModule when saleModules[msg.sender] is false, and settle() calls it unconditionally at line 239. The owner-only ArtHouse.setSaleModule (ArtHouse.sol:203) has no guard against revoking a module whose auction holds live bids. Asymmetry: the open-time check (setAuction) and the settle-time check (recordSale) read the same slot but only the first is fenced by auction state. Effect: after a revocation nobody can settle; the winner's ETH stays locked until endTime + SETTLE_GRACE (7 days), then voidUnsettled refunds the bidder and the artist's sale is lost; the owner may then re-approve and re-open with a new reserve. No funds are lost and the actor is the trusted curator, so this is an owner power to document (README 'Trust assumptions' lists split changes and the resale effect of revocation, not this settlement block). If the design wants 'the winning bid can always settle' to hold, settle() could fall back to crediting through the piece's pull path, or setSaleModule(module,false) could refuse while that module reports a live auction; either changes agreed behaviour and is a scope decision for the author.","line":239,"path":"src/ArtifactsSource.sol","reproduction":"Deploy per launch.json; curator: approveArtist(artist), setSaleModule(source,true), registerModuleCollection(source,artist), storeRendererChunk, lock, setAuction(1 ether, now+1 day). alice: bid{2 ether}(0). curator: setSaleModule(source,false). warp past endTime. Expected (per setAuction comment): settle() succeeds, artist is paid, alice gets THE SOURCE. Actual: settle() reverts ArtHouse.NotSaleModule for every caller; voidUnsettled() reverts AuctionNotEnded until endTime+7 days; after that voidUnsettled() succeeds, refunds[alice]==2 ether, artist balance 0, no piece deployed. Confirmed with test/scratch/OwnerBlocksSettle.t.sol (test_ownerRevokesModuleAfterBid_settleBlocked_thenVoid passes on this tree, i.e. the blocked state is reachable).","severity":"low","snippet":"        house.recordSale{value: highBid}(address(this), highBidder, highBroker); // last: it pays the artist","title":"Owner can strand THE SOURCE auction after bids: settle() re-checks saleModules at settle time, so setSaleModule(source,false) blocks settlement for everyone and forces a void after 7 days (trust gap: "}],"hash":"cad2ba6d90260f84e01194fed90695363d61f576188b0b39c6d0cb7dda26ce73","nodeId":"0c51dd68-a98a-4992-83bb-9efc197c0707","outcome":"completed","summary":"Review complete. The findings file is written and validated, and every one of the 112 listed entry points has a coverage row.\n\n**Outcome.** No permission bypass, escalation path, broken initializer or asymmetric guard was found in the assigned area. The ownership model is sound: two-step everywhere, no renounce, implementations locked in their constructors, clones created and initialised atomically, callbacks bound to the coordinator and pool manager, and the owner can never reduce or redirect artist, broker or buyback balances. Self-brokering by pass holders is a documented perk, not a defect. The launch manifest matches every constructor in order and argument count. All 232 non-fork tests pass on this tree.\n\n**One finding, severity low.** THE SOURCE's settlement re-reads the sale-module flag at settle time, while only the opening check is fenced by auction state. The curator can call `setSaleModule(source,false)` after bids, which makes every call to settle revert, locks the winner's bid until the 7-day grace ends, and then forces a void so the artist's sale is lost. This is an owner power rather than a bypass, but it is not listed in the README's trust assumptions, and the comment on setAuction promises the winning bid can always settle. A scratch test under test/scratch/ reproduces the blocked state. Nothing was changed in the repository.\n\n**Coverage.** All Access Control, Trust Gap and Asymmetry checks were applied across every contract, including the escrow state machine, HolderGate, BrokerPass claims, VRF retry and fallback paths, and the buyback burner. Fork tests were not run. KeyProof's elliptic-curve arithmetic and the SVG and base64 encoders were read only for access relevance, not for mathematical correctness, which belongs to another specialist.","treeHash":null,"usage":{"cachedInputTokens":1178885,"inputTokens":290,"model":"claude-fable-5-1","outputTokens":48891,"runtime":"claude","turns":37,"wallClockMs":1287689}},{"artifacts":[],"attempt":1,"bundleHash":"daeb2571853a0b1c00295fb2df41631ca98892103e4723657e5eba74cf91b8eb","device":"2bb6789ad7b554e8","findings":[],"hash":"d9172b6c1162eb1017a6b7bd12855b7159297b2404ccc7e55dd9b31ee670ba33","nodeId":"729a3922-4e3a-4e5d-a11b-9e9bf354faae","outcome":"completed","summary":"Implemented fixes for NFT proxies, initialization access, BrokerPass failures, membership validation, and opcode-scan compatibility. Every change and audit disposition is documented in [ADAPTATION.md](/Users/heiry/.identitymd/work/ea8e8e20-b777-487b-82a0-b0be5eb702c7/729a3922-4e3a-4e5d-a11b-9e9bf354faae/ADAPTATION.md).\n\nValidation with the required seed:\n\n- `forge build`: passed.\n- `forge test`: 245 passed, zero failed.\n- Two fork suites skipped because `FORK_URL` was unset.\n\nFull-copy editions now cost approximately 4.9M gas for code deposit alone.","treeHash":"dd56d53d6daaeae0c768610f57e29ebd41022093","usage":{"cachedInputTokens":4218752,"inputTokens":131629,"model":"gpt-6-astra","outputTokens":38895,"runtime":"codex","turns":12,"wallClockMs":956436}}],"verification":[{"checks":[{"durationMs":534490,"exitCode":0,"name":"build","output":"Compiling 68 files with Solc 0.8.26\nSolc 0.8.26 finished in 534.31s\nCompiler run successful with warnings:\nWarning (5667): Unused function parameter. Remove or comment out the variable name to silence this warning.\n   --> test/invariants/ArtHouseInvariant.t.sol:105:9:\n    |\n105 |         address buyer,\n    |         ^^^^^^^^^^^^^\n\n","passed":true},{"durationMs":19521,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/fork/VrfFork.t.sol:VrfForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 8.97ms (0.00ns CPU time)\n\nRan 5 tests for test/audit/KeyProofEdges.t.sol:KeyProofEdgesTest\n[PASS] test_adversarialE_isProvable() (gas: 107849)\n[PASS] test_adversarialE_proofIsActuallyChecked() (gas: 23615)\n[PASS] test_negatedSCannotFrame() (gas: 60700)\n[PASS] test_oddYWrapThatOpensIsNotFake() (gas: 37558)\n[PASS] test_xEqualsN_isMalformed() (gas: 13218)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 14.11ms (22.72ms CPU time)\n\nRan 8 tests for test/KeyProof.t.sol:KeyProofTest\n[PASS] test_aJunkKeyIsProvenFake() (gas: 369871)\nLogs:\n  gas to check a fake-key proof: 44805\n\n[PASS] test_aKeyThatOpensIsNeverProvenFake() (gas: 368087)\n[PASS] test_aProofOnlyHoldsForItsBuyerPieceAndChain() (gas: 416867)\n[PASS] test_aProofOnlyHoldsForItsOwnWrappedKey() (gas: 416275)\n[PASS] test_aTamperedProofFails() (gas: 768976)\n[PASS] test_madeUpBytesAndTheOldFormatAreFake() (gas: 690806)\n[PASS] test_theRightKeyForSomeoneElseIsProvenFake() (gas: 368314)\n[PASS] test_viewingKeys() (gas: 34725)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 17.00ms (7.40ms CPU time)\n\nRan 1 test for test/fork/BurnerFork.t.sol:BurnerForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 288.68µs (0.00ns CPU time)\n\nRan 1 test for test/ClaimEnd.t.sol:EndBeforeOpenTest\n[PASS] test_endSale_beforeOpening_refused() (gas: 60691353)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 39.27ms (30.15ms CPU time)\n\nRan 5 tests for test/ClaimEnd.t.sol:ClaimEndTest\n[PASS] test_claimMany_claimsEveryOneInOneCall() (gas: 18151497)\n[PASS] test_claimMany_emptyRefused_andTheCuratorCanClaimForBuyers() (gas: 12311987)\n[PASS] test_claimMany_isAllOrNothing() (gas: 18205777)\n[PASS] test_endSale_isFinal() (gas: 6923933)\n[PASS] test_endSale_needsTheSaleToHaveOpened_andWorksWhileClosed() (gas: 96083)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 51.27ms (5.64ms CPU time)\n\nRan 1 test for test/audit/KeyReuseLeak.t.sol:KeyReuseLeakTest\n[PASS] test_copiedE_cantBePosted(uint256,uint256) (runs: 64, μ: 603054, ~: 603215)\nLogs:\n  Bound result 6677771717396745857438524715775791381032702405673290885595687978682\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 57.80ms (52.98ms CPU time)\n\nRan 4 tests for test/Phases.t.sol:PhasesTest\n[PASS] test_aSeatFollowsThePhases_whereverItGoes() (gas: 1747729)\n[PASS] test_afterTheWindow_anyoneUpToFive() (gas: 1042332)\n[PASS] test_capsRise_1_then_2_then_5_forAnImdHolder() (gas: 1740786)\n[PASS] test_setOnlyBeforeTheSaleOpens_andChecked() (gas: 322444)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 83.68ms (2.18ms CPU time)\n\nRan 7 tests for test/Burner.t.sol:BurnerTest\n[PASS] test_anyoneBurnsHeldImd() (gas: 169949)\n[PASS] test_anyoneSwapsInSmallStepsAfter60QuietDays() (gas: 845755)\n[PASS] test_constructorChecks() (gas: 8711)\n[PASS] test_editionSaleToBurnedImd() (gas: 61798551)\n[PASS] test_onlyTheCuratorSwaps_withAMinimumAndADeadline() (gas: 653639)\n[PASS] test_onlyThePoolManagerCallsBack() (gas: 32189)\n[PASS] test_theNewOwnerSwapsAfterAHandover() (gas: 304000)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 72.41ms (38.86ms CPU time)\n\nRan 4 tests for test/AuditRound3.t.sol:AuditRound3Test\n[PASS] test_aReturnDataBombCostsThePayerNothing() (gas: 694152)\n[PASS] test_aShareThatWaitsInTheLedgerIsAnnounced() (gas: 339919)\n[PASS] test_theArtistsPayoutCantMoveThePieceDuringARelease() (gas: 415877)\n[PASS] test_theArtistsPayoutCantRelistDuringARelease() (gas: 600564)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 82.65ms (1.19ms CPU time)\n\nRan 10 tests for test/Artifacts.t.sol:ArtifactsPieceEscrowTest\n[PASS] test_escrowCancelBeforeKey_andDelist() (gas: 501042)\n[PASS] test_escrowHappyPath_buyerConfirms() (gas: 1181854)\n[PASS] test_escrowKeyMustNotBeEmpty() (gas: 310921)\n[PASS] test_escrowTimeoutRelease() (gas: 728994)\n[PASS] test_pieceViewingKeyZeroRejected() (gas: 168689)\n[PASS] test_plainTransferClearsKey_previousOwnerRekeys() (gas: 506819)\n[PASS] test_reentrancyOnEscrowWithdrawBlocked() (gas: 844317)\n[PASS] test_rewrapIsOneShotAndNonEmpty() (gas: 284134)\n[PASS] test_sellerCannotOverwriteKeyAfterRelease() (gas: 913301)\n[PASS] test_sourceOnlyReveal() (gas: 35552)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 66.67ms (5.36ms CPU time)\n\nRan 18 tests for test/BrokerPass.t.sol:BrokerPassTest\n[PASS] test_capIs100() (gas: 19752778)\n[PASS] test_claimWithPiece_onceEverPerPiece() (gas: 6679912)\n[PASS] test_claimWithSeat_onceEverPerSeat() (gas: 376003)\n[PASS] test_claimWithTheSource() (gas: 6010301)\n[PASS] test_claimsWaitForTheStartTime_setOnceByTheCurator() (gas: 489742)\n[PASS] test_oneClaimPerWallet() (gas: 6980812)\n[PASS] test_passHolderCanBrokerTheirOwnBuy() (gas: 1019992)\n[PASS] test_passHolderEarnsOnMint_andTheRightMovesWithThePass() (gas: 2081372)\n[PASS] test_recordResaleRejectsAnythingButAPiece() (gas: 298286)\n[PASS] test_resaleBrokerShare_creditedInTheLedger() (gas: 7295006)\n[PASS] test_resaleBuyerWithAPassCanBrokerTheirOwnBuy() (gas: 7232310)\n[PASS] test_resaleFallsBackToThePieceWhenTheLedgerRefuses() (gas: 7247411)\n[PASS] test_resaleSellerCannotBeBroker() (gas: 7144850)\n[PASS] test_resaleWithoutEligibleBroker_sellerKeepsTheShare() (gas: 6934008)\n[PASS] test_setBrokerPassOnce() (gas: 64999)\n[PASS] test_sourceSplit_brokerAndArtistOnly() (gas: 6162142)\n[PASS] test_sourceSplit_noBrokerBurns() (gas: 5919583)\n[PASS] test_tokenURIIsOnChainJson() (gas: 388848)\nSuite result: ok. 18 passed; 0 failed; 0 skipped; finished in 59.37ms (24.19ms CPU time)\n\nRan 7 tests for test/Adversarial.t.sol:SourceEdgeTest\n[PASS] testFuzz_minimumRaiseIsCeilingOfFivePercent(uint96,uint96) (runs: 512, μ: 629587, ~: 629679)\nLogs:\n  Bound result 211984286375686451847427327\n  Bound result 222583501000000000222593605\n\n[PASS] testFuzz_rendererHashIsKeccakOfConcatenation(bytes,bytes,bytes) (runs: 64, μ: 419688, ~: 416599)\n[PASS] test_bidBoundaries() (gas: 901651)\n[PASS] test_payloadChunkLimits() (gas: 5443288)\n[PASS] test_setAuctionEdges() (gas: 459334)\n[PASS] test_settleEdges_brokerSplit() (gas: 6966012)\n[PASS] test_settleWithUnapprovedBrokerPaysTheBurn() (gas: 5869414)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 176.57ms (198.95ms CPU time)\n\nRan 6 tests for test/Adversarial.t.sol:PieceEdgeTest\n[PASS] test_cancelThenSecondBuyerAndRoyaltyToChangedPayout() (gas: 1087998)\n[PASS] test_listingEdges() (gas: 1002975)\n[PASS] test_releaseAtExactly72HoursByStranger() (gas: 914016)\n[PASS] test_revealNeedsTheSourceLocked_andEmptyRendererURI() (gas: 6265659)\n[PASS] test_safeTransferReceivers() (gas: 670237)\n[PASS] test_transferAuthEdges() (gas: 350213)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 204.35ms (25.38ms CPU time)\n\nRan 24 tests for test/NothingStuck.t.sol:NothingStuckTest\n[PASS] test_aBuyerNeedsAViewingKeyAProofCanUse() (gas: 67198049)\n[PASS] test_aJunkKeyIsProvenFake_paymentAndDepositToTheBuyer() (gas: 67782335)\n[PASS] test_aSilentSellerLetsTheBuyerCancelAfter24Hours() (gas: 67369506)\n[PASS] test_anAuctionClosedInTimeCannotBeVoided() (gas: 5846482)\n[PASS] test_anAuctionNobodyCanCloseGivesTheBidBack() (gas: 6134344)\n[PASS] test_callbackGasCanOnlyGoUpOnceTheSaleOpens() (gas: 60960821)\n[PASS] test_claimWithoutAKey_after30Days_thenTheKeyGoesIntoThePiece() (gas: 67149952)\n[PASS] test_curatorReKeysAPieceItsPreviousOwnerNeverDid() (gas: 67306108)\n[PASS] test_fallbackDraw_aStartedDrawsResultStands_finishedFromTheHistory() (gas: 61879528)\n[PASS] test_fallbackDraw_chainlinkStillWinsIfItAnswersFirst() (gas: 61646048)\n[PASS] test_fallbackDraw_countsFromThePurchase() (gas: 61768699)\n[PASS] test_fallbackDraw_oneAtATime() (gas: 62757333)\n[PASS] test_fallbackDraw_onlyAfterThreeDays_fromABlockNobodyKnew() (gas: 61803340)\n[PASS] test_fallbackDraw_startsAgainOnlyOnceItsHashIsGone() (gas: 61648636)\n[PASS] test_noProofBeforeAKey_andTheSellerCantDodgeOne() (gas: 67729653)\n[PASS] test_onlyAKeyTheSellerMadeCanBePosted() (gas: 67791236)\n[PASS] test_realKeys_aJunkKeyIsProvenFake() (gas: 907133)\nLogs:\n  gas for the buyer's proveFakeKey: 170130\n\n[PASS] test_realKeys_anHonestKeyCanNeverBeProvenFake() (gas: 1254953)\n[PASS] test_realKeys_theBuyerCantSwapViewingKeysToFrameTheSeller() (gas: 888070)\n[PASS] test_realKeys_theRightKeyWrappedToAnotherKeyIsFake() (gas: 894751)\n[PASS] test_the72HoursCountFromTheKey() (gas: 67790866)\n[PASS] test_theBuyerCantCancelUnderAPendingKey() (gas: 67565859)\n[PASS] test_theDepositIsExactly10Percent() (gas: 67670165)\n[PASS] test_theSellerCanRefundBeforeSendingAKey() (gas: 67476941)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 231.38ms (846.86ms CPU time)\n\nRan 3 tests for test/Adversarial.t.sol:RuntimeTest\n[PASS] test_implementationsAreLocked() (gas: 104926)\n[PASS] test_launchedRuntimesAreBoundedAndHaveNoEscapeOpcodes() (gas: 60540280)\n[PASS] test_noRenounceAnywhere() (gas: 155507)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 285.28ms (279.74ms CPU time)\n\nRan 2 tests for test/LaunchDeployment.t.sol:LaunchDeploymentTest\n[PASS] test_allEightConstructorsAcceptCodeLessDependencies() (gas: 75376878)\n[PASS] test_manifestOrderAndOwnerConfigurationRemainIntact() (gas: 82011018)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 331.69ms (550.57ms CPU time)\n\nRan 1 test for test/invariants/SourceAuctionInvariant.t.sol:SourceAuctionInvariantTest\n[PASS]\nSourceAuctionInvariantTest invariants:\n[PASS] invariant_auctionConservation\n[PASS] invariant_highBidMonotone\n[PASS] invariant_settlementIsFinal\n SourceAuctionInvariantTest invariants (runs: 96, calls: 5760, reverts: 0)\n\n╭----------------+--------------------+-------+---------+----------╮\n| Contract       | Selector           | Calls | Reverts | Discards |\n+==================================================================+\n| AuctionHandler | bid                | 851   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | payloadStaysLocked | 829   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | recordHigh         | 828   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | setAuction         | 794   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | settle             | 834   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | warp               | 852   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | withdrawRefund     | 772   | 0       | 0        |\n╰----------------+--------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 920\n  Bound result 2000000000000003632\n  Bound result 238\n  Bound result 4000000000000004685\n  Bound result 1697\n  Bound result 511\n  Bound result 6000000000000022905\n  Bound result 8000000000000000990\n  Bound result 1400\n  Bound result 600\n  Bound result 3493\n  Bound result 10000000000000000407\n  Bound result 10000000000818771063\n  Bound result 523\n  Bound result 97\n  Bound result 10000000000000000255\n  Bound result 606\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.85s (1.84s CPU time)\n\nRan 12 tests for test/Source.t.sol:ArtifactsSourceTest\n[PASS] testFuzz_revealOpensTheSealedSeed(bytes32,bytes32) (runs: 64, μ: 5893765, ~: 5893838)\n[PASS] test_auctionNeedsTheHouseToAcceptTheSale() (gas: 3285282)\n[PASS] test_auctionNeedsTheSourceLocked() (gas: 620659)\n[PASS] test_auctionReopensWhenNoBids() (gas: 441150)\n[PASS] test_auctionRules() (gas: 6733129)\n[PASS] test_bidReentrancyAndRefundPull() (gas: 767944)\n[PASS] test_deliverKeyOnceToTheWinner() (gas: 9241958)\n[PASS] test_noRevealWhileABuyerIsInEscrow() (gas: 9012360)\n[PASS] test_revealServesTheRendererWithItsSeed() (gas: 512490433)\nLogs:\n  revealed tokenURI gas: 2897251\n\n[PASS] test_revealTakesDownAListingWithNoBuyer() (gas: 8943770)\n[PASS] test_storedSeedIsSealed() (gas: 8734200)\n[PASS] test_tinyBidsMustStrictlyExceed() (gas: 940816)\nSuite result: ok. 12 passed; 0 failed; 0 skipped; finished in 1.96s (1.94s CPU time)\n\nRan 21 tests for test/ArtHouse.t.sol:ArtHouseTest\n[PASS] testFuzz_ethSplitInvariant(uint96,bool,bool) (runs: 64, μ: 1218376, ~: 1239979)\n[PASS] testFuzz_imdSplitInvariant(uint96,bool) (runs: 64, μ: 1311558, ~: 1314827)\n[PASS] test_artistPayoutOnlyArtist_keptOnReapproval() (gas: 179207)\n[PASS] test_collectionMintOnlyHouse() (gas: 73967)\n[PASS] test_curationFlow_andFailures() (gas: 938837)\n[PASS] test_customSplit() (gas: 1124713)\n[PASS] test_deploymentWiring() (gas: 93139)\n[PASS] test_imdBuybackIsReleasedAndBurned() (gas: 1882866)\n[PASS] test_mintFailures() (gas: 1550882)\n[PASS] test_onlyCuratorApproves() (gas: 123827)\n[PASS] test_pieceOver100KBRejected() (gas: 21310484)\n[PASS] test_recordSaleOnlyModules() (gas: 120446)\n[PASS] test_reentrancyOnWithdrawBlocked() (gas: 1838346)\n[PASS] test_revokedArtistLosesCuration() (gas: 582575)\n[PASS] test_sealNeedsEveryPieceFinalized() (gas: 527413)\n[PASS] test_setHouseOnce() (gas: 78294)\n[PASS] test_submissions() (gas: 260658)\n[PASS] test_tokenURIOnChain() (gas: 1190981)\n[PASS] test_twoStepOwnership_noRenounce() (gas: 198046)\n[PASS] test_withdrawNothingReverts_andHouseGoesToCurrentOwner() (gas: 1241987)\n[PASS] test_wrongHashIsCorrectable() (gas: 777075)\nSuite result: ok. 21 passed; 0 failed; 0 skipped; finished in 1.98s (114.80ms CPU time)\n\nRan 15 tests for test/LaunchAudit.t.sol:LaunchAuditTest\n[PASS] testFuzz_memberReplyMustBeExactlyOneWord(uint16,uint256,uint256) (runs: 64, μ: 432924, ~: 434817)\nLogs:\n  Bound result 300000\n\n[PASS] test_attackerCannotInitializeCollectionAsRealHouse() (gas: 1082634)\n[PASS] test_attackerCannotInitializePieceAsRealFactory() (gas: 5034126)\n[PASS] test_attackerCannotInitializePieceAsRealSource() (gas: 5024422)\n[PASS] test_brokenBrokerPassDoesNotBlockEditionPurchase() (gas: 61673474)\n[PASS] test_brokenBrokerPassDoesNotBlockSourceSettlement() (gas: 19657183)\n[PASS] test_brokenPassDoesNotBlockPlainMintsInEitherCurrency() (gas: 2535075)\n[PASS] test_brokerPassMalformedRepliesCountAsIneligible() (gas: 934454)\n[PASS] test_claimedEditionsAreIndependentRuntimesAndStorage() (gas: 104035491)\n[PASS] test_dynamicMemberReplyCannotBypassEditionWindow() (gas: 61590171)\n[PASS] test_dynamicMemberReplyCannotBypassSourceWindow() (gas: 676706)\n[PASS] test_initializerRejectsEOAController() (gas: 6086143)\n[PASS] test_keyPostEventUnchangedBeforeAndAfterClaim() (gas: 67263357)\n[PASS] test_ownerCanClosePrimarySaleAndChangePendingAuctionSplit() (gas: 73212183)\n[PASS] test_plainCollectionIsIndependentRuntime() (gas: 4127353)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 2.20s (656.87ms CPU time)\n\nRan 11 tests for test/Reviews.t.sol:ReviewsTest\n[PASS] testFuzz_tallyMatchesVoices(uint8[12]) (runs: 64, μ: 1441587, ~: 1442057)\n[PASS] test_aClaimedPieceIsAVoice_andAnUnclaimedOneIsNot() (gas: 67621657)\n[PASS] test_aMovedSeatStillHasOneVoice() (gas: 441792)\n[PASS] test_aSeatAndAPieceInOneWalletAreTwoVoices() (gas: 67346389)\n[PASS] test_anyoneAppliesToBeABroker() (gas: 224553)\n[PASS] test_anyonePublishesTheses() (gas: 810776)\n[PASS] test_changingAReviewMovesItsVote() (gas: 305393)\n[PASS] test_frozenOnceTheCuratorDecides_andAdvisoryOnly() (gas: 349039)\n[PASS] test_inputChecks() (gas: 307196)\n[PASS] test_onlyTheSeatHolderReviews() (gas: 97570)\n[PASS] test_seatsReview_andTheTallyFollows() (gas: 457095)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 2.38s (257.01ms CPU time)\n\nRan 16 tests for test/Artifacts.t.sol:ArtifactsFactoryTest\n[PASS] test_buyFailures() (gas: 60997224)\n[PASS] test_buyMany_cannotPassSupply() (gas: 98935498)\n[PASS] test_buyMany_fivePerWallet() (gas: 63854050)\n[PASS] test_buyRecordsSaleAndAssignsEveryEditionOnce() (gas: 177499320)\n[PASS] test_claimFlow_andFailures() (gas: 67455794)\n[PASS] test_postWrappedKeysInOneBatch() (gas: 67751346)\n[PASS] test_publishAndLock_accessAndFailures() (gas: 60947985)\n[PASS] test_rerequestAtOnceWhenTheCoordinatorAnsweredButTheCallbackFailed() (gas: 61872452)\n[PASS] test_rerequestRandomnessAfterDroppedRequest() (gas: 62028891)\n[PASS] test_saleControl() (gas: 61043179)\n[PASS] test_sealTokenURIMatchesR8Frame() (gas: 970411811)\n[PASS] test_viewingKeyZeroRejected() (gas: 33301)\n[PASS] test_vrfCallbackCannotBeReplayed() (gas: 61623145)\n[PASS] test_vrfCallbackGasIsTheCuratorsToTune() (gas: 61431482)\n[PASS] test_vrfCorrectableUntilTheSaleOpens_thenLockedForever() (gas: 62246539)\n[PASS] test_vrfMustBeConfiguredBeforeSelling() (gas: 46850)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 3.04s (3.92s CPU time)\n\nRan 1 test for test/invariants/ArtifactsFactoryInvariant.t.sol:ArtifactsFactoryInvariantTest\n[PASS]\nArtifactsFactoryInvariantTest invariants:\n[PASS] invariant_claimedPiecesBelongToBuyers\n[PASS] invariant_counts\n[PASS] invariant_ledgerHoldsEveryPurchase\n[PASS] invariant_lockedAndPriced\n[PASS] invariant_walletLimit\n ArtifactsFactoryInvariantTest invariants (runs: 96, calls: 5760, reverts: 0)\n\n╭----------------+-------------------+-------+---------+----------╮\n| Contract       | Selector          | Calls | Reverts | Discards |\n+=================================================================+\n| FactoryHandler | buy               | 534   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | buyMany           | 495   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | claim             | 552   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | fulfil            | 497   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | lockedForever     | 508   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | replay            | 536   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | rerequest         | 507   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | setPrice          | 494   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | strangerFulfil    | 564   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | strangerRerequest | 534   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | toggleSale        | 539   | 0       | 0        |\n╰----------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 10008\n  Bound result 51638143296626\n  Bound result 0\n  Bound result 2574237282764180103\n  Bound result 4264337593543950335\n  Bound result 3\n  Bound result 5\n  Bound result 3\n  Bound result 1\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.15s (3.08s CPU time)\n\nRan 1 test for test/invariants/PieceEscrowInvariant.t.sol:PieceEscrowInvariantTest\n[PASS]\nPieceEscrowInvariantTest invariants:\n[PASS] invariant_escrowConservation\n[PASS] invariant_escrowSellerOwns\n[PASS] invariant_royaltyAndIdentity\n[PASS] invariant_singleToken\n PieceEscrowInvariantTest invariants (runs: 96, calls: 5760, reverts: 0)\n\n╭---------------+--------------------+-------+---------+----------╮\n| Contract      | Selector           | Calls | Reverts | Discards |\n+=================================================================+\n| EscrowHandler | approveAndTransfer | 387   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | buy                | 370   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | cancel             | 387   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | delist             | 402   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | list               | 390   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | postKey            | 413   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | proveFake          | 367   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | refundBuyer        | 354   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | registerKey        | 387   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | release            | 391   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | rewrap             | 402   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | transfer           | 407   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | warp               | 366   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | withdraw           | 355   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | withdrawRoyalty    | 382   | 0       | 0        |\n╰---------------+--------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 16105\n  Bound result 1500000000000000000\n  Bound result 4274151582\n  Bound result 20337108042\n  Bound result 111059\n  Bound result 34646\n  Bound result 4070\n  Bound result 1000000000000000000\n  Bound result 544000\n  Bound result 20880797823880349362\n  Bound result 259200\n  Bound result 104089\n  Bound result 544000\n  Bound result 47915958131739435367\n  Bound result 10000\n  Bound result 285478\n  Bound result 149144\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.35s (3.10s CPU time)\n\nRan 1 test for test/invariants/ArtHouseInvariant.t.sol:ArtHouseInvariantTest\n[PASS]\nArtHouseInvariantTest invariants:\n[PASS] invariant_constants\n[PASS] invariant_ethConservation\n[PASS] invariant_imdConservation\n[PASS] invariant_noOverWithdrawal\n[PASS] invariant_supplyAndSeal\n ArtHouseInvariantTest invariants (runs: 128, calls: 5120, reverts: 0)\n\n╭---------------+----------------+-------+---------+----------╮\n| Contract      | Selector       | Calls | Reverts | Discards |\n+=============================================================+\n| LedgerHandler | handOver       | 380   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | mintETH        | 369   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | mintIMD        | 414   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | moduleSale     | 377   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | releaseBuyback | 413   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setBroker      | 396   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setPayout      | 404   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setPrices      | 429   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setSaleOpen    | 378   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setSplit       | 413   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | strangerCalls  | 361   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | withdraw       | 377   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | withdrawHouse  | 409   | 0       | 0        |\n╰---------------+----------------+-------+---------+----------╯\n\nLogs:\n  Bound result 18882627285399\n  Bound result 685\n  Bound result 9797\n  Bound result 61765395460014508990\n  Bound result 9999\n  Bound result 1\n  Bound result 0\n  Bound result 1073\n  Bound result 5568\n  Bound result 4262\n  Bound result 93\n  Bound result 1500000000000000000\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 6.61s (6.59s CPU time)\n\nRan 12 tests for test/Gate.t.sol:GateTest\n[PASS] test_aHostileMembershipContractCountsAsNotMember() (gas: 62498580)\n[PASS] test_auction_gateFixedFromTheFirstBid() (gas: 714486)\n[PASS] test_auction_holdersFirstThenAnyone() (gas: 948357)\n[PASS] test_auction_membersBid_andTheMemberGateIsFixedFromTheFirstBid() (gas: 1006759)\n[PASS] test_brokenSeatContractCountsAsNotHeld() (gas: 61030533)\n[PASS] test_editions_gateFixedOnceTheSaleOpens() (gas: 61529270)\n[PASS] test_editions_holdersFirstThenAnyone() (gas: 62031024)\n[PASS] test_editions_membersBuyInTheWindow_asTokenHoldersDo() (gas: 62059284)\n[PASS] test_editions_noGateMeansOpen() (gas: 61274007)\n[PASS] test_editions_seatBuysUpToFivePerSeatWhereverItGoes() (gas: 62695849)\n[PASS] test_gateRules() (gas: 239527)\n[PASS] test_memberGateRules() (gas: 61261926)\nSuite result: ok. 12 passed; 0 failed; 0 skipped; finished in 19.32s (407.69ms CPU time)\n\nRan 23 tests for test/Adversarial.t.sol:ArtHouseEdgeTest\n[PASS] testFuzz_everyoneWithdrawsExactlyTheirShare(uint96,uint96,uint96) (runs: 256, μ: 2048171, ~: 2051364)\nLogs:\n  Bound result 1687053956312409914\n  Bound result 29410530796336771647\n  Bound result 1215619572\n\n[PASS] testFuzz_splitConservesAndHouseTakesRounding(uint16,uint16,uint16,uint96,uint8) (runs: 512, μ: 261218, ~: 262826)\nLogs:\n  Bound result 1500\n  Bound result 26\n  Bound result 3000\n  Bound result 12054\n\n[PASS] test_artistEdges() (gas: 1210240)\n[PASS] test_buybackOnlyToTheBurnerSetOnce() (gas: 460935)\n[PASS] test_clearThenReuploadKeepsSizeAccounting() (gas: 40763894)\n[PASS] test_collectionErc721Edges() (gas: 1436052)\n[PASS] test_constructorsDoNotCallDependencies() (gas: 36654)\n[PASS] test_constructorsRejectZeroDependencies() (gas: 4550)\n[PASS] test_curationEdges() (gas: 780836)\n[PASS] test_defaultSplit_agentHouseBurn() (gas: 381579)\n[PASS] test_mintWithIMD_falseReturnRejected() (gas: 2073855)\n[PASS] test_mintWithIMD_feeOnTransferRejected() (gas: 2297085)\n[PASS] test_mintWithIMD_stalePriceRejected() (gas: 1250853)\n[PASS] test_mintZeroPricesReject() (gas: 943137)\n[PASS] test_moduleCollectionsHaveNoPlainCuration() (gas: 376256)\n[PASS] test_pendingOwnerHasNoPowerBeforeAccepting() (gas: 197527)\n[PASS] test_registerModuleCollectionTwiceReverts() (gas: 44789)\n[PASS] test_revokedBrokerKeepsEarnedBalance_butEarnsNoMore() (gas: 1291624)\n[PASS] test_sealEmptyCollectionRevertsAndSealIsOnce() (gas: 657864)\n[PASS] test_splitExtremes() (gas: 1284500)\n[PASS] test_submissionEdges() (gas: 246348)\n[PASS] test_updatePieceAccessEdges() (gas: 1976561)\n[PASS] test_withdrawToRevertingPayoutKeepsBalance() (gas: 1372032)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 19.32s (19.60s CPU time)\n\nRan 13 tests for test/Adversarial.t.sol:ArtifactsEdgeTest\n[PASS] testFuzz_anyWordsAssignDistinctEditions(uint256[8]) (runs: 256, μ: 64647046, ~: 64649037)\n[PASS] testFuzz_sealFramesAnyTraits(uint8,uint8,uint8,uint8,uint8) (runs: 16, μ: 519807520, ~: 519807826)\nLogs:\n  Bound result 7\n\n[PASS] test_buyRevertsAtomicallyWhenCoordinatorReverts() (gas: 59197366)\n[PASS] test_callbackWithNoWordsReverts() (gas: 61547541)\n[PASS] test_claimedPieceIsAFullCopyOfTheImplementation() (gas: 67247088)\n[PASS] test_configureVRFRejectsZeroes() (gas: 211437)\n[PASS] test_duplicateRequestIdRejected() (gas: 59391685)\n[PASS] test_nonOwnerCannotRunTheSale() (gas: 60818098)\n[PASS] test_rerequestIsAtomicWhenCoordinatorReverts() (gas: 59883161)\n[PASS] test_rerequestWindowBoundaryAndChaining() (gas: 67816052)\n[PASS] test_setPieceEdges() (gas: 61051490)\n[PASS] test_unapprovedBuyerAsBrokerEarnsNothing_andOneWeiPriceWorks() (gas: 61487275)\n[PASS] test_wrappedKeyEdges() (gas: 67229754)\nSuite result: ok. 13 passed; 0 failed; 0 skipped; finished in 19.32s (21.92s CPU time)\n\nRan 29 test suites in 19.33s (86.27s CPU time): 232 tests passed, 0 failed, 2 skipped (234 total tests)\n","passed":true},{"durationMs":194,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"ArtCollection.approve(address,uint256)\",\"ArtCollection.initialize(address,string,string)\",\"ArtCollection.mint(address,uint256)\",\"ArtCollection.safeTransferFrom(address,address,uint256)\",\"ArtCollection.safeTransferFrom(address,address,uint256,bytes)\",\"ArtCollection.setApprovalForAll(address,bool)\",\"ArtCollection.transferFrom(address,address,uint256)\",\"ArtHouse.acceptOwnership()\",\"ArtHouse.approveArtist(address,string)\",\"ArtHouse.clearPiece(address,uint256)\",\"ArtHouse.createCollection(string,string,address)\",\"ArtHouse.decideSubmission(uint256,bool)\",\"ArtHouse.finalizePiece(address,uint256)\",\"ArtHouse.mint(address,uint256,address)\",\"ArtHouse.mintWithIMD(address,uint256,address,uint256)\",\"ArtHouse.recordResale(address,uint256,uint256)\",\"ArtHouse.recordSale(address,address,address)\",\"ArtHouse.registerModuleCollection(address,address)\",\"ArtHouse.registerPiece(address,uint256,bytes32,string,string)\",\"ArtHouse.releaseBuyback(address)\",\"ArtHouse.revokeArtist(address)\",\"ArtHouse.sealCollection(address)\",\"ArtHouse.setBroker(address,bool)\",\"ArtHouse.setBrokerPass(address)\",\"ArtHouse.setBuybackBurner(address)\",\"ArtHouse.setPayout(address)\",\"ArtHouse.setPrices(address,uint256,uint256)\",\"ArtHouse.setSaleModule(address,bool)\",\"ArtHouse.setSaleOpen(address,bool)\",\"ArtHouse.setSplit(address,uint16,uint16,uint16,uint16)\",\"ArtHouse.submit(bytes32,string)\",\"ArtHouse.transferOwnership(address)\",\"ArtHouse.updatePiece(address,uint256,bytes32,string,string)\",\"ArtHouse.uploadChunk(address,uint256,uint256,bytes)\",\"ArtHouse.withdraw(address)\",\"ArtHouse.withdrawHouse(address)\",\"ArtStorage.acceptOwnership()\",\"ArtStorage.clear(address,uint256)\",\"ArtStorage.setHouse(address)\",\"ArtStorage.transferOwnership(address)\",\"ArtStorage.write(address,uint256,uint256,bytes)\",\"ArtifactsFactory.acceptOwnership()\",\"ArtifactsFactory.buy(address)\",\"ArtifactsFactory.buyMany(uint256,address)\",\"ArtifactsFactory.buyWithSeat(uint256,uint256,address)\",\"ArtifactsFactory.claim(uint256)\",\"ArtifactsFactory.claimMany(uint256[])\",\"ArtifactsFactory.configureVRF(address,bytes32,uint256,bool)\",\"ArtifactsFactory.endSale()\",\"ArtifactsFactory.finishFallbackDraw(uint256)\",\"ArtifactsFactory.lock()\",\"ArtifactsFactory.postWrappedKey(uint256,bytes)\",\"ArtifactsFactory.postWrappedKeys(uint256[],bytes[])\",\"ArtifactsFactory.rawFulfillRandomWords(uint256,uint256[])\",\"ArtifactsFactory.registerViewingKey(bytes32)\",\"ArtifactsFactory.rerequestRandomness(uint256)\",\"ArtifactsFactory.setGate(address,address,uint256,uint64)\",\"ArtifactsFactory.setMemberGate(address,bytes4,uint256)\",\"ArtifactsFactory.setMintPhases(uint64,uint8,uint64,uint8)\",\"ArtifactsFactory.setPiece(uint256,(string,string,uint8,string),bytes,bytes32)\",\"ArtifactsFactory.setPrice(uint256)\",\"ArtifactsFactory.setSaleOpen(bool)\",\"ArtifactsFactory.setVRFCallbackGas(uint32)\",\"ArtifactsFactory.startFallbackDraw(uint256)\",\"ArtifactsFactory.transferOwnership(address)\",\"ArtifactsPiece.approve(address,uint256)\",\"ArtifactsPiece.buy(bytes32,address)\",\"ArtifactsPiece.cancel()\",\"ArtifactsPiece.delist()\",\"ArtifactsPiece.initialize(address,address,uint256,address,(string,string,uint8,string),address,bytes32,bytes,bool,bytes32)\",\"ArtifactsPiece.list(uint256)\",\"ArtifactsPiece.postEscrowKey(bytes,address,uint256)\",\"ArtifactsPiece.proveFakeKey((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256))\",\"ArtifactsPiece.refundBuyer()\",\"ArtifactsPiece.registerViewingKey(bytes32)\",\"ArtifactsPiece.release()\",\"ArtifactsPiece.reveal(bytes32)\",\"ArtifactsPiece.rewrapFor(bytes)\",\"ArtifactsPiece.safeTransferFrom(address,address,uint256)\",\"ArtifactsPiece.safeTransferFrom(address,address,uint256,bytes)\",\"ArtifactsPiece.setApprovalForAll(address,bool)\",\"ArtifactsPiece.transferFrom(address,address,uint256)\",\"ArtifactsPiece.withdraw()\",\"ArtifactsSource.acceptOwnership()\",\"ArtifactsSource.bid(address)\",\"ArtifactsSource.deliverKey(bytes)\",\"ArtifactsSource.lock(bytes32,bytes32)\",\"ArtifactsSource.resetRenderer()\",\"ArtifactsSource.setAuction(uint256,uint64)\",\"ArtifactsSource.setGate(address,address,uint256,uint64)\",\"ArtifactsSource.setMemberGate(address,bytes4,uint256)\",\"ArtifactsSource.settle()\",\"ArtifactsSource.storeRendererChunk(bytes)\",\"ArtifactsSource.transferOwnership(address)\",\"ArtifactsSource.voidUnsettled()\",\"ArtifactsSource.withdrawRefund()\",\"BrokerPass.approve(address,uint256)\",\"BrokerPass.claimWithPiece(uint256)\",\"BrokerPass.claimWithSeat(uint256)\",\"BrokerPass.safeTransferFrom(address,address,uint256)\",\"BrokerPass.safeTransferFrom(address,address,uint256,bytes)\",\"BrokerPass.setApprovalForAll(address,bool)\",\"BrokerPass.setClaimsOpenAt(uint64)\",\"BrokerPass.transferFrom(address,address,uint256)\",\"ImdBuybackBurner.burnEth(uint256,uint256,uint256)\",\"ImdBuybackBurner.burnImd()\",\"ImdBuybackBurner.receive()\",\"ImdBuybackBurner.unlockCallback(bytes)\",\"SubmissionReviews.applyAsBroker(string)\",\"SubmissionReviews.postThesis(uint256,string)\",\"SubmissionReviews.reviewAsPiece(uint256,uint256,uint8,string)\",\"SubmissionReviews.reviewAsSeat(uint256,uint256,uint8,string)\"],\"files\":{\".gitignore\":3,\"ADAPTATION.md\":248,\"README.md\":261,\"foundry.toml\":25,\"launch.burner.json\":17,\"launch.json\":63,\"reference/PROTOCOL.md\":99,\"reference/RULES.md\":137,\"reference/audit/V13Audit.t.sol.txt\":381,\"reference/check-framed.js\":25,\"reference/framed/framed-003.svg\":1,\"reference/framed/framed-MASTER.svg\":1,\"reference/rules.js\":145,\"reference/the-source.renderer.html\":148,\"remappings.txt\":1,\"script/Deploy.s.sol\":39,\"src/ArtCollection.sol\":55,\"src/ArtHouse.sol\":609,\"src/ArtStorage.sol\":82,\"src/ArtifactsFactory.sol\":622,\"src/ArtifactsPiece.sol\":457,\"src/ArtifactsSource.sol\":271,\"src/BrokerPass.sol\":142,\"src/ImdBuybackBurner.sol\":163,\"src/KeyProof.sol\":154,\"src/SubmissionReviews.sol\":215,\"src/base/ERC721Lite.sol\":122,\"src/base/HolderGate.sol\":109,\"src/base/ReentrancyGuard.sol\":15,\"src/base/TwoStepOwnable.sol\":40,\"src/interfaces/Interfaces.sol\":93,\"src/libs/Clones.sol\":19,\"src/libs/Encoding.sol\":79,\"src/libs/SSTORE2.sol\":41,\"src/libs/Seal.sol\":102,\"test/Adversarial.t.sol\":1409,\"test/ArtHouse.t.sol\":463,\"test/Artifacts.t.sol\":673,\"test/AuditRound3.t.sol\":151,\"test/BrokerPass.t.sol\":373,\"test/Burner.t.sol\":161,\"test/ClaimEnd.t.sol\":152,\"test/Fixture.sol\":230,\"test/Gate.t.sol\":295,\"test/KeyProof.t.sol\":134,\"test/LaunchAudit.t.sol\":338,\"test/LaunchDeployment.t.sol\":191,\"test/NothingStuck.t.sol\":568,\"test/Phases.t.sol\":130,\"test/Reviews.t.sol\":264,\"test/Source.t.sol\":396,\"test/audit/KeyProofEdges.t.sol\":178,\"test/audit/KeyReuseLeak.t.sol\":38,\"test/fixtures/keyproof.json\":81,\"test/fork/BurnerFork.t.sol\":70,\"test/fork/VrfFork.t.sol\":131,\"test/invariants/ArtHouseInvariant.t.sol\":444,\"test/invariants/ArtifactsFactoryInvariant.t.sol\":323,\"test/invariants/PieceEscrowInvariant.t.sol\":445,\"test/invariants/SourceAuctionInvariant.t.sol\":227,\"test/mocks/AdversarialMocks.sol\":134,\"test/mocks/MockPoolManager.sol\":57,\"test/mocks/MockSeats.sol\":27,\"test/mocks/Mocks.sol\":149,\"test/mocks/TestVRFCoordinator.sol\":46,\"test/utils/Base64Decode.sol\":83},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"02fe3d3189147116ffdab68da766f6758aa4de0a97b90783a057ff41747f8689","verifiedTreeHash":"67772cd367099ff693cfbbd04f4af48fdbd0b809","verifierVersion":"0.1.0+745c1db4"},{"checks":[{"durationMs":323563,"exitCode":0,"name":"build","output":"Compiling 69 files with Solc 0.8.26\nSolc 0.8.26 finished in 323.46s\nCompiler run successful with warnings:\nWarning (5667): Unused function parameter. Remove or comment out the variable name to silence this warning.\n   --> test/invariants/ArtHouseInvariant.t.sol:105:9:\n    |\n105 |         address buyer,\n    |         ^^^^^^^^^^^^^\n\n","passed":true},{"durationMs":10124,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 8 tests for test/KeyProof.t.sol:KeyProofTest\n[PASS] test_aJunkKeyIsProvenFake() (gas: 369871)\nLogs:\n  gas to check a fake-key proof: 44805\n\n[PASS] test_aKeyThatOpensIsNeverProvenFake() (gas: 368087)\n[PASS] test_aProofOnlyHoldsForItsBuyerPieceAndChain() (gas: 416867)\n[PASS] test_aProofOnlyHoldsForItsOwnWrappedKey() (gas: 416275)\n[PASS] test_aTamperedProofFails() (gas: 768976)\n[PASS] test_madeUpBytesAndTheOldFormatAreFake() (gas: 690806)\n[PASS] test_theRightKeyForSomeoneElseIsProvenFake() (gas: 368314)\n[PASS] test_viewingKeys() (gas: 34725)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 1.85ms (4.70ms CPU time)\n\nRan 5 tests for test/audit/KeyProofEdges.t.sol:KeyProofEdgesTest\n[PASS] test_adversarialE_isProvable() (gas: 107849)\n[PASS] test_adversarialE_proofIsActuallyChecked() (gas: 23615)\n[PASS] test_negatedSCannotFrame() (gas: 60700)\n[PASS] test_oddYWrapThatOpensIsNotFake() (gas: 37558)\n[PASS] test_xEqualsN_isMalformed() (gas: 13218)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 1.87ms (3.77ms CPU time)\n\nRan 1 test for test/fork/BurnerFork.t.sol:BurnerForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 214.83µs (0.00ns CPU time)\n\nRan 1 test for test/ClaimEnd.t.sol:EndBeforeOpenTest\n[PASS] test_endSale_beforeOpening_refused() (gas: 60691353)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 16.46ms (14.08ms CPU time)\n\nRan 7 tests for test/Burner.t.sol:BurnerTest\n[PASS] test_anyoneBurnsHeldImd() (gas: 169949)\n[PASS] test_anyoneSwapsInSmallStepsAfter60QuietDays() (gas: 845755)\n[PASS] test_constructorChecks() (gas: 8711)\n[PASS] test_editionSaleToBurnedImd() (gas: 61800771)\n[PASS] test_onlyTheCuratorSwaps_withAMinimumAndADeadline() (gas: 653639)\n[PASS] test_onlyThePoolManagerCallsBack() (gas: 32189)\n[PASS] test_theNewOwnerSwapsAfterAHandover() (gas: 304000)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 19.46ms (17.29ms CPU time)\n\nRan 6 tests for test/Adversarial.t.sol:PieceEdgeTest\n[PASS] test_cancelThenSecondBuyerAndRoyaltyToChangedPayout() (gas: 1087998)\n[PASS] test_listingEdges() (gas: 1002975)\n[PASS] test_releaseAtExactly72HoursByStranger() (gas: 914016)\n[PASS] test_revealNeedsTheSourceLocked_andEmptyRendererURI() (gas: 6265659)\n[PASS] test_safeTransferReceivers() (gas: 670237)\n[PASS] test_transferAuthEdges() (gas: 350213)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 23.76ms (3.59ms CPU time)\n\nRan 4 tests for test/Phases.t.sol:PhasesTest\n[PASS] test_aSeatFollowsThePhases_whereverItGoes() (gas: 1747601)\n[PASS] test_afterTheWindow_anyoneUpToFive() (gas: 1042332)\n[PASS] test_capsRise_1_then_2_then_5_forAnImdHolder() (gas: 1740916)\n[PASS] test_setOnlyBeforeTheSaleOpens_andChecked() (gas: 322444)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 28.50ms (1.36ms CPU time)\n\nRan 5 tests for test/ClaimEnd.t.sol:ClaimEndTest\n[PASS] test_claimMany_claimsEveryOneInOneCall() (gas: 18158157)\n[PASS] test_claimMany_emptyRefused_andTheCuratorCanClaimForBuyers() (gas: 12316427)\n[PASS] test_claimMany_isAllOrNothing() (gas: 18212437)\n[PASS] test_endSale_isFinal() (gas: 6928373)\n[PASS] test_endSale_needsTheSaleToHaveOpened_andWorksWhileClosed() (gas: 96083)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 29.02ms (3.76ms CPU time)\n\nRan 4 tests for test/AuditRound3.t.sol:AuditRound3Test\n[PASS] test_aReturnDataBombCostsThePayerNothing() (gas: 694152)\n[PASS] test_aShareThatWaitsInTheLedgerIsAnnounced() (gas: 339919)\n[PASS] test_theArtistsPayoutCantMoveThePieceDuringARelease() (gas: 415877)\n[PASS] test_theArtistsPayoutCantRelistDuringARelease() (gas: 600564)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 26.73ms (1.01ms CPU time)\n\nRan 1 test for test/fork/VrfFork.t.sol:VrfForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 840.19µs (0.00ns CPU time)\n\nRan 10 tests for test/Artifacts.t.sol:ArtifactsPieceEscrowTest\n[PASS] test_escrowCancelBeforeKey_andDelist() (gas: 501042)\n[PASS] test_escrowHappyPath_buyerConfirms() (gas: 1181854)\n[PASS] test_escrowKeyMustNotBeEmpty() (gas: 310921)\n[PASS] test_escrowTimeoutRelease() (gas: 728994)\n[PASS] test_pieceViewingKeyZeroRejected() (gas: 168689)\n[PASS] test_plainTransferClearsKey_previousOwnerRekeys() (gas: 506819)\n[PASS] test_reentrancyOnEscrowWithdrawBlocked() (gas: 844317)\n[PASS] test_rewrapIsOneShotAndNonEmpty() (gas: 284134)\n[PASS] test_sellerCannotOverwriteKeyAfterRelease() (gas: 913301)\n[PASS] test_sourceOnlyReveal() (gas: 35552)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 33.05ms (3.89ms CPU time)\n\nRan 1 test for test/audit/KeyReuseLeak.t.sol:KeyReuseLeakTest\n[PASS] test_copiedE_cantBePosted(uint256,uint256) (runs: 64, μ: 603053, ~: 603233)\nLogs:\n  Bound result 6677771717396745857438524715775791381032702405673290885595687978682\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 36.82ms (33.33ms CPU time)\n\nRan 18 tests for test/BrokerPass.t.sol:BrokerPassTest\n[PASS] test_capIs100() (gas: 19752778)\n[PASS] test_claimWithPiece_onceEverPerPiece() (gas: 6682132)\n[PASS] test_claimWithSeat_onceEverPerSeat() (gas: 376003)\n[PASS] test_claimWithTheSource() (gas: 6010301)\n[PASS] test_claimsWaitForTheStartTime_setOnceByTheCurator() (gas: 489742)\n[PASS] test_oneClaimPerWallet() (gas: 6983032)\n[PASS] test_passHolderCanBrokerTheirOwnBuy() (gas: 1022212)\n[PASS] test_passHolderEarnsOnMint_andTheRightMovesWithThePass() (gas: 2088032)\n[PASS] test_recordResaleRejectsAnythingButAPiece() (gas: 298286)\n[PASS] test_resaleBrokerShare_creditedInTheLedger() (gas: 7297226)\n[PASS] test_resaleBuyerWithAPassCanBrokerTheirOwnBuy() (gas: 7234530)\n[PASS] test_resaleFallsBackToThePieceWhenTheLedgerRefuses() (gas: 7249631)\n[PASS] test_resaleSellerCannotBeBroker() (gas: 7147070)\n[PASS] test_resaleWithoutEligibleBroker_sellerKeepsTheShare() (gas: 6936228)\n[PASS] test_setBrokerPassOnce() (gas: 64999)\n[PASS] test_sourceSplit_brokerAndArtistOnly() (gas: 6162142)\n[PASS] test_sourceSplit_noBrokerBurns() (gas: 5919583)\n[PASS] test_tokenURIIsOnChainJson() (gas: 388848)\nSuite result: ok. 18 passed; 0 failed; 0 skipped; finished in 64.21ms (16.85ms CPU time)\n\nRan 21 tests for test/ArtHouse.t.sol:ArtHouseTest\n[PASS] testFuzz_ethSplitInvariant(uint96,bool,bool) (runs: 64, μ: 1218374, ~: 1239979)\n[PASS] testFuzz_imdSplitInvariant(uint96,bool) (runs: 64, μ: 1311545, ~: 1314827)\n[PASS] test_artistPayoutOnlyArtist_keptOnReapproval() (gas: 179207)\n[PASS] test_collectionMintOnlyHouse() (gas: 73967)\n[PASS] test_curationFlow_andFailures() (gas: 938837)\n[PASS] test_customSplit() (gas: 1124713)\n[PASS] test_deploymentWiring() (gas: 93139)\n[PASS] test_imdBuybackIsReleasedAndBurned() (gas: 1882866)\n[PASS] test_mintFailures() (gas: 1550882)\n[PASS] test_onlyCuratorApproves() (gas: 123827)\n[PASS] test_pieceOver100KBRejected() (gas: 21310484)\n[PASS] test_recordSaleOnlyModules() (gas: 120446)\n[PASS] test_reentrancyOnWithdrawBlocked() (gas: 1838346)\n[PASS] test_revokedArtistLosesCuration() (gas: 582575)\n[PASS] test_sealNeedsEveryPieceFinalized() (gas: 527413)\n[PASS] test_setHouseOnce() (gas: 78294)\n[PASS] test_submissions() (gas: 260658)\n[PASS] test_tokenURIOnChain() (gas: 1190981)\n[PASS] test_twoStepOwnership_noRenounce() (gas: 198046)\n[PASS] test_withdrawNothingReverts_andHouseGoesToCurrentOwner() (gas: 1241987)\n[PASS] test_wrongHashIsCorrectable() (gas: 777075)\nSuite result: ok. 21 passed; 0 failed; 0 skipped; finished in 75.55ms (73.63ms CPU time)\n\nRan 12 tests for test/Gate.t.sol:GateTest\n[PASS] test_aHostileMembershipContractCountsAsNotMember() (gas: 62498695)\n[PASS] test_auction_gateFixedFromTheFirstBid() (gas: 714509)\n[PASS] test_auction_holdersFirstThenAnyone() (gas: 948469)\n[PASS] test_auction_membersBid_andTheMemberGateIsFixedFromTheFirstBid() (gas: 1006851)\n[PASS] test_brokenSeatContractCountsAsNotHeld() (gas: 61030979)\n[PASS] test_editions_gateFixedOnceTheSaleOpens() (gas: 61529270)\n[PASS] test_editions_holdersFirstThenAnyone() (gas: 62031088)\n[PASS] test_editions_membersBuyInTheWindow_asTokenHoldersDo() (gas: 62059353)\n[PASS] test_editions_noGateMeansOpen() (gas: 61274007)\n[PASS] test_editions_seatBuysUpToFivePerSeatWhereverItGoes() (gas: 62695785)\n[PASS] test_gateRules() (gas: 239527)\n[PASS] test_memberGateRules() (gas: 61261926)\nSuite result: ok. 12 passed; 0 failed; 0 skipped; finished in 78.11ms (152.99ms CPU time)\n\nRan 11 tests for test/Reviews.t.sol:ReviewsTest\n[PASS] testFuzz_tallyMatchesVoices(uint8[12]) (runs: 64, μ: 1444721, ~: 1442081)\n[PASS] test_aClaimedPieceIsAVoice_andAnUnclaimedOneIsNot() (gas: 67623877)\n[PASS] test_aMovedSeatStillHasOneVoice() (gas: 441792)\n[PASS] test_aSeatAndAPieceInOneWalletAreTwoVoices() (gas: 67348609)\n[PASS] test_anyoneAppliesToBeABroker() (gas: 224553)\n[PASS] test_anyonePublishesTheses() (gas: 810776)\n[PASS] test_changingAReviewMovesItsVote() (gas: 305393)\n[PASS] test_frozenOnceTheCuratorDecides_andAdvisoryOnly() (gas: 349039)\n[PASS] test_inputChecks() (gas: 307196)\n[PASS] test_onlyTheSeatHolderReviews() (gas: 97570)\n[PASS] test_seatsReview_andTheTallyFollows() (gas: 457095)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 89.79ms (78.61ms CPU time)\n\nRan 7 tests for test/Adversarial.t.sol:SourceEdgeTest\n[PASS] testFuzz_minimumRaiseIsCeilingOfFivePercent(uint96,uint96) (runs: 512, μ: 629588, ~: 629679)\nLogs:\n  Bound result 60141942638\n  Bound result 476213683457539704\n\n[PASS] testFuzz_rendererHashIsKeccakOfConcatenation(bytes,bytes,bytes) (runs: 64, μ: 419785, ~: 416599)\n[PASS] test_bidBoundaries() (gas: 901651)\n[PASS] test_payloadChunkLimits() (gas: 5443288)\n[PASS] test_setAuctionEdges() (gas: 459334)\n[PASS] test_settleEdges_brokerSplit() (gas: 6966012)\n[PASS] test_settleWithUnapprovedBrokerPaysTheBurn() (gas: 5869414)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 118.52ms (128.29ms CPU time)\n\nRan 23 tests for test/Adversarial.t.sol:ArtHouseEdgeTest\n[PASS] testFuzz_everyoneWithdrawsExactlyTheirShare(uint96,uint96,uint96) (runs: 256, μ: 2048171, ~: 2051370)\nLogs:\n  Bound result 1991214\n  Bound result 88966114747433248107\n  Bound result 150691221\n\n[PASS] testFuzz_splitConservesAndHouseTakesRounding(uint16,uint16,uint16,uint96,uint8) (runs: 512, μ: 260325, ~: 262826)\nLogs:\n  Bound result 9999\n  Bound result 1\n  Bound result 0\n  Bound result 79228162514264337593543950335\n\n[PASS] test_artistEdges() (gas: 1210240)\n[PASS] test_buybackOnlyToTheBurnerSetOnce() (gas: 460935)\n[PASS] test_clearThenReuploadKeepsSizeAccounting() (gas: 40763894)\n[PASS] test_collectionErc721Edges() (gas: 1436052)\n[PASS] test_constructorsDoNotCallDependencies() (gas: 36654)\n[PASS] test_constructorsRejectZeroDependencies() (gas: 4550)\n[PASS] test_curationEdges() (gas: 780836)\n[PASS] test_defaultSplit_agentHouseBurn() (gas: 381579)\n[PASS] test_mintWithIMD_falseReturnRejected() (gas: 2073855)\n[PASS] test_mintWithIMD_feeOnTransferRejected() (gas: 2297085)\n[PASS] test_mintWithIMD_stalePriceRejected() (gas: 1250853)\n[PASS] test_mintZeroPricesReject() (gas: 943137)\n[PASS] test_moduleCollectionsHaveNoPlainCuration() (gas: 376256)\n[PASS] test_pendingOwnerHasNoPowerBeforeAccepting() (gas: 197527)\n[PASS] test_registerModuleCollectionTwiceReverts() (gas: 44789)\n[PASS] test_revokedBrokerKeepsEarnedBalance_butEarnsNoMore() (gas: 1291624)\n[PASS] test_sealEmptyCollectionRevertsAndSealIsOnce() (gas: 657864)\n[PASS] test_splitExtremes() (gas: 1284500)\n[PASS] test_submissionEdges() (gas: 246348)\n[PASS] test_updatePieceAccessEdges() (gas: 1976561)\n[PASS] test_withdrawToRevertingPayoutKeepsBalance() (gas: 1372032)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 122.89ms (189.82ms CPU time)\n\nRan 2 tests for test/LaunchDeployment.t.sol:LaunchDeploymentTest\n[PASS] test_allEightConstructorsAcceptCodeLessDependencies() (gas: 75369724)\n[PASS] test_manifestOrderAndOwnerConfigurationRemainIntact() (gas: 82003740)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 135.85ms (221.50ms CPU time)\n\nRan 12 tests for test/Source.t.sol:ArtifactsSourceTest\n[PASS] testFuzz_revealOpensTheSealedSeed(bytes32,bytes32) (runs: 64, μ: 5893757, ~: 5893838)\n[PASS] test_auctionNeedsTheHouseToAcceptTheSale() (gas: 3285282)\n[PASS] test_auctionNeedsTheSourceLocked() (gas: 620659)\n[PASS] test_auctionReopensWhenNoBids() (gas: 441150)\n[PASS] test_auctionRules() (gas: 6733129)\n[PASS] test_bidReentrancyAndRefundPull() (gas: 767944)\n[PASS] test_deliverKeyOnceToTheWinner() (gas: 9241958)\n[PASS] test_noRevealWhileABuyerIsInEscrow() (gas: 9012360)\n[PASS] test_revealServesTheRendererWithItsSeed() (gas: 512490433)\nLogs:\n  revealed tokenURI gas: 2897251\n\n[PASS] test_revealTakesDownAListingWithNoBuyer() (gas: 8943770)\n[PASS] test_storedSeedIsSealed() (gas: 8734200)\n[PASS] test_tinyBidsMustStrictlyExceed() (gas: 940816)\nSuite result: ok. 12 passed; 0 failed; 0 skipped; finished in 757.44ms (770.79ms CPU time)\n\nRan 11 tests for test/ReviewRound4.t.sol:ReviewRound4Test\n[PASS] testFuzz_gateViewsNeverRevert(address,address,address) (runs: 64, μ: 147459, ~: 147548)\n[PASS] testFuzz_theFallbackResultStandsAgainstAnyLateWord(uint256,bytes32) (runs: 64, μ: 61602125, ~: 61602134)\n[PASS] test_aDeadFallbackDrawCanBeRerequested() (gas: 62342387)\n[PASS] test_aLiveFallbackDrawStillCannotBeRerequested() (gas: 61855098)\n[PASS] test_gateSeats_dirtyOwnerWord_isNotHeld() (gas: 61073739)\n[PASS] test_gateSeats_noCode_isNotHeld() (gas: 61538697)\n[PASS] test_gateSeats_withCode_unchanged() (gas: 61870940)\n[PASS] test_gateToken_noCode_isNotHeld_andMembersStillBuy() (gas: 62065872)\n[PASS] test_noChainlinkAnswerOnceTheFallbackHashIsPublic() (gas: 61639787)\n[PASS] test_noFallbackOnARequestChainlinkMayStillAnswer() (gas: 61638100)\n[PASS] test_source_gateNoCode_bidsRefusedNotReverted_membersBid() (gas: 998508)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 831.72ms (978.24ms CPU time)\n\nRan 1 test for test/invariants/SourceAuctionInvariant.t.sol:SourceAuctionInvariantTest\n[PASS]\nSourceAuctionInvariantTest invariants:\n[PASS] invariant_auctionConservation\n[PASS] invariant_highBidMonotone\n[PASS] invariant_settlementIsFinal\n SourceAuctionInvariantTest invariants (runs: 96, calls: 5760, reverts: 0)\n\n╭----------------+--------------------+-------+---------+----------╮\n| Contract       | Selector           | Calls | Reverts | Discards |\n+==================================================================+\n| AuctionHandler | bid                | 851   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | payloadStaysLocked | 829   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | recordHigh         | 828   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | setAuction         | 794   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | settle             | 834   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | warp               | 852   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | withdrawRefund     | 772   | 0       | 0        |\n╰----------------+--------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 694\n  Bound result 1583096506078419801\n  Bound result 437\n  Bound result 1321\n  Bound result 2000000000000000128\n  Bound result 400\n  Bound result 1800\n  Bound result 401\n  Bound result 3497\n  Bound result 4000000000000000405\n  Bound result 1078\n  Bound result 425\n  Bound result 1562\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 862.18ms (858.82ms CPU time)\n\nRan 25 tests for test/NothingStuck.t.sol:NothingStuckTest\n[PASS] test_aBuyerNeedsAViewingKeyAProofCanUse() (gas: 67200269)\n[PASS] test_aJunkKeyIsProvenFake_paymentAndDepositToTheBuyer() (gas: 67784555)\n[PASS] test_aSilentSellerLetsTheBuyerCancelAfter24Hours() (gas: 67371726)\n[PASS] test_anAuctionClosedInTimeCannotBeVoided() (gas: 5846482)\n[PASS] test_anAuctionNobodyCanCloseGivesTheBidBack() (gas: 6134344)\n[PASS] test_callbackGasCanOnlyGoUpOnceTheSaleOpens() (gas: 60960821)\n[PASS] test_claimWithoutAKey_after30Days_thenTheKeyGoesIntoThePiece() (gas: 67152172)\n[PASS] test_curatorReKeysAPieceItsPreviousOwnerNeverDid() (gas: 67308328)\n[PASS] test_fallbackDraw_aStartedDrawsResultStands_finishedFromTheHistory() (gas: 61896434)\n[PASS] test_fallbackDraw_chainlinkStillWinsIfItAnswersFirst() (gas: 61650523)\n[PASS] test_fallbackDraw_countsFromThePurchase() (gas: 61827139)\n[PASS] test_fallbackDraw_oneAtATime() (gas: 62775290)\n[PASS] test_fallbackDraw_onlyAfterThreeDays_fromABlockNobodyKnew() (gas: 61810020)\n[PASS] test_fallbackDraw_startsAgainOnlyOnceItsHashIsGone() (gas: 61653096)\n[PASS] test_fallbackDraw_startsOnAYoungRequestTheCoordinatorNoLongerHolds() (gas: 61625047)\n[PASS] test_noProofBeforeAKey_andTheSellerCantDodgeOne() (gas: 67731873)\n[PASS] test_onlyAKeyTheSellerMadeCanBePosted() (gas: 67793456)\n[PASS] test_realKeys_aJunkKeyIsProvenFake() (gas: 907133)\nLogs:\n  gas for the buyer's proveFakeKey: 170130\n\n[PASS] test_realKeys_anHonestKeyCanNeverBeProvenFake() (gas: 1254953)\n[PASS] test_realKeys_theBuyerCantSwapViewingKeysToFrameTheSeller() (gas: 888070)\n[PASS] test_realKeys_theRightKeyWrappedToAnotherKeyIsFake() (gas: 894751)\n[PASS] test_the72HoursCountFromTheKey() (gas: 67793086)\n[PASS] test_theBuyerCantCancelUnderAPendingKey() (gas: 67568079)\n[PASS] test_theDepositIsExactly10Percent() (gas: 67672385)\n[PASS] test_theSellerCanRefundBeforeSendingAKey() (gas: 67479161)\nSuite result: ok. 25 passed; 0 failed; 0 skipped; finished in 1.05s (410.75ms CPU time)\n\nRan 3 tests for test/Adversarial.t.sol:RuntimeTest\n[PASS] test_implementationsAreLocked() (gas: 104926)\n[PASS] test_launchedRuntimesAreBoundedAndHaveNoEscapeOpcodes() (gas: 60534514)\n[PASS] test_noRenounceAnywhere() (gas: 155507)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 1.06s (91.90ms CPU time)\n\nRan 15 tests for test/LaunchAudit.t.sol:LaunchAuditTest\n[PASS] testFuzz_memberReplyMustBeExactlyOneWord(uint16,uint256,uint256) (runs: 64, μ: 433298, ~: 434781)\nLogs:\n  Bound result 350000\n\n[PASS] test_attackerCannotInitializeCollectionAsRealHouse() (gas: 1082634)\n[PASS] test_attackerCannotInitializePieceAsRealFactory() (gas: 5034126)\n[PASS] test_attackerCannotInitializePieceAsRealSource() (gas: 5024422)\n[PASS] test_brokenBrokerPassDoesNotBlockEditionPurchase() (gas: 61675694)\n[PASS] test_brokenBrokerPassDoesNotBlockSourceSettlement() (gas: 19657183)\n[PASS] test_brokenPassDoesNotBlockPlainMintsInEitherCurrency() (gas: 2535075)\n[PASS] test_brokerPassMalformedRepliesCountAsIneligible() (gas: 934454)\n[PASS] test_claimedEditionsAreIndependentRuntimesAndStorage() (gas: 104039931)\n[PASS] test_dynamicMemberReplyCannotBypassEditionWindow() (gas: 61590217)\n[PASS] test_dynamicMemberReplyCannotBypassSourceWindow() (gas: 676729)\n[PASS] test_initializerRejectsEOAController() (gas: 6086143)\n[PASS] test_keyPostEventUnchangedBeforeAndAfterClaim() (gas: 67265577)\n[PASS] test_ownerCanClosePrimarySaleAndChangePendingAuctionSplit() (gas: 73214403)\n[PASS] test_plainCollectionIsIndependentRuntime() (gas: 4127353)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 1.06s (203.81ms CPU time)\n\nRan 16 tests for test/Artifacts.t.sol:ArtifactsFactoryTest\n[PASS] test_buyFailures() (gas: 60997239)\n[PASS] test_buyMany_cannotPassSupply() (gas: 98935498)\n[PASS] test_buyMany_fivePerWallet() (gas: 63860710)\n[PASS] test_buyRecordsSaleAndAssignsEveryEditionOnce() (gas: 178065420)\n[PASS] test_claimFlow_andFailures() (gas: 67458014)\n[PASS] test_postWrappedKeysInOneBatch() (gas: 67755786)\n[PASS] test_publishAndLock_accessAndFailures() (gas: 60947985)\n[PASS] test_rerequestAtOnceWhenTheCoordinatorAnsweredButTheCallbackFailed() (gas: 61875354)\n[PASS] test_rerequestRandomnessAfterDroppedRequest() (gas: 62033982)\n[PASS] test_saleControl() (gas: 61043179)\n[PASS] test_sealTokenURIMatchesR8Frame() (gas: 970414031)\n[PASS] test_viewingKeyZeroRejected() (gas: 33301)\n[PASS] test_vrfCallbackCannotBeReplayed() (gas: 61629805)\n[PASS] test_vrfCallbackGasIsTheCuratorsToTune() (gas: 61431482)\n[PASS] test_vrfCorrectableUntilTheSaleOpens_thenLockedForever() (gas: 62248774)\n[PASS] test_vrfMustBeConfiguredBeforeSelling() (gas: 46850)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 1.31s (1.66s CPU time)\n\nRan 1 test for test/invariants/PieceEscrowInvariant.t.sol:PieceEscrowInvariantTest\n[PASS]\nPieceEscrowInvariantTest invariants:\n[PASS] invariant_escrowConservation\n[PASS] invariant_escrowSellerOwns\n[PASS] invariant_royaltyAndIdentity\n[PASS] invariant_singleToken\n PieceEscrowInvariantTest invariants (runs: 96, calls: 5760, reverts: 0)\n\n╭---------------+--------------------+-------+---------+----------╮\n| Contract      | Selector           | Calls | Reverts | Discards |\n+=================================================================+\n| EscrowHandler | approveAndTransfer | 387   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | buy                | 370   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | cancel             | 387   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | delist             | 402   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | list               | 390   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | postKey            | 413   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | proveFake          | 367   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | refundBuyer        | 354   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | registerKey        | 387   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | release            | 391   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | rewrap             | 402   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | transfer           | 407   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | warp               | 366   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | withdraw           | 355   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | withdrawRoyalty    | 382   | 0       | 0        |\n╰---------------+--------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 17083\n  Bound result 14264337593543950335\n  Bound result 735\n  Bound result 20337108042\n  Bound result 111059\n  Bound result 34646\n  Bound result 4037\n  Bound result 4660\n  Bound result 576000\n  Bound result 20880797823880349362\n  Bound result 1000\n  Bound result 15121\n  Bound result 336000\n  Bound result 47915958131739435367\n  Bound result 9999\n  Bound result 3811\n  Bound result 149144\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.46s (1.42s CPU time)\n\nRan 1 test for test/invariants/ArtifactsFactoryInvariant.t.sol:ArtifactsFactoryInvariantTest\n[PASS]\nArtifactsFactoryInvariantTest invariants:\n[PASS] invariant_claimedPiecesBelongToBuyers\n[PASS] invariant_counts\n[PASS] invariant_ledgerHoldsEveryPurchase\n[PASS] invariant_lockedAndPriced\n[PASS] invariant_walletLimit\n ArtifactsFactoryInvariantTest invariants (runs: 96, calls: 5760, reverts: 0)\n\n╭----------------+-------------------+-------+---------+----------╮\n| Contract       | Selector          | Calls | Reverts | Discards |\n+=================================================================+\n| FactoryHandler | buy               | 534   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | buyMany           | 495   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | claim             | 552   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | fulfil            | 497   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | lockedForever     | 508   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | replay            | 536   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | rerequest         | 507   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | setPrice          | 494   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | strangerFulfil    | 564   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | strangerRerequest | 534   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | toggleSale        | 539   | 0       | 0        |\n╰----------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 338193125\n  Bound result 51638143296626\n  Bound result 0\n  Bound result 2574237282764180103\n  Bound result 4264337593543950335\n  Bound result 4\n  Bound result 5\n  Bound result 6\n  Bound result 1\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.67s (1.59s CPU time)\n\nRan 1 test for test/invariants/ArtHouseInvariant.t.sol:ArtHouseInvariantTest\n[PASS]\nArtHouseInvariantTest invariants:\n[PASS] invariant_constants\n[PASS] invariant_ethConservation\n[PASS] invariant_imdConservation\n[PASS] invariant_noOverWithdrawal\n[PASS] invariant_supplyAndSeal\n ArtHouseInvariantTest invariants (runs: 128, calls: 5120, reverts: 0)\n\n╭---------------+----------------+-------+---------+----------╮\n| Contract      | Selector       | Calls | Reverts | Discards |\n+=============================================================+\n| LedgerHandler | handOver       | 380   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | mintETH        | 369   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | mintIMD        | 414   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | moduleSale     | 377   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | releaseBuyback | 413   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setBroker      | 396   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setPayout      | 404   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setPrices      | 429   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setSaleOpen    | 378   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setSplit       | 413   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | strangerCalls  | 361   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | withdraw       | 377   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | withdrawHouse  | 409   | 0       | 0        |\n╰---------------+----------------+-------+---------+----------╯\n\nLogs:\n  Bound result 18882627285399\n  Bound result 685\n  Bound result 1073742068\n  Bound result 61765395460014508990\n  Bound result 9\n  Bound result 986\n  Bound result 127\n  Bound result 1074\n  Bound result 5569\n  Bound result 4058\n  Bound result 6\n  Bound result 14264337593543950335\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.43s (3.42s CPU time)\n\nRan 13 tests for test/Adversarial.t.sol:ArtifactsEdgeTest\n[PASS] testFuzz_anyWordsAssignDistinctEditions(uint256[8]) (runs: 256, μ: 64665126, ~: 64666799)\n[PASS] testFuzz_sealFramesAnyTraits(uint8,uint8,uint8,uint8,uint8) (runs: 16, μ: 519807370, ~: 519808015)\nLogs:\n  Bound result 7\n\n[PASS] test_buyRevertsAtomicallyWhenCoordinatorReverts() (gas: 59197366)\n[PASS] test_callbackWithNoWordsReverts() (gas: 61551984)\n[PASS] test_claimedPieceIsAFullCopyOfTheImplementation() (gas: 67249308)\n[PASS] test_configureVRFRejectsZeroes() (gas: 211437)\n[PASS] test_duplicateRequestIdRejected() (gas: 59391685)\n[PASS] test_nonOwnerCannotRunTheSale() (gas: 60818098)\n[PASS] test_rerequestIsAtomicWhenCoordinatorReverts() (gas: 59885766)\n[PASS] test_rerequestWindowBoundaryAndChaining() (gas: 67823748)\n[PASS] test_setPieceEdges() (gas: 61051490)\n[PASS] test_unapprovedBuyerAsBrokerEarnsNothing_andOneWeiPriceWorks() (gas: 61489495)\n[PASS] test_wrappedKeyEdges() (gas: 67231974)\nSuite result: ok. 13 passed; 0 failed; 0 skipped; finished in 10.00s (11.17s CPU time)\n\nRan 30 test suites in 10.01s (24.39s CPU time): 244 tests passed, 0 failed, 2 skipped (246 total tests)\n","passed":true},{"durationMs":88,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"ArtCollection.approve(address,uint256)\",\"ArtCollection.initialize(address,string,string)\",\"ArtCollection.mint(address,uint256)\",\"ArtCollection.safeTransferFrom(address,address,uint256)\",\"ArtCollection.safeTransferFrom(address,address,uint256,bytes)\",\"ArtCollection.setApprovalForAll(address,bool)\",\"ArtCollection.transferFrom(address,address,uint256)\",\"ArtHouse.acceptOwnership()\",\"ArtHouse.approveArtist(address,string)\",\"ArtHouse.clearPiece(address,uint256)\",\"ArtHouse.createCollection(string,string,address)\",\"ArtHouse.decideSubmission(uint256,bool)\",\"ArtHouse.finalizePiece(address,uint256)\",\"ArtHouse.mint(address,uint256,address)\",\"ArtHouse.mintWithIMD(address,uint256,address,uint256)\",\"ArtHouse.recordResale(address,uint256,uint256)\",\"ArtHouse.recordSale(address,address,address)\",\"ArtHouse.registerModuleCollection(address,address)\",\"ArtHouse.registerPiece(address,uint256,bytes32,string,string)\",\"ArtHouse.releaseBuyback(address)\",\"ArtHouse.revokeArtist(address)\",\"ArtHouse.sealCollection(address)\",\"ArtHouse.setBroker(address,bool)\",\"ArtHouse.setBrokerPass(address)\",\"ArtHouse.setBuybackBurner(address)\",\"ArtHouse.setPayout(address)\",\"ArtHouse.setPrices(address,uint256,uint256)\",\"ArtHouse.setSaleModule(address,bool)\",\"ArtHouse.setSaleOpen(address,bool)\",\"ArtHouse.setSplit(address,uint16,uint16,uint16,uint16)\",\"ArtHouse.submit(bytes32,string)\",\"ArtHouse.transferOwnership(address)\",\"ArtHouse.updatePiece(address,uint256,bytes32,string,string)\",\"ArtHouse.uploadChunk(address,uint256,uint256,bytes)\",\"ArtHouse.withdraw(address)\",\"ArtHouse.withdrawHouse(address)\",\"ArtStorage.acceptOwnership()\",\"ArtStorage.clear(address,uint256)\",\"ArtStorage.setHouse(address)\",\"ArtStorage.transferOwnership(address)\",\"ArtStorage.write(address,uint256,uint256,bytes)\",\"ArtifactsFactory.acceptOwnership()\",\"ArtifactsFactory.buy(address)\",\"ArtifactsFactory.buyMany(uint256,address)\",\"ArtifactsFactory.buyWithSeat(uint256,uint256,address)\",\"ArtifactsFactory.claim(uint256)\",\"ArtifactsFactory.claimMany(uint256[])\",\"ArtifactsFactory.configureVRF(address,bytes32,uint256,bool)\",\"ArtifactsFactory.endSale()\",\"ArtifactsFactory.finishFallbackDraw(uint256)\",\"ArtifactsFactory.lock()\",\"ArtifactsFactory.postWrappedKey(uint256,bytes)\",\"ArtifactsFactory.postWrappedKeys(uint256[],bytes[])\",\"ArtifactsFactory.rawFulfillRandomWords(uint256,uint256[])\",\"ArtifactsFactory.registerViewingKey(bytes32)\",\"ArtifactsFactory.rerequestRandomness(uint256)\",\"ArtifactsFactory.setGate(address,address,uint256,uint64)\",\"ArtifactsFactory.setMemberGate(address,bytes4,uint256)\",\"ArtifactsFactory.setMintPhases(uint64,uint8,uint64,uint8)\",\"ArtifactsFactory.setPiece(uint256,(string,string,uint8,string),bytes,bytes32)\",\"ArtifactsFactory.setPrice(uint256)\",\"ArtifactsFactory.setSaleOpen(bool)\",\"ArtifactsFactory.setVRFCallbackGas(uint32)\",\"ArtifactsFactory.startFallbackDraw(uint256)\",\"ArtifactsFactory.transferOwnership(address)\",\"ArtifactsPiece.approve(address,uint256)\",\"ArtifactsPiece.buy(bytes32,address)\",\"ArtifactsPiece.cancel()\",\"ArtifactsPiece.delist()\",\"ArtifactsPiece.initialize(address,address,uint256,address,(string,string,uint8,string),address,bytes32,bytes,bool,bytes32)\",\"ArtifactsPiece.list(uint256)\",\"ArtifactsPiece.postEscrowKey(bytes,address,uint256)\",\"ArtifactsPiece.proveFakeKey((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256))\",\"ArtifactsPiece.refundBuyer()\",\"ArtifactsPiece.registerViewingKey(bytes32)\",\"ArtifactsPiece.release()\",\"ArtifactsPiece.reveal(bytes32)\",\"ArtifactsPiece.rewrapFor(bytes)\",\"ArtifactsPiece.safeTransferFrom(address,address,uint256)\",\"ArtifactsPiece.safeTransferFrom(address,address,uint256,bytes)\",\"ArtifactsPiece.setApprovalForAll(address,bool)\",\"ArtifactsPiece.transferFrom(address,address,uint256)\",\"ArtifactsPiece.withdraw()\",\"ArtifactsSource.acceptOwnership()\",\"ArtifactsSource.bid(address)\",\"ArtifactsSource.deliverKey(bytes)\",\"ArtifactsSource.lock(bytes32,bytes32)\",\"ArtifactsSource.resetRenderer()\",\"ArtifactsSource.setAuction(uint256,uint64)\",\"ArtifactsSource.setGate(address,address,uint256,uint64)\",\"ArtifactsSource.setMemberGate(address,bytes4,uint256)\",\"ArtifactsSource.settle()\",\"ArtifactsSource.storeRendererChunk(bytes)\",\"ArtifactsSource.transferOwnership(address)\",\"ArtifactsSource.voidUnsettled()\",\"ArtifactsSource.withdrawRefund()\",\"BrokerPass.approve(address,uint256)\",\"BrokerPass.claimWithPiece(uint256)\",\"BrokerPass.claimWithSeat(uint256)\",\"BrokerPass.safeTransferFrom(address,address,uint256)\",\"BrokerPass.safeTransferFrom(address,address,uint256,bytes)\",\"BrokerPass.setApprovalForAll(address,bool)\",\"BrokerPass.setClaimsOpenAt(uint64)\",\"BrokerPass.transferFrom(address,address,uint256)\",\"ImdBuybackBurner.burnEth(uint256,uint256,uint256)\",\"ImdBuybackBurner.burnImd()\",\"ImdBuybackBurner.receive()\",\"ImdBuybackBurner.unlockCallback(bytes)\",\"SubmissionReviews.applyAsBroker(string)\",\"SubmissionReviews.postThesis(uint256,string)\",\"SubmissionReviews.reviewAsPiece(uint256,uint256,uint8,string)\",\"SubmissionReviews.reviewAsSeat(uint256,uint256,uint8,string)\"],\"files\":{\".gitignore\":3,\"ADAPTATION.md\":356,\"README.md\":272,\"foundry.toml\":25,\"launch.burner.json\":17,\"launch.json\":63,\"reference/PROTOCOL.md\":99,\"reference/RULES.md\":137,\"reference/audit/V13Audit.t.sol.txt\":381,\"reference/check-framed.js\":25,\"reference/framed/framed-003.svg\":1,\"reference/framed/framed-MASTER.svg\":1,\"reference/rules.js\":145,\"reference/the-source.renderer.html\":148,\"remappings.txt\":1,\"script/Deploy.s.sol\":39,\"src/ArtCollection.sol\":55,\"src/ArtHouse.sol\":609,\"src/ArtStorage.sol\":82,\"src/ArtifactsFactory.sol\":635,\"src/ArtifactsPiece.sol\":457,\"src/ArtifactsSource.sol\":271,\"src/BrokerPass.sol\":142,\"src/ImdBuybackBurner.sol\":163,\"src/KeyProof.sol\":154,\"src/SubmissionReviews.sol\":215,\"src/base/ERC721Lite.sol\":122,\"src/base/HolderGate.sol\":113,\"src/base/ReentrancyGuard.sol\":15,\"src/base/TwoStepOwnable.sol\":40,\"src/interfaces/Interfaces.sol\":93,\"src/libs/Clones.sol\":19,\"src/libs/Encoding.sol\":79,\"src/libs/SSTORE2.sol\":41,\"src/libs/Seal.sol\":102,\"test/Adversarial.t.sol\":1409,\"test/ArtHouse.t.sol\":463,\"test/Artifacts.t.sol\":673,\"test/AuditRound3.t.sol\":151,\"test/BrokerPass.t.sol\":373,\"test/Burner.t.sol\":161,\"test/ClaimEnd.t.sol\":152,\"test/Fixture.sol\":230,\"test/Gate.t.sol\":295,\"test/KeyProof.t.sol\":134,\"test/LaunchAudit.t.sol\":338,\"test/LaunchDeployment.t.sol\":191,\"test/NothingStuck.t.sol\":594,\"test/Phases.t.sol\":130,\"test/ReviewRound4.t.sol\":262,\"test/Reviews.t.sol\":264,\"test/Source.t.sol\":396,\"test/audit/KeyProofEdges.t.sol\":178,\"test/audit/KeyReuseLeak.t.sol\":38,\"test/fixtures/keyproof.json\":81,\"test/fork/BurnerFork.t.sol\":70,\"test/fork/VrfFork.t.sol\":131,\"test/invariants/ArtHouseInvariant.t.sol\":444,\"test/invariants/ArtifactsFactoryInvariant.t.sol\":323,\"test/invariants/PieceEscrowInvariant.t.sol\":445,\"test/invariants/SourceAuctionInvariant.t.sol\":227,\"test/mocks/AdversarialMocks.sol\":134,\"test/mocks/MockPoolManager.sol\":57,\"test/mocks/MockSeats.sol\":27,\"test/mocks/Mocks.sol\":149,\"test/mocks/TestVRFCoordinator.sol\":46,\"test/utils/Base64Decode.sol\":83},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"1594313bbfc4bfec71e608aa6d7e7e6cc619b82f7cba369e29d7eb059afd76bf","verifiedTreeHash":"48a5085f4e9297a26d1414c51ab8843201bbed3f","verifierVersion":"0.1.0+a6ee6548"},{"checks":[{"durationMs":373863,"exitCode":0,"name":"build","output":"Compiling 73 files with Solc 0.8.26\nSolc 0.8.26 finished in 373.75s\nCompiler run successful with warnings:\nWarning (5667): Unused function parameter. Remove or comment out the variable name to silence this warning.\n   --> test/invariants/ArtHouseInvariant.t.sol:105:9:\n    |\n105 |         address buyer,\n    |         ^^^^^^^^^^^^^\n\n","passed":true},{"durationMs":9608,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/fork/BurnerFork.t.sol:BurnerForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 389.45µs (0.00ns CPU time)\n\nRan 8 tests for test/KeyProof.t.sol:KeyProofTest\n[PASS] test_aJunkKeyIsProvenFake() (gas: 369871)\nLogs:\n  gas to check a fake-key proof: 44805\n\n[PASS] test_aKeyThatOpensIsNeverProvenFake() (gas: 368087)\n[PASS] test_aProofOnlyHoldsForItsBuyerPieceAndChain() (gas: 416867)\n[PASS] test_aProofOnlyHoldsForItsOwnWrappedKey() (gas: 416275)\n[PASS] test_aTamperedProofFails() (gas: 768976)\n[PASS] test_madeUpBytesAndTheOldFormatAreFake() (gas: 690806)\n[PASS] test_theRightKeyForSomeoneElseIsProvenFake() (gas: 368314)\n[PASS] test_viewingKeys() (gas: 34725)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 8.99ms (7.73ms CPU time)\n\nRan 1 test for test/fork/VrfFork.t.sol:VrfForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 1.41ms (0.00ns CPU time)\n\nRan 1 test for test/ClaimEnd.t.sol:EndBeforeOpenTest\n[PASS] test_endSale_beforeOpening_refused() (gas: 60691353)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 19.97ms (17.87ms CPU time)\n\nRan 4 tests for test/Phases.t.sol:PhasesTest\n[PASS] test_aSeatFollowsThePhases_whereverItGoes() (gas: 1747601)\n[PASS] test_afterTheWindow_anyoneUpToFive() (gas: 1042332)\n[PASS] test_capsRise_1_then_2_then_5_forAnImdHolder() (gas: 1740916)\n[PASS] test_setOnlyBeforeTheSaleOpens_andChecked() (gas: 322444)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 23.79ms (1.27ms CPU time)\n\nRan 6 tests for test/Adversarial.t.sol:PieceEdgeTest\n[PASS] test_cancelThenSecondBuyerAndRoyaltyToChangedPayout() (gas: 1087998)\n[PASS] test_listingEdges() (gas: 1002975)\n[PASS] test_releaseAtExactly72HoursByStranger() (gas: 914016)\n[PASS] test_revealNeedsTheSourceLocked_andEmptyRendererURI() (gas: 6265659)\n[PASS] test_safeTransferReceivers() (gas: 670237)\n[PASS] test_transferAuthEdges() (gas: 350213)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 26.84ms (3.31ms CPU time)\n\nRan 4 tests for test/AuditRound3.t.sol:AuditRound3Test\n[PASS] test_aReturnDataBombCostsThePayerNothing() (gas: 694152)\n[PASS] test_aShareThatWaitsInTheLedgerIsAnnounced() (gas: 339919)\n[PASS] test_theArtistsPayoutCantMoveThePieceDuringARelease() (gas: 415877)\n[PASS] test_theArtistsPayoutCantRelistDuringARelease() (gas: 600564)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 30.32ms (849.80µs CPU time)\n\nRan 1 test for test/audit/KeyReuseLeak.t.sol:KeyReuseLeakTest\n[PASS] test_copiedE_cantBePosted(uint256,uint256) (runs: 64, μ: 602938, ~: 603209)\nLogs:\n  Bound result 6677771717396745857438524715775791381032702405673290885595687978682\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 31.03ms (28.68ms CPU time)\n\nRan 5 tests for test/ClaimEnd.t.sol:ClaimEndTest\n[PASS] test_claimMany_claimsEveryOneInOneCall() (gas: 18158157)\n[PASS] test_claimMany_emptyRefused_andTheCuratorCanClaimForBuyers() (gas: 12316427)\n[PASS] test_claimMany_isAllOrNothing() (gas: 18212437)\n[PASS] test_endSale_isFinal() (gas: 6928373)\n[PASS] test_endSale_needsTheSaleToHaveOpened_andWorksWhileClosed() (gas: 96083)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 31.32ms (3.78ms CPU time)\n\nRan 10 tests for test/Artifacts.t.sol:ArtifactsPieceEscrowTest\n[PASS] test_escrowCancelBeforeKey_andDelist() (gas: 501042)\n[PASS] test_escrowHappyPath_buyerConfirms() (gas: 1181854)\n[PASS] test_escrowKeyMustNotBeEmpty() (gas: 310921)\n[PASS] test_escrowTimeoutRelease() (gas: 728994)\n[PASS] test_pieceViewingKeyZeroRejected() (gas: 168689)\n[PASS] test_plainTransferClearsKey_previousOwnerRekeys() (gas: 506819)\n[PASS] test_reentrancyOnEscrowWithdrawBlocked() (gas: 844317)\n[PASS] test_rewrapIsOneShotAndNonEmpty() (gas: 284134)\n[PASS] test_sellerCannotOverwriteKeyAfterRelease() (gas: 913301)\n[PASS] test_sourceOnlyReveal() (gas: 35552)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 35.64ms (4.01ms CPU time)\n\nRan 21 tests for test/ArtHouse.t.sol:ArtHouseTest\n[PASS] testFuzz_ethSplitInvariant(uint96,bool,bool) (runs: 64, μ: 1218374, ~: 1239979)\n[PASS] testFuzz_imdSplitInvariant(uint96,bool) (runs: 64, μ: 1311545, ~: 1314827)\n[PASS] test_artistPayoutOnlyArtist_keptOnReapproval() (gas: 179207)\n[PASS] test_collectionMintOnlyHouse() (gas: 73967)\n[PASS] test_curationFlow_andFailures() (gas: 938837)\n[PASS] test_customSplit() (gas: 1124713)\n[PASS] test_deploymentWiring() (gas: 93139)\n[PASS] test_imdBuybackIsReleasedAndBurned() (gas: 1882866)\n[PASS] test_mintFailures() (gas: 1550882)\n[PASS] test_onlyCuratorApproves() (gas: 123827)\n[PASS] test_pieceOver100KBRejected() (gas: 21310484)\n[PASS] test_recordSaleOnlyModules() (gas: 120446)\n[PASS] test_reentrancyOnWithdrawBlocked() (gas: 1838346)\n[PASS] test_revokedArtistLosesCuration() (gas: 582575)\n[PASS] test_sealNeedsEveryPieceFinalized() (gas: 527413)\n[PASS] test_setHouseOnce() (gas: 78294)\n[PASS] test_submissions() (gas: 260658)\n[PASS] test_tokenURIOnChain() (gas: 1190981)\n[PASS] test_twoStepOwnership_noRenounce() (gas: 198046)\n[PASS] test_withdrawNothingReverts_andHouseGoesToCurrentOwner() (gas: 1241987)\n[PASS] test_wrongHashIsCorrectable() (gas: 777075)\nSuite result: ok. 21 passed; 0 failed; 0 skipped; finished in 55.46ms (52.43ms CPU time)\n\nRan 7 tests for test/Burner.t.sol:BurnerTest\n[PASS] test_anyoneBurnsHeldImd() (gas: 169949)\n[PASS] test_anyoneSwapsInSmallStepsAfter60QuietDays() (gas: 845755)\n[PASS] test_constructorChecks() (gas: 8711)\n[PASS] test_editionSaleToBurnedImd() (gas: 61800771)\n[PASS] test_onlyTheCuratorSwaps_withAMinimumAndADeadline() (gas: 653639)\n[PASS] test_onlyThePoolManagerCallsBack() (gas: 32189)\n[PASS] test_theNewOwnerSwapsAfterAHandover() (gas: 304000)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 76.80ms (72.85ms CPU time)\n\nRan 3 tests for test/Adversarial.t.sol:RuntimeTest\n[PASS] test_implementationsAreLocked() (gas: 104926)\n[PASS] test_launchedRuntimesAreBoundedAndHaveNoEscapeOpcodes() (gas: 60534514)\n[PASS] test_noRenounceAnywhere() (gas: 155507)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 85.80ms (82.99ms CPU time)\n\nRan 11 tests for test/Reviews.t.sol:ReviewsTest\n[PASS] testFuzz_tallyMatchesVoices(uint8[12]) (runs: 64, μ: 1443075, ~: 1448713)\n[PASS] test_aClaimedPieceIsAVoice_andAnUnclaimedOneIsNot() (gas: 67623877)\n[PASS] test_aMovedSeatStillHasOneVoice() (gas: 441792)\n[PASS] test_aSeatAndAPieceInOneWalletAreTwoVoices() (gas: 67348609)\n[PASS] test_anyoneAppliesToBeABroker() (gas: 224553)\n[PASS] test_anyonePublishesTheses() (gas: 810776)\n[PASS] test_changingAReviewMovesItsVote() (gas: 305393)\n[PASS] test_frozenOnceTheCuratorDecides_andAdvisoryOnly() (gas: 349039)\n[PASS] test_inputChecks() (gas: 307196)\n[PASS] test_onlyTheSeatHolderReviews() (gas: 97570)\n[PASS] test_seatsReview_andTheTallyFollows() (gas: 457095)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 97.02ms (82.23ms CPU time)\n\nRan 5 tests for test/audit/KeyProofEdges.t.sol:KeyProofEdgesTest\n[PASS] test_adversarialE_isProvable() (gas: 107849)\n[PASS] test_adversarialE_proofIsActuallyChecked() (gas: 23615)\n[PASS] test_negatedSCannotFrame() (gas: 60700)\n[PASS] test_oddYWrapThatOpensIsNotFake() (gas: 37558)\n[PASS] test_xEqualsN_isMalformed() (gas: 13218)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 98.44ms (1.95ms CPU time)\n\nRan 7 tests for test/Adversarial.t.sol:SourceEdgeTest\n[PASS] testFuzz_minimumRaiseIsCeilingOfFivePercent(uint96,uint96) (runs: 512, μ: 629588, ~: 629679)\nLogs:\n  Bound result 60141942638\n  Bound result 476213683457539704\n\n[PASS] testFuzz_rendererHashIsKeccakOfConcatenation(bytes,bytes,bytes) (runs: 64, μ: 419892, ~: 416599)\n[PASS] test_bidBoundaries() (gas: 901651)\n[PASS] test_payloadChunkLimits() (gas: 5443288)\n[PASS] test_setAuctionEdges() (gas: 459334)\n[PASS] test_settleEdges_brokerSplit() (gas: 6966012)\n[PASS] test_settleWithUnapprovedBrokerPaysTheBurn() (gas: 5869414)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 131.26ms (137.40ms CPU time)\n\nRan 18 tests for test/BrokerPass.t.sol:BrokerPassTest\n[PASS] test_capIs100() (gas: 19752778)\n[PASS] test_claimWithPiece_onceEverPerPiece() (gas: 6682132)\n[PASS] test_claimWithSeat_onceEverPerSeat() (gas: 376003)\n[PASS] test_claimWithTheSource() (gas: 6010301)\n[PASS] test_claimsWaitForTheStartTime_setOnceByTheCurator() (gas: 489742)\n[PASS] test_oneClaimPerWallet() (gas: 6983032)\n[PASS] test_passHolderCanBrokerTheirOwnBuy() (gas: 1022212)\n[PASS] test_passHolderEarnsOnMint_andTheRightMovesWithThePass() (gas: 2088032)\n[PASS] test_recordResaleRejectsAnythingButAPiece() (gas: 298286)\n[PASS] test_resaleBrokerShare_creditedInTheLedger() (gas: 7297226)\n[PASS] test_resaleBuyerWithAPassCanBrokerTheirOwnBuy() (gas: 7234530)\n[PASS] test_resaleFallsBackToThePieceWhenTheLedgerRefuses() (gas: 7249631)\n[PASS] test_resaleSellerCannotBeBroker() (gas: 7147070)\n[PASS] test_resaleWithoutEligibleBroker_sellerKeepsTheShare() (gas: 6936228)\n[PASS] test_setBrokerPassOnce() (gas: 64999)\n[PASS] test_sourceSplit_brokerAndArtistOnly() (gas: 6162142)\n[PASS] test_sourceSplit_noBrokerBurns() (gas: 5919583)\n[PASS] test_tokenURIIsOnChainJson() (gas: 388848)\nSuite result: ok. 18 passed; 0 failed; 0 skipped; finished in 154.81ms (14.76ms CPU time)\n\nRan 2 tests for test/LaunchDeployment.t.sol:LaunchDeploymentTest\n[PASS] test_allEightConstructorsAcceptCodeLessDependencies() (gas: 75369724)\n[PASS] test_manifestOrderAndOwnerConfigurationRemainIntact() (gas: 82003740)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 168.10ms (224.65ms CPU time)\n\nRan 12 tests for test/Gate.t.sol:GateTest\n[PASS] test_aHostileMembershipContractCountsAsNotMember() (gas: 62498695)\n[PASS] test_auction_gateFixedFromTheFirstBid() (gas: 714509)\n[PASS] test_auction_holdersFirstThenAnyone() (gas: 948469)\n[PASS] test_auction_membersBid_andTheMemberGateIsFixedFromTheFirstBid() (gas: 1006851)\n[PASS] test_brokenSeatContractCountsAsNotHeld() (gas: 61030979)\n[PASS] test_editions_gateFixedOnceTheSaleOpens() (gas: 61529270)\n[PASS] test_editions_holdersFirstThenAnyone() (gas: 62031088)\n[PASS] test_editions_membersBuyInTheWindow_asTokenHoldersDo() (gas: 62059353)\n[PASS] test_editions_noGateMeansOpen() (gas: 61274007)\n[PASS] test_editions_seatBuysUpToFivePerSeatWhereverItGoes() (gas: 62695785)\n[PASS] test_gateRules() (gas: 239527)\n[PASS] test_memberGateRules() (gas: 61261926)\nSuite result: ok. 12 passed; 0 failed; 0 skipped; finished in 168.18ms (130.45ms CPU time)\n\nRan 23 tests for test/Adversarial.t.sol:ArtHouseEdgeTest\n[PASS] testFuzz_everyoneWithdrawsExactlyTheirShare(uint96,uint96,uint96) (runs: 256, μ: 2048171, ~: 2051370)\nLogs:\n  Bound result 1687053956312409914\n  Bound result 29410530796336771647\n  Bound result 1215619572\n\n[PASS] testFuzz_splitConservesAndHouseTakesRounding(uint16,uint16,uint16,uint96,uint8) (runs: 512, μ: 260287, ~: 262814)\nLogs:\n  Bound result 15\n  Bound result 0\n  Bound result 5363\n  Bound result 28723682549529592863503981\n\n[PASS] test_artistEdges() (gas: 1210240)\n[PASS] test_buybackOnlyToTheBurnerSetOnce() (gas: 460935)\n[PASS] test_clearThenReuploadKeepsSizeAccounting() (gas: 40763894)\n[PASS] test_collectionErc721Edges() (gas: 1436052)\n[PASS] test_constructorsDoNotCallDependencies() (gas: 36654)\n[PASS] test_constructorsRejectZeroDependencies() (gas: 4550)\n[PASS] test_curationEdges() (gas: 780836)\n[PASS] test_defaultSplit_agentHouseBurn() (gas: 381579)\n[PASS] test_mintWithIMD_falseReturnRejected() (gas: 2073855)\n[PASS] test_mintWithIMD_feeOnTransferRejected() (gas: 2297085)\n[PASS] test_mintWithIMD_stalePriceRejected() (gas: 1250853)\n[PASS] test_mintZeroPricesReject() (gas: 943137)\n[PASS] test_moduleCollectionsHaveNoPlainCuration() (gas: 376256)\n[PASS] test_pendingOwnerHasNoPowerBeforeAccepting() (gas: 197527)\n[PASS] test_registerModuleCollectionTwiceReverts() (gas: 44789)\n[PASS] test_revokedBrokerKeepsEarnedBalance_butEarnsNoMore() (gas: 1291624)\n[PASS] test_sealEmptyCollectionRevertsAndSealIsOnce() (gas: 657864)\n[PASS] test_splitExtremes() (gas: 1284500)\n[PASS] test_submissionEdges() (gas: 246348)\n[PASS] test_updatePieceAccessEdges() (gas: 1976561)\n[PASS] test_withdrawToRevertingPayoutKeepsBalance() (gas: 1372032)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 168.34ms (248.92ms CPU time)\n\nRan 5 tests for test/invariants/BuybackConservation.t.sol:BuybackConservationTest\n[PASS]\nBuybackConservationTest invariants:\n[PASS] invariant_ethGoesOnlyToPool\n[PASS] invariant_imdGoesOnlyToBurnDestination\n BuybackConservationTest invariants (runs: 96, calls: 6144, reverts: 0)\n\n╭----------------------------+----------------------+-------+---------+----------╮\n| Contract                   | Selector             | Calls | Reverts | Discards |\n+================================================================================+\n| BuybackConservationHandler | advanceTime          | 656   | 0       | 0        |\n|----------------------------+----------------------+-------+---------+----------|\n| BuybackConservationHandler | burnIMD              | 678   | 0       | 0        |\n|----------------------------+----------------------+-------+---------+----------|\n| BuybackConservationHandler | curatorSwap          | 702   | 0       | 0        |\n|----------------------------+----------------------+-------+---------+----------|\n| BuybackConservationHandler | donateETH            | 679   | 0       | 0        |\n|----------------------------+----------------------+-------+---------+----------|\n| BuybackConservationHandler | donateIMD            | 715   | 0       | 0        |\n|----------------------------+----------------------+-------+---------+----------|\n| BuybackConservationHandler | handover             | 687   | 0       | 0        |\n|----------------------------+----------------------+-------+---------+----------|\n| BuybackConservationHandler | publicSwap           | 711   | 0       | 0        |\n|----------------------------+----------------------+-------+---------+----------|\n| BuybackConservationHandler | rejectedSwap         | 646   | 0       | 0        |\n|----------------------------+----------------------+-------+---------+----------|\n| BuybackConservationHandler | unauthorizedCallback | 670   | 0       | 0        |\n╰----------------------------+----------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 6431\n  Bound result 11099\n  Bound result 11033\n  Bound result 254\n  Bound result 8575\n  Bound result 3389\n  Bound result 5313\n  Bound result 15\n  Bound result 8178\n  Bound result 128\n  Bound result 281\n  Bound result 1282\n  Bound result 756\n  Bound result 523\n  Bound result 2863\n  Bound result 55730866537662525194199\n  Bound result 85\n  Bound result 6562\n  Bound result 4834\n\n[PASS] testFuzz_fundingBurnRoundTrip(uint96,uint96) (runs: 1000, μ: 645486, ~: 645550)\nLogs:\n  Bound result 4264337593543950335\n  Bound result 62514264337593543950335\n\n[PASS] test_failedCuratorSwapDoesNotPostponePublicLiveness() (gas: 896798)\nLogs:\n  Bound result 1000000000000000000\n  Bound result 3\n\n[PASS] test_oneWeiSwapAndDirectBurnConserveFunds() (gas: 603515)\nLogs:\n  Bound result 1\n  Bound result 1\n\n[PASS] test_publicSwapDrainsRemainderBelowTheDailyCap() (gas: 334842)\nLogs:\n  Bound result 1\n\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 674.48ms (746.42ms CPU time)\n\nRan 12 tests for test/Source.t.sol:ArtifactsSourceTest\n[PASS] testFuzz_revealOpensTheSealedSeed(bytes32,bytes32) (runs: 64, μ: 5893756, ~: 5893838)\n[PASS] test_auctionNeedsTheHouseToAcceptTheSale() (gas: 3285282)\n[PASS] test_auctionNeedsTheSourceLocked() (gas: 620659)\n[PASS] test_auctionReopensWhenNoBids() (gas: 441150)\n[PASS] test_auctionRules() (gas: 6733129)\n[PASS] test_bidReentrancyAndRefundPull() (gas: 767944)\n[PASS] test_deliverKeyOnceToTheWinner() (gas: 9241958)\n[PASS] test_noRevealWhileABuyerIsInEscrow() (gas: 9012360)\n[PASS] test_revealServesTheRendererWithItsSeed() (gas: 512490433)\nLogs:\n  revealed tokenURI gas: 2897251\n\n[PASS] test_revealTakesDownAListingWithNoBuyer() (gas: 8943770)\n[PASS] test_storedSeedIsSealed() (gas: 8734200)\n[PASS] test_tinyBidsMustStrictlyExceed() (gas: 940816)\nSuite result: ok. 12 passed; 0 failed; 0 skipped; finished in 720.46ms (719.24ms CPU time)\n\nRan 11 tests for test/ReviewRound4.t.sol:ReviewRound4Test\n[PASS] testFuzz_gateViewsNeverRevert(address,address,address) (runs: 64, μ: 147459, ~: 147548)\n[PASS] testFuzz_theFallbackResultStandsAgainstAnyLateWord(uint256,bytes32) (runs: 64, μ: 61602117, ~: 61602110)\n[PASS] test_aDeadFallbackDrawCanBeRerequested() (gas: 62342387)\n[PASS] test_aLiveFallbackDrawStillCannotBeRerequested() (gas: 61855098)\n[PASS] test_gateSeats_dirtyOwnerWord_isNotHeld() (gas: 61073739)\n[PASS] test_gateSeats_noCode_isNotHeld() (gas: 61538697)\n[PASS] test_gateSeats_withCode_unchanged() (gas: 61870940)\n[PASS] test_gateToken_noCode_isNotHeld_andMembersStillBuy() (gas: 62065872)\n[PASS] test_noChainlinkAnswerOnceTheFallbackHashIsPublic() (gas: 61639787)\n[PASS] test_noFallbackOnARequestChainlinkMayStillAnswer() (gas: 61638100)\n[PASS] test_source_gateNoCode_bidsRefusedNotReverted_membersBid() (gas: 998508)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 860.89ms (999.89ms CPU time)\n\nRan 1 test for test/invariants/SourceAuctionInvariant.t.sol:SourceAuctionInvariantTest\n[PASS]\nSourceAuctionInvariantTest invariants:\n[PASS] invariant_auctionConservation\n[PASS] invariant_highBidMonotone\n[PASS] invariant_settlementIsFinal\n SourceAuctionInvariantTest invariants (runs: 96, calls: 5760, reverts: 0)\n\n╭----------------+--------------------+-------+---------+----------╮\n| Contract       | Selector           | Calls | Reverts | Discards |\n+==================================================================+\n| AuctionHandler | bid                | 851   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | payloadStaysLocked | 829   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | recordHigh         | 828   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | setAuction         | 794   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | settle             | 834   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | warp               | 852   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | withdrawRefund     | 772   | 0       | 0        |\n╰----------------+--------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 694\n  Bound result 1583096506078419801\n  Bound result 437\n  Bound result 1323\n  Bound result 2000000000000000243\n  Bound result 1800\n  Bound result 4000000000000022905\n  Bound result 735\n  Bound result 1400\n  Bound result 3512\n  Bound result 4000000000000000405\n  Bound result 458\n  Bound result 1132\n  Bound result 4000000000000000257\n  Bound result 1615\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 894.00ms (890.18ms CPU time)\n\nRan 15 tests for test/LaunchAudit.t.sol:LaunchAuditTest\n[PASS] testFuzz_memberReplyMustBeExactlyOneWord(uint16,uint256,uint256) (runs: 64, μ: 433460, ~: 434893)\nLogs:\n  Bound result 1100000000000000000\n\n[PASS] test_attackerCannotInitializeCollectionAsRealHouse() (gas: 1082634)\n[PASS] test_attackerCannotInitializePieceAsRealFactory() (gas: 5034126)\n[PASS] test_attackerCannotInitializePieceAsRealSource() (gas: 5024422)\n[PASS] test_brokenBrokerPassDoesNotBlockEditionPurchase() (gas: 61675694)\n[PASS] test_brokenBrokerPassDoesNotBlockSourceSettlement() (gas: 19657183)\n[PASS] test_brokenPassDoesNotBlockPlainMintsInEitherCurrency() (gas: 2535075)\n[PASS] test_brokerPassMalformedRepliesCountAsIneligible() (gas: 934454)\n[PASS] test_claimedEditionsAreIndependentRuntimesAndStorage() (gas: 104039931)\n[PASS] test_dynamicMemberReplyCannotBypassEditionWindow() (gas: 61590217)\n[PASS] test_dynamicMemberReplyCannotBypassSourceWindow() (gas: 676729)\n[PASS] test_initializerRejectsEOAController() (gas: 6086143)\n[PASS] test_keyPostEventUnchangedBeforeAndAfterClaim() (gas: 67265577)\n[PASS] test_ownerCanClosePrimarySaleAndChangePendingAuctionSplit() (gas: 73214403)\n[PASS] test_plainCollectionIsIndependentRuntime() (gas: 4127353)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 1.07s (218.56ms CPU time)\n\nRan 16 tests for test/Artifacts.t.sol:ArtifactsFactoryTest\n[PASS] test_buyFailures() (gas: 60997239)\n[PASS] test_buyMany_cannotPassSupply() (gas: 98935498)\n[PASS] test_buyMany_fivePerWallet() (gas: 63860710)\n[PASS] test_buyRecordsSaleAndAssignsEveryEditionOnce() (gas: 178065420)\n[PASS] test_claimFlow_andFailures() (gas: 67458014)\n[PASS] test_postWrappedKeysInOneBatch() (gas: 67755786)\n[PASS] test_publishAndLock_accessAndFailures() (gas: 60947985)\n[PASS] test_rerequestAtOnceWhenTheCoordinatorAnsweredButTheCallbackFailed() (gas: 61875354)\n[PASS] test_rerequestRandomnessAfterDroppedRequest() (gas: 62033982)\n[PASS] test_saleControl() (gas: 61043179)\n[PASS] test_sealTokenURIMatchesR8Frame() (gas: 970414031)\n[PASS] test_viewingKeyZeroRejected() (gas: 33301)\n[PASS] test_vrfCallbackCannotBeReplayed() (gas: 61629805)\n[PASS] test_vrfCallbackGasIsTheCuratorsToTune() (gas: 61431482)\n[PASS] test_vrfCorrectableUntilTheSaleOpens_thenLockedForever() (gas: 62248774)\n[PASS] test_vrfMustBeConfiguredBeforeSelling() (gas: 46850)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 1.27s (1.54s CPU time)\n\nRan 1 test for test/invariants/PieceEscrowInvariant.t.sol:PieceEscrowInvariantTest\n[PASS]\nPieceEscrowInvariantTest invariants:\n[PASS] invariant_escrowConservation\n[PASS] invariant_escrowSellerOwns\n[PASS] invariant_royaltyAndIdentity\n[PASS] invariant_singleToken\n PieceEscrowInvariantTest invariants (runs: 96, calls: 5760, reverts: 0)\n\n╭---------------+--------------------+-------+---------+----------╮\n| Contract      | Selector           | Calls | Reverts | Discards |\n+=================================================================+\n| EscrowHandler | approveAndTransfer | 387   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | buy                | 370   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | cancel             | 387   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | delist             | 402   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | list               | 390   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | postKey            | 413   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | proveFake          | 367   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | refundBuyer        | 354   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | registerKey        | 387   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | release            | 391   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | rewrap             | 402   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | transfer           | 407   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | warp               | 366   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | withdraw           | 355   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | withdrawRoyalty    | 382   | 0       | 0        |\n╰---------------+--------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 17083\n  Bound result 24000\n  Bound result 735\n  Bound result 20337108042\n  Bound result 111059\n  Bound result 34646\n  Bound result 4039\n  Bound result 48879\n  Bound result 20880797823880349362\n  Bound result 86400\n  Bound result 15078\n  Bound result 41\n  Bound result 47915958131739435369\n  Bound result 6827\n  Bound result 3811\n  Bound result 149144\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.45s (1.40s CPU time)\n\nRan 1 test for test/invariants/ArtifactsFactoryInvariant.t.sol:ArtifactsFactoryInvariantTest\n[PASS]\nArtifactsFactoryInvariantTest invariants:\n[PASS] invariant_claimedPiecesBelongToBuyers\n[PASS] invariant_counts\n[PASS] invariant_ledgerHoldsEveryPurchase\n[PASS] invariant_lockedAndPriced\n[PASS] invariant_walletLimit\n ArtifactsFactoryInvariantTest invariants (runs: 96, calls: 5760, reverts: 0)\n\n╭----------------+-------------------+-------+---------+----------╮\n| Contract       | Selector          | Calls | Reverts | Discards |\n+=================================================================+\n| FactoryHandler | buy               | 534   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | buyMany           | 495   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | claim             | 552   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | fulfil            | 497   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | lockedForever     | 508   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | replay            | 536   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | rerequest         | 507   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | setPrice          | 494   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | strangerFulfil    | 564   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | strangerRerequest | 534   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | toggleSale        | 539   | 0       | 0        |\n╰----------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 338193125\n  Bound result 51638143296626\n  Bound result 0\n  Bound result 2574237282764180103\n  Bound result 4264337593543950335\n  Bound result 4\n  Bound result 5\n  Bound result 7\n  Bound result 1\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.62s (1.55s CPU time)\n\nRan 3 tests for test/invariants/FallbackDrawInvariant.t.sol:FallbackDrawInvariantTest\n[PASS]\nFallbackDrawInvariantTest invariants:\n[PASS] invariant_everyPurchaseOneEdition\n[PASS] invariant_oneFallbackAtATime\n[PASS] invariant_paymentsUntouched\n[PASS] invariant_retiredIdsStayDead\n FallbackDrawInvariantTest invariants (runs: 96, calls: 6144, reverts: 0)\n\n╭---------------------+------------------------+-------+---------+----------╮\n| Contract            | Selector               | Calls | Reverts | Discards |\n+===========================================================================+\n| FallbackDrawHandler | answer                 | 618   | 0       | 0        |\n|---------------------+------------------------+-------+---------+----------|\n| FallbackDrawHandler | buy                    | 601   | 0       | 0        |\n|---------------------+------------------------+-------+---------+----------|\n| FallbackDrawHandler | failedCallback         | 613   | 0       | 0        |\n|---------------------+------------------------+-------+---------+----------|\n| FallbackDrawHandler | finishFallback         | 682   | 0       | 0        |\n|---------------------+------------------------+-------+---------+----------|\n| FallbackDrawHandler | finishSettledOrRetired | 629   | 0       | 0        |\n|---------------------+------------------------+-------+---------+----------|\n| FallbackDrawHandler | lateAnswerToRetired    | 635   | 0       | 0        |\n|---------------------+------------------------+-------+---------+----------|\n| FallbackDrawHandler | rerequest              | 601   | 0       | 0        |\n|---------------------+------------------------+-------+---------+----------|\n| FallbackDrawHandler | roll                   | 577   | 0       | 0        |\n|---------------------+------------------------+-------+---------+----------|\n| FallbackDrawHandler | startFallback          | 600   | 0       | 0        |\n|---------------------+------------------------+-------+---------+----------|\n| FallbackDrawHandler | strangerRerequest      | 588   | 0       | 0        |\n╰---------------------+------------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 5\n  Bound result 2\n  Bound result 33\n  Bound result 6\n  Bound result 43\n  Bound result 1\n  Bound result 3\n\n[PASS] test_deadFallbackIsClearedByARerequest() (gas: 1953077)\nLogs:\n  Bound result 1\n  Bound result 0\n  Bound result 0\n\n[PASS] test_fallbackRouteIsReachable() (gas: 1625757)\nLogs:\n  Bound result 1\n  Bound result 0\n  Bound result 0\n\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 2.64s (2.60s CPU time)\n\nRan 1 test for test/invariants/ArtHouseInvariant.t.sol:ArtHouseInvariantTest\n[PASS]\nArtHouseInvariantTest invariants:\n[PASS] invariant_constants\n[PASS] invariant_ethConservation\n[PASS] invariant_imdConservation\n[PASS] invariant_noOverWithdrawal\n[PASS] invariant_supplyAndSeal\n ArtHouseInvariantTest invariants (runs: 128, calls: 5120, reverts: 0)\n\n╭---------------+----------------+-------+---------+----------╮\n| Contract      | Selector       | Calls | Reverts | Discards |\n+=============================================================+\n| LedgerHandler | handOver       | 380   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | mintETH        | 369   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | mintIMD        | 414   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | moduleSale     | 377   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | releaseBuyback | 413   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setBroker      | 396   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setPayout      | 404   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setPrices      | 429   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setSaleOpen    | 378   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setSplit       | 413   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | strangerCalls  | 361   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | withdraw       | 377   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | withdrawHouse  | 409   | 0       | 0        |\n╰---------------+----------------+-------+---------+----------╯\n\nLogs:\n  Bound result 18882627285399\n  Bound result 685\n  Bound result 1776\n  Bound result 98065623860081674297\n  Bound result 128\n  Bound result 64\n  Bound result 244\n  Bound result 1074\n  Bound result 5431\n  Bound result 3805\n  Bound result 70\n  Bound result 24000\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.39s (3.38s CPU time)\n\nRan 4 tests for test/invariants/BrokerClaimsInvariant.t.sol:BrokerClaimsInvariantTest\n[PASS]\nBrokerClaimsInvariantTest invariants:\n[PASS] invariant_claimHistorySurvivesTransfers\n[PASS] invariant_ownershipBalancesAndBrokerRightsAgree\n BrokerClaimsInvariantTest invariants (runs: 96, calls: 6144, reverts: 0)\n\n╭---------------------+------------------+-------+---------+----------╮\n| Contract            | Selector         | Calls | Reverts | Discards |\n+=====================================================================+\n| BrokerClaimsHandler | advanceTime      | 914   | 0       | 0        |\n|---------------------+------------------+-------+---------+----------|\n| BrokerClaimsHandler | claimPiece       | 861   | 0       | 0        |\n|---------------------+------------------+-------+---------+----------|\n| BrokerClaimsHandler | claimSeat        | 869   | 0       | 0        |\n|---------------------+------------------+-------+---------+----------|\n| BrokerClaimsHandler | movePass         | 871   | 0       | 0        |\n|---------------------+------------------+-------+---------+----------|\n| BrokerClaimsHandler | movePiece        | 845   | 0       | 0        |\n|---------------------+------------------+-------+---------+----------|\n| BrokerClaimsHandler | moveSeat         | 891   | 0       | 0        |\n|---------------------+------------------+-------+---------+----------|\n| BrokerClaimsHandler | rejectedTransfer | 893   | 0       | 0        |\n╰---------------------+------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 592\n  Bound result 9066\n  Bound result 17064\n  Bound result 12800\n  Bound result 34494\n  Bound result 67363\n  Bound result 512\n  Bound result 72203\n  Bound result 13215\n  Bound result 2862\n\n[PASS] test_seatAndPassTransfersDoNotResetEitherClaimLimit() (gas: 1553655)\n[PASS] test_sourceClaimAlsoConsumesTheWalletsSeatEntitlement() (gas: 1137627)\n[PASS] test_startIsInclusiveAndClosedClaimsLeaveNoHistory() (gas: 1893855)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 3.75s (3.70s CPU time)\n\nRan 3 tests for test/invariants/ReviewHistoryInvariant.t.sol:ReviewHistoryInvariantTest\n[PASS]\nReviewHistoryInvariantTest invariants:\n[PASS] invariant_pagesKeepFirstReviewOrderAndLatestContents\n[PASS] invariant_thesisCountsDistinctAuthorsWithoutGrantingBrokerPowers\n[PASS] invariant_votesArePerCredentialAndFinalDecisionsFreezeRecords\n ReviewHistoryInvariantTest invariants (runs: 96, calls: 6144, reverts: 0)\n\n╭----------------------+---------------+-------+---------+----------╮\n| Contract             | Selector      | Calls | Reverts | Discards |\n+===================================================================+\n| ReviewHistoryHandler | advanceTime   | 1002  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| ReviewHistoryHandler | decide        | 963   | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| ReviewHistoryHandler | invalidReview | 1031  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| ReviewHistoryHandler | moveSeat      | 1013  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| ReviewHistoryHandler | review        | 1084  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| ReviewHistoryHandler | thesis        | 1051  | 0       | 0        |\n╰----------------------+---------------+-------+---------+----------╯\n\nLogs:\n  Bound result 29\n  Bound result 14564\n  Bound result 2762\n  Bound result 2026479\n  Bound result 4\n  Bound result 2050138\n  Bound result 4660\n\n[PASS] test_finalDecisionsFreezeOldAndNewHolderReviews() (gas: 1951545)\n[PASS] test_transferredSeatEditsOneExistingVoiceInPlace() (gas: 1175361)\nLogs:\n  Bound result 1\n\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 5.51s (5.50s CPU time)\n\nRan 25 tests for test/NothingStuck.t.sol:NothingStuckTest\n[PASS] test_aBuyerNeedsAViewingKeyAProofCanUse() (gas: 67200269)\n[PASS] test_aJunkKeyIsProvenFake_paymentAndDepositToTheBuyer() (gas: 67784555)\n[PASS] test_aSilentSellerLetsTheBuyerCancelAfter24Hours() (gas: 67371726)\n[PASS] test_anAuctionClosedInTimeCannotBeVoided() (gas: 5846482)\n[PASS] test_anAuctionNobodyCanCloseGivesTheBidBack() (gas: 6134344)\n[PASS] test_callbackGasCanOnlyGoUpOnceTheSaleOpens() (gas: 60960821)\n[PASS] test_claimWithoutAKey_after30Days_thenTheKeyGoesIntoThePiece() (gas: 67152172)\n[PASS] test_curatorReKeysAPieceItsPreviousOwnerNeverDid() (gas: 67308328)\n[PASS] test_fallbackDraw_aStartedDrawsResultStands_finishedFromTheHistory() (gas: 61896434)\n[PASS] test_fallbackDraw_chainlinkStillWinsIfItAnswersFirst() (gas: 61650523)\n[PASS] test_fallbackDraw_countsFromThePurchase() (gas: 61827139)\n[PASS] test_fallbackDraw_oneAtATime() (gas: 62775290)\n[PASS] test_fallbackDraw_onlyAfterThreeDays_fromABlockNobodyKnew() (gas: 61810020)\n[PASS] test_fallbackDraw_startsAgainOnlyOnceItsHashIsGone() (gas: 61653096)\n[PASS] test_fallbackDraw_startsOnAYoungRequestTheCoordinatorNoLongerHolds() (gas: 61625047)\n[PASS] test_noProofBeforeAKey_andTheSellerCantDodgeOne() (gas: 67731873)\n[PASS] test_onlyAKeyTheSellerMadeCanBePosted() (gas: 67793456)\n[PASS] test_realKeys_aJunkKeyIsProvenFake() (gas: 907133)\nLogs:\n  gas for the buyer's proveFakeKey: 170130\n\n[PASS] test_realKeys_anHonestKeyCanNeverBeProvenFake() (gas: 1254953)\n[PASS] test_realKeys_theBuyerCantSwapViewingKeysToFrameTheSeller() (gas: 888070)\n[PASS] test_realKeys_theRightKeyWrappedToAnotherKeyIsFake() (gas: 894751)\n[PASS] test_the72HoursCountFromTheKey() (gas: 67793086)\n[PASS] test_theBuyerCantCancelUnderAPendingKey() (gas: 67568079)\n[PASS] test_theDepositIsExactly10Percent() (gas: 67672385)\n[PASS] test_theSellerCanRefundBeforeSendingAKey() (gas: 67479161)\nSuite result: ok. 25 passed; 0 failed; 0 skipped; finished in 9.50s (330.78ms CPU time)\n\nRan 13 tests for test/Adversarial.t.sol:ArtifactsEdgeTest\n[PASS] testFuzz_anyWordsAssignDistinctEditions(uint256[8]) (runs: 256, μ: 64664928, ~: 64666797)\n[PASS] testFuzz_sealFramesAnyTraits(uint8,uint8,uint8,uint8,uint8) (runs: 16, μ: 519806543, ~: 519805845)\nLogs:\n  Bound result 7\n\n[PASS] test_buyRevertsAtomicallyWhenCoordinatorReverts() (gas: 59197366)\n[PASS] test_callbackWithNoWordsReverts() (gas: 61551984)\n[PASS] test_claimedPieceIsAFullCopyOfTheImplementation() (gas: 67249308)\n[PASS] test_configureVRFRejectsZeroes() (gas: 211437)\n[PASS] test_duplicateRequestIdRejected() (gas: 59391685)\n[PASS] test_nonOwnerCannotRunTheSale() (gas: 60818098)\n[PASS] test_rerequestIsAtomicWhenCoordinatorReverts() (gas: 59885766)\n[PASS] test_rerequestWindowBoundaryAndChaining() (gas: 67823748)\n[PASS] test_setPieceEdges() (gas: 61051490)\n[PASS] test_unapprovedBuyerAsBrokerEarnsNothing_andOneWeiPriceWorks() (gas: 61489495)\n[PASS] test_wrappedKeyEdges() (gas: 67231974)\nSuite result: ok. 13 passed; 0 failed; 0 skipped; finished in 9.50s (10.64s CPU time)\n\nRan 34 test suites in 9.50s (44.26s CPU time): 259 tests passed, 0 failed, 2 skipped (261 total tests)\n","passed":true},{"durationMs":112,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"ArtCollection.approve(address,uint256)\",\"ArtCollection.initialize(address,string,string)\",\"ArtCollection.mint(address,uint256)\",\"ArtCollection.safeTransferFrom(address,address,uint256)\",\"ArtCollection.safeTransferFrom(address,address,uint256,bytes)\",\"ArtCollection.setApprovalForAll(address,bool)\",\"ArtCollection.transferFrom(address,address,uint256)\",\"ArtHouse.acceptOwnership()\",\"ArtHouse.approveArtist(address,string)\",\"ArtHouse.clearPiece(address,uint256)\",\"ArtHouse.createCollection(string,string,address)\",\"ArtHouse.decideSubmission(uint256,bool)\",\"ArtHouse.finalizePiece(address,uint256)\",\"ArtHouse.mint(address,uint256,address)\",\"ArtHouse.mintWithIMD(address,uint256,address,uint256)\",\"ArtHouse.recordResale(address,uint256,uint256)\",\"ArtHouse.recordSale(address,address,address)\",\"ArtHouse.registerModuleCollection(address,address)\",\"ArtHouse.registerPiece(address,uint256,bytes32,string,string)\",\"ArtHouse.releaseBuyback(address)\",\"ArtHouse.revokeArtist(address)\",\"ArtHouse.sealCollection(address)\",\"ArtHouse.setBroker(address,bool)\",\"ArtHouse.setBrokerPass(address)\",\"ArtHouse.setBuybackBurner(address)\",\"ArtHouse.setPayout(address)\",\"ArtHouse.setPrices(address,uint256,uint256)\",\"ArtHouse.setSaleModule(address,bool)\",\"ArtHouse.setSaleOpen(address,bool)\",\"ArtHouse.setSplit(address,uint16,uint16,uint16,uint16)\",\"ArtHouse.submit(bytes32,string)\",\"ArtHouse.transferOwnership(address)\",\"ArtHouse.updatePiece(address,uint256,bytes32,string,string)\",\"ArtHouse.uploadChunk(address,uint256,uint256,bytes)\",\"ArtHouse.withdraw(address)\",\"ArtHouse.withdrawHouse(address)\",\"ArtStorage.acceptOwnership()\",\"ArtStorage.clear(address,uint256)\",\"ArtStorage.setHouse(address)\",\"ArtStorage.transferOwnership(address)\",\"ArtStorage.write(address,uint256,uint256,bytes)\",\"ArtifactsFactory.acceptOwnership()\",\"ArtifactsFactory.buy(address)\",\"ArtifactsFactory.buyMany(uint256,address)\",\"ArtifactsFactory.buyWithSeat(uint256,uint256,address)\",\"ArtifactsFactory.claim(uint256)\",\"ArtifactsFactory.claimMany(uint256[])\",\"ArtifactsFactory.configureVRF(address,bytes32,uint256,bool)\",\"ArtifactsFactory.endSale()\",\"ArtifactsFactory.finishFallbackDraw(uint256)\",\"ArtifactsFactory.lock()\",\"ArtifactsFactory.postWrappedKey(uint256,bytes)\",\"ArtifactsFactory.postWrappedKeys(uint256[],bytes[])\",\"ArtifactsFactory.rawFulfillRandomWords(uint256,uint256[])\",\"ArtifactsFactory.registerViewingKey(bytes32)\",\"ArtifactsFactory.rerequestRandomness(uint256)\",\"ArtifactsFactory.setGate(address,address,uint256,uint64)\",\"ArtifactsFactory.setMemberGate(address,bytes4,uint256)\",\"ArtifactsFactory.setMintPhases(uint64,uint8,uint64,uint8)\",\"ArtifactsFactory.setPiece(uint256,(string,string,uint8,string),bytes,bytes32)\",\"ArtifactsFactory.setPrice(uint256)\",\"ArtifactsFactory.setSaleOpen(bool)\",\"ArtifactsFactory.setVRFCallbackGas(uint32)\",\"ArtifactsFactory.startFallbackDraw(uint256)\",\"ArtifactsFactory.transferOwnership(address)\",\"ArtifactsPiece.approve(address,uint256)\",\"ArtifactsPiece.buy(bytes32,address)\",\"ArtifactsPiece.cancel()\",\"ArtifactsPiece.delist()\",\"ArtifactsPiece.initialize(address,address,uint256,address,(string,string,uint8,string),address,bytes32,bytes,bool,bytes32)\",\"ArtifactsPiece.list(uint256)\",\"ArtifactsPiece.postEscrowKey(bytes,address,uint256)\",\"ArtifactsPiece.proveFakeKey((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256))\",\"ArtifactsPiece.refundBuyer()\",\"ArtifactsPiece.registerViewingKey(bytes32)\",\"ArtifactsPiece.release()\",\"ArtifactsPiece.reveal(bytes32)\",\"ArtifactsPiece.rewrapFor(bytes)\",\"ArtifactsPiece.safeTransferFrom(address,address,uint256)\",\"ArtifactsPiece.safeTransferFrom(address,address,uint256,bytes)\",\"ArtifactsPiece.setApprovalForAll(address,bool)\",\"ArtifactsPiece.transferFrom(address,address,uint256)\",\"ArtifactsPiece.withdraw()\",\"ArtifactsSource.acceptOwnership()\",\"ArtifactsSource.bid(address)\",\"ArtifactsSource.deliverKey(bytes)\",\"ArtifactsSource.lock(bytes32,bytes32)\",\"ArtifactsSource.resetRenderer()\",\"ArtifactsSource.setAuction(uint256,uint64)\",\"ArtifactsSource.setGate(address,address,uint256,uint64)\",\"ArtifactsSource.setMemberGate(address,bytes4,uint256)\",\"ArtifactsSource.settle()\",\"ArtifactsSource.storeRendererChunk(bytes)\",\"ArtifactsSource.transferOwnership(address)\",\"ArtifactsSource.voidUnsettled()\",\"ArtifactsSource.withdrawRefund()\",\"BrokerPass.approve(address,uint256)\",\"BrokerPass.claimWithPiece(uint256)\",\"BrokerPass.claimWithSeat(uint256)\",\"BrokerPass.safeTransferFrom(address,address,uint256)\",\"BrokerPass.safeTransferFrom(address,address,uint256,bytes)\",\"BrokerPass.setApprovalForAll(address,bool)\",\"BrokerPass.setClaimsOpenAt(uint64)\",\"BrokerPass.transferFrom(address,address,uint256)\",\"ImdBuybackBurner.burnEth(uint256,uint256,uint256)\",\"ImdBuybackBurner.burnImd()\",\"ImdBuybackBurner.receive()\",\"ImdBuybackBurner.unlockCallback(bytes)\",\"SubmissionReviews.applyAsBroker(string)\",\"SubmissionReviews.postThesis(uint256,string)\",\"SubmissionReviews.reviewAsPiece(uint256,uint256,uint8,string)\",\"SubmissionReviews.reviewAsSeat(uint256,uint256,uint8,string)\"],\"files\":{\".gitignore\":3,\"ADAPTATION.md\":356,\"README.md\":272,\"foundry.toml\":25,\"launch.burner.json\":17,\"launch.json\":63,\"reference/PROTOCOL.md\":99,\"reference/RULES.md\":137,\"reference/audit/V13Audit.t.sol.txt\":381,\"reference/check-framed.js\":25,\"reference/framed/framed-003.svg\":1,\"reference/framed/framed-MASTER.svg\":1,\"reference/rules.js\":145,\"reference/the-source.renderer.html\":148,\"remappings.txt\":1,\"script/Deploy.s.sol\":39,\"src/ArtCollection.sol\":55,\"src/ArtHouse.sol\":609,\"src/ArtStorage.sol\":82,\"src/ArtifactsFactory.sol\":635,\"src/ArtifactsPiece.sol\":457,\"src/ArtifactsSource.sol\":271,\"src/BrokerPass.sol\":142,\"src/ImdBuybackBurner.sol\":163,\"src/KeyProof.sol\":154,\"src/SubmissionReviews.sol\":215,\"src/base/ERC721Lite.sol\":122,\"src/base/HolderGate.sol\":113,\"src/base/ReentrancyGuard.sol\":15,\"src/base/TwoStepOwnable.sol\":40,\"src/interfaces/Interfaces.sol\":93,\"src/libs/Clones.sol\":19,\"src/libs/Encoding.sol\":79,\"src/libs/SSTORE2.sol\":41,\"src/libs/Seal.sol\":102,\"test/Adversarial.t.sol\":1409,\"test/ArtHouse.t.sol\":463,\"test/Artifacts.t.sol\":673,\"test/AuditRound3.t.sol\":151,\"test/BrokerPass.t.sol\":373,\"test/Burner.t.sol\":161,\"test/ClaimEnd.t.sol\":152,\"test/Fixture.sol\":230,\"test/Gate.t.sol\":295,\"test/KeyProof.t.sol\":134,\"test/LaunchAudit.t.sol\":338,\"test/LaunchDeployment.t.sol\":191,\"test/NothingStuck.t.sol\":594,\"test/Phases.t.sol\":130,\"test/ReviewRound4.t.sol\":262,\"test/Reviews.t.sol\":264,\"test/Source.t.sol\":396,\"test/audit/KeyProofEdges.t.sol\":178,\"test/audit/KeyReuseLeak.t.sol\":38,\"test/fixtures/keyproof.json\":81,\"test/fork/BurnerFork.t.sol\":70,\"test/fork/VrfFork.t.sol\":131,\"test/invariants/ADDED_COVERAGE.md\":24,\"test/invariants/ArtHouseInvariant.t.sol\":444,\"test/invariants/ArtifactsFactoryInvariant.t.sol\":323,\"test/invariants/BrokerClaimsInvariant.t.sol\":275,\"test/invariants/BuybackConservation.t.sol\":246,\"test/invariants/FallbackDrawInvariant.t.sol\":417,\"test/invariants/PieceEscrowInvariant.t.sol\":445,\"test/invariants/ReviewHistoryInvariant.t.sol\":245,\"test/invariants/SourceAuctionInvariant.t.sol\":227,\"test/mocks/AdversarialMocks.sol\":134,\"test/mocks/MockPoolManager.sol\":57,\"test/mocks/MockSeats.sol\":27,\"test/mocks/Mocks.sol\":149,\"test/mocks/TestVRFCoordinator.sol\":46,\"test/utils/Base64Decode.sol\":83},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"481b148423ba761f03abe9dc937e4142ffec48ff5e61c1eb177be34a87f8d778","verifiedTreeHash":"17188742c81b389631b024010e4802043ba618e3","verifierVersion":"0.1.0+a6ee6548"},{"checks":[{"durationMs":695309,"exitCode":0,"name":"build","output":"Compiling 69 files with Solc 0.8.26\nSolc 0.8.26 finished in 695.09s\nCompiler run successful with warnings:\nWarning (5667): Unused function parameter. Remove or comment out the variable name to silence this warning.\n   --> test/invariants/ArtHouseInvariant.t.sol:105:9:\n    |\n105 |         address buyer,\n    |         ^^^^^^^^^^^^^\n\n","passed":true},{"durationMs":19280,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/fork/BurnerFork.t.sol:BurnerForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 951.67µs (0.00ns CPU time)\n\nRan 1 test for test/fork/VrfFork.t.sol:VrfForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 1.49ms (0.00ns CPU time)\n\nRan 5 tests for test/audit/KeyProofEdges.t.sol:KeyProofEdgesTest\n[PASS] test_adversarialE_isProvable() (gas: 107849)\n[PASS] test_adversarialE_proofIsActuallyChecked() (gas: 23615)\n[PASS] test_negatedSCannotFrame() (gas: 60700)\n[PASS] test_oddYWrapThatOpensIsNotFake() (gas: 37558)\n[PASS] test_xEqualsN_isMalformed() (gas: 13218)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 3.73ms (4.99ms CPU time)\n\nRan 4 tests for test/AuditRound3.t.sol:AuditRound3Test\n[PASS] test_aReturnDataBombCostsThePayerNothing() (gas: 694152)\n[PASS] test_aShareThatWaitsInTheLedgerIsAnnounced() (gas: 339919)\n[PASS] test_theArtistsPayoutCantMoveThePieceDuringARelease() (gas: 415877)\n[PASS] test_theArtistsPayoutCantRelistDuringARelease() (gas: 600564)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 38.90ms (1.42ms CPU time)\n\nRan 7 tests for test/Burner.t.sol:BurnerTest\n[PASS] test_anyoneBurnsHeldImd() (gas: 169949)\n[PASS] test_anyoneSwapsInSmallStepsAfter60QuietDays() (gas: 845755)\n[PASS] test_constructorChecks() (gas: 8711)\n[PASS] test_editionSaleToBurnedImd() (gas: 61800771)\n[PASS] test_onlyTheCuratorSwaps_withAMinimumAndADeadline() (gas: 653639)\n[PASS] test_onlyThePoolManagerCallsBack() (gas: 32189)\n[PASS] test_theNewOwnerSwapsAfterAHandover() (gas: 304000)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 40.26ms (35.27ms CPU time)\n\nRan 4 tests for test/Phases.t.sol:PhasesTest\n[PASS] test_aSeatFollowsThePhases_whereverItGoes() (gas: 1747601)\n[PASS] test_afterTheWindow_anyoneUpToFive() (gas: 1042332)\n[PASS] test_capsRise_1_then_2_then_5_forAnImdHolder() (gas: 1740916)\n[PASS] test_setOnlyBeforeTheSaleOpens_andChecked() (gas: 322444)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 47.31ms (3.13ms CPU time)\n\nRan 1 test for test/audit/KeyReuseLeak.t.sol:KeyReuseLeakTest\n[PASS] test_copiedE_cantBePosted(uint256,uint256) (runs: 64, μ: 603053, ~: 603233)\nLogs:\n  Bound result 6677771717396745857438524715775791381032702405673290885595687978682\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 48.06ms (44.66ms CPU time)\n\nRan 5 tests for test/ClaimEnd.t.sol:ClaimEndTest\n[PASS] test_claimMany_claimsEveryOneInOneCall() (gas: 18158157)\n[PASS] test_claimMany_emptyRefused_andTheCuratorCanClaimForBuyers() (gas: 12316427)\n[PASS] test_claimMany_isAllOrNothing() (gas: 18212437)\n[PASS] test_endSale_isFinal() (gas: 6928373)\n[PASS] test_endSale_needsTheSaleToHaveOpened_andWorksWhileClosed() (gas: 96083)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 52.25ms (11.93ms CPU time)\n\nRan 10 tests for test/Artifacts.t.sol:ArtifactsPieceEscrowTest\n[PASS] test_escrowCancelBeforeKey_andDelist() (gas: 501042)\n[PASS] test_escrowHappyPath_buyerConfirms() (gas: 1181854)\n[PASS] test_escrowKeyMustNotBeEmpty() (gas: 310921)\n[PASS] test_escrowTimeoutRelease() (gas: 728994)\n[PASS] test_pieceViewingKeyZeroRejected() (gas: 168689)\n[PASS] test_plainTransferClearsKey_previousOwnerRekeys() (gas: 506819)\n[PASS] test_reentrancyOnEscrowWithdrawBlocked() (gas: 844317)\n[PASS] test_rewrapIsOneShotAndNonEmpty() (gas: 284134)\n[PASS] test_sellerCannotOverwriteKeyAfterRelease() (gas: 913301)\n[PASS] test_sourceOnlyReveal() (gas: 35552)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 69.01ms (7.46ms CPU time)\n\nRan 6 tests for test/Adversarial.t.sol:PieceEdgeTest\n[PASS] test_cancelThenSecondBuyerAndRoyaltyToChangedPayout() (gas: 1087998)\n[PASS] test_listingEdges() (gas: 1002975)\n[PASS] test_releaseAtExactly72HoursByStranger() (gas: 914016)\n[PASS] test_revealNeedsTheSourceLocked_andEmptyRendererURI() (gas: 6265659)\n[PASS] test_safeTransferReceivers() (gas: 670237)\n[PASS] test_transferAuthEdges() (gas: 350213)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 81.47ms (6.94ms CPU time)\n\nRan 8 tests for test/KeyProof.t.sol:KeyProofTest\n[PASS] test_aJunkKeyIsProvenFake() (gas: 369871)\nLogs:\n  gas to check a fake-key proof: 44805\n\n[PASS] test_aKeyThatOpensIsNeverProvenFake() (gas: 368087)\n[PASS] test_aProofOnlyHoldsForItsBuyerPieceAndChain() (gas: 416867)\n[PASS] test_aProofOnlyHoldsForItsOwnWrappedKey() (gas: 416275)\n[PASS] test_aTamperedProofFails() (gas: 768976)\n[PASS] test_madeUpBytesAndTheOldFormatAreFake() (gas: 690806)\n[PASS] test_theRightKeyForSomeoneElseIsProvenFake() (gas: 368314)\n[PASS] test_viewingKeys() (gas: 34725)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 86.78ms (28.06ms CPU time)\n\nRan 18 tests for test/BrokerPass.t.sol:BrokerPassTest\n[PASS] test_capIs100() (gas: 19752778)\n[PASS] test_claimWithPiece_onceEverPerPiece() (gas: 6682132)\n[PASS] test_claimWithSeat_onceEverPerSeat() (gas: 376003)\n[PASS] test_claimWithTheSource() (gas: 6010301)\n[PASS] test_claimsWaitForTheStartTime_setOnceByTheCurator() (gas: 489742)\n[PASS] test_oneClaimPerWallet() (gas: 6983032)\n[PASS] test_passHolderCanBrokerTheirOwnBuy() (gas: 1022212)\n[PASS] test_passHolderEarnsOnMint_andTheRightMovesWithThePass() (gas: 2088032)\n[PASS] test_recordResaleRejectsAnythingButAPiece() (gas: 298286)\n[PASS] test_resaleBrokerShare_creditedInTheLedger() (gas: 7297226)\n[PASS] test_resaleBuyerWithAPassCanBrokerTheirOwnBuy() (gas: 7234530)\n[PASS] test_resaleFallsBackToThePieceWhenTheLedgerRefuses() (gas: 7249631)\n[PASS] test_resaleSellerCannotBeBroker() (gas: 7147070)\n[PASS] test_resaleWithoutEligibleBroker_sellerKeepsTheShare() (gas: 6936228)\n[PASS] test_setBrokerPassOnce() (gas: 64999)\n[PASS] test_sourceSplit_brokerAndArtistOnly() (gas: 6162142)\n[PASS] test_sourceSplit_noBrokerBurns() (gas: 5919583)\n[PASS] test_tokenURIIsOnChainJson() (gas: 388848)\nSuite result: ok. 18 passed; 0 failed; 0 skipped; finished in 88.11ms (38.81ms CPU time)\n\nRan 1 test for test/ClaimEnd.t.sol:EndBeforeOpenTest\n[PASS] test_endSale_beforeOpening_refused() (gas: 60691353)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 90.80ms (63.18ms CPU time)\n\nRan 3 tests for test/Adversarial.t.sol:RuntimeTest\n[PASS] test_implementationsAreLocked() (gas: 104926)\n[PASS] test_launchedRuntimesAreBoundedAndHaveNoEscapeOpcodes() (gas: 60534514)\n[PASS] test_noRenounceAnywhere() (gas: 155507)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 165.42ms (161.35ms CPU time)\n\nRan 11 tests for test/Reviews.t.sol:ReviewsTest\n[PASS] testFuzz_tallyMatchesVoices(uint8[12]) (runs: 64, μ: 1444721, ~: 1442081)\n[PASS] test_aClaimedPieceIsAVoice_andAnUnclaimedOneIsNot() (gas: 67623877)\n[PASS] test_aMovedSeatStillHasOneVoice() (gas: 441792)\n[PASS] test_aSeatAndAPieceInOneWalletAreTwoVoices() (gas: 67348609)\n[PASS] test_anyoneAppliesToBeABroker() (gas: 224553)\n[PASS] test_anyonePublishesTheses() (gas: 810776)\n[PASS] test_changingAReviewMovesItsVote() (gas: 305393)\n[PASS] test_frozenOnceTheCuratorDecides_andAdvisoryOnly() (gas: 349039)\n[PASS] test_inputChecks() (gas: 307196)\n[PASS] test_onlyTheSeatHolderReviews() (gas: 97570)\n[PASS] test_seatsReview_andTheTallyFollows() (gas: 457095)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 166.29ms (154.71ms CPU time)\n\nRan 2 tests for test/LaunchDeployment.t.sol:LaunchDeploymentTest\n[PASS] test_allEightConstructorsAcceptCodeLessDependencies() (gas: 75369724)\n[PASS] test_manifestOrderAndOwnerConfigurationRemainIntact() (gas: 82003740)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 191.67ms (375.28ms CPU time)\n\nRan 15 tests for test/LaunchAudit.t.sol:LaunchAuditTest\n[PASS] testFuzz_memberReplyMustBeExactlyOneWord(uint16,uint256,uint256) (runs: 64, μ: 433298, ~: 434781)\nLogs:\n  Bound result 350000\n\n[PASS] test_attackerCannotInitializeCollectionAsRealHouse() (gas: 1082634)\n[PASS] test_attackerCannotInitializePieceAsRealFactory() (gas: 5034126)\n[PASS] test_attackerCannotInitializePieceAsRealSource() (gas: 5024422)\n[PASS] test_brokenBrokerPassDoesNotBlockEditionPurchase() (gas: 61675694)\n[PASS] test_brokenBrokerPassDoesNotBlockSourceSettlement() (gas: 19657183)\n[PASS] test_brokenPassDoesNotBlockPlainMintsInEitherCurrency() (gas: 2535075)\n[PASS] test_brokerPassMalformedRepliesCountAsIneligible() (gas: 934454)\n[PASS] test_claimedEditionsAreIndependentRuntimesAndStorage() (gas: 104039931)\n[PASS] test_dynamicMemberReplyCannotBypassEditionWindow() (gas: 61590217)\n[PASS] test_dynamicMemberReplyCannotBypassSourceWindow() (gas: 676729)\n[PASS] test_initializerRejectsEOAController() (gas: 6086143)\n[PASS] test_keyPostEventUnchangedBeforeAndAfterClaim() (gas: 67265577)\n[PASS] test_ownerCanClosePrimarySaleAndChangePendingAuctionSplit() (gas: 73214403)\n[PASS] test_plainCollectionIsIndependentRuntime() (gas: 4127353)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 267.15ms (451.79ms CPU time)\n\nRan 23 tests for test/Adversarial.t.sol:ArtHouseEdgeTest\n[PASS] testFuzz_everyoneWithdrawsExactlyTheirShare(uint96,uint96,uint96) (runs: 256, μ: 2048171, ~: 2051370)\nLogs:\n  Bound result 1687053956312409914\n  Bound result 29410530796336771647\n  Bound result 1215619572\n\n[PASS] testFuzz_splitConservesAndHouseTakesRounding(uint16,uint16,uint16,uint96,uint8) (runs: 512, μ: 260325, ~: 262826)\nLogs:\n  Bound result 178\n  Bound result 1952\n  Bound result 1953\n  Bound result 64378445814\n\n[PASS] test_artistEdges() (gas: 1210240)\n[PASS] test_buybackOnlyToTheBurnerSetOnce() (gas: 460935)\n[PASS] test_clearThenReuploadKeepsSizeAccounting() (gas: 40763894)\n[PASS] test_collectionErc721Edges() (gas: 1436052)\n[PASS] test_constructorsDoNotCallDependencies() (gas: 36654)\n[PASS] test_constructorsRejectZeroDependencies() (gas: 4550)\n[PASS] test_curationEdges() (gas: 780836)\n[PASS] test_defaultSplit_agentHouseBurn() (gas: 381579)\n[PASS] test_mintWithIMD_falseReturnRejected() (gas: 2073855)\n[PASS] test_mintWithIMD_feeOnTransferRejected() (gas: 2297085)\n[PASS] test_mintWithIMD_stalePriceRejected() (gas: 1250853)\n[PASS] test_mintZeroPricesReject() (gas: 943137)\n[PASS] test_moduleCollectionsHaveNoPlainCuration() (gas: 376256)\n[PASS] test_pendingOwnerHasNoPowerBeforeAccepting() (gas: 197527)\n[PASS] test_registerModuleCollectionTwiceReverts() (gas: 44789)\n[PASS] test_revokedBrokerKeepsEarnedBalance_butEarnsNoMore() (gas: 1291624)\n[PASS] test_sealEmptyCollectionRevertsAndSealIsOnce() (gas: 657864)\n[PASS] test_splitExtremes() (gas: 1284500)\n[PASS] test_submissionEdges() (gas: 246348)\n[PASS] test_updatePieceAccessEdges() (gas: 1976561)\n[PASS] test_withdrawToRevertingPayoutKeepsBalance() (gas: 1372032)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 279.47ms (413.59ms CPU time)\n\nRan 25 tests for test/NothingStuck.t.sol:NothingStuckTest\n[PASS] test_aBuyerNeedsAViewingKeyAProofCanUse() (gas: 67200269)\n[PASS] test_aJunkKeyIsProvenFake_paymentAndDepositToTheBuyer() (gas: 67784555)\n[PASS] test_aSilentSellerLetsTheBuyerCancelAfter24Hours() (gas: 67371726)\n[PASS] test_anAuctionClosedInTimeCannotBeVoided() (gas: 5846482)\n[PASS] test_anAuctionNobodyCanCloseGivesTheBidBack() (gas: 6134344)\n[PASS] test_callbackGasCanOnlyGoUpOnceTheSaleOpens() (gas: 60960821)\n[PASS] test_claimWithoutAKey_after30Days_thenTheKeyGoesIntoThePiece() (gas: 67152172)\n[PASS] test_curatorReKeysAPieceItsPreviousOwnerNeverDid() (gas: 67308328)\n[PASS] test_fallbackDraw_aStartedDrawsResultStands_finishedFromTheHistory() (gas: 61896434)\n[PASS] test_fallbackDraw_chainlinkStillWinsIfItAnswersFirst() (gas: 61650523)\n[PASS] test_fallbackDraw_countsFromThePurchase() (gas: 61827139)\n[PASS] test_fallbackDraw_oneAtATime() (gas: 62775290)\n[PASS] test_fallbackDraw_onlyAfterThreeDays_fromABlockNobodyKnew() (gas: 61810020)\n[PASS] test_fallbackDraw_startsAgainOnlyOnceItsHashIsGone() (gas: 61653096)\n[PASS] test_fallbackDraw_startsOnAYoungRequestTheCoordinatorNoLongerHolds() (gas: 61625047)\n[PASS] test_noProofBeforeAKey_andTheSellerCantDodgeOne() (gas: 67731873)\n[PASS] test_onlyAKeyTheSellerMadeCanBePosted() (gas: 67793456)\n[PASS] test_realKeys_aJunkKeyIsProvenFake() (gas: 907133)\nLogs:\n  gas for the buyer's proveFakeKey: 170130\n\n[PASS] test_realKeys_anHonestKeyCanNeverBeProvenFake() (gas: 1254953)\n[PASS] test_realKeys_theBuyerCantSwapViewingKeysToFrameTheSeller() (gas: 888070)\n[PASS] test_realKeys_theRightKeyWrappedToAnotherKeyIsFake() (gas: 894751)\n[PASS] test_the72HoursCountFromTheKey() (gas: 67793086)\n[PASS] test_theBuyerCantCancelUnderAPendingKey() (gas: 67568079)\n[PASS] test_theDepositIsExactly10Percent() (gas: 67672385)\n[PASS] test_theSellerCanRefundBeforeSendingAKey() (gas: 67479161)\nSuite result: ok. 25 passed; 0 failed; 0 skipped; finished in 466.85ms (953.47ms CPU time)\n\nRan 12 tests for test/Source.t.sol:ArtifactsSourceTest\n[PASS] testFuzz_revealOpensTheSealedSeed(bytes32,bytes32) (runs: 64, μ: 5893757, ~: 5893838)\n[PASS] test_auctionNeedsTheHouseToAcceptTheSale() (gas: 3285282)\n[PASS] test_auctionNeedsTheSourceLocked() (gas: 620659)\n[PASS] test_auctionReopensWhenNoBids() (gas: 441150)\n[PASS] test_auctionRules() (gas: 6733129)\n[PASS] test_bidReentrancyAndRefundPull() (gas: 767944)\n[PASS] test_deliverKeyOnceToTheWinner() (gas: 9241958)\n[PASS] test_noRevealWhileABuyerIsInEscrow() (gas: 9012360)\n[PASS] test_revealServesTheRendererWithItsSeed() (gas: 512490433)\nLogs:\n  revealed tokenURI gas: 2897251\n\n[PASS] test_revealTakesDownAListingWithNoBuyer() (gas: 8943770)\n[PASS] test_storedSeedIsSealed() (gas: 8734200)\n[PASS] test_tinyBidsMustStrictlyExceed() (gas: 940816)\nSuite result: ok. 12 passed; 0 failed; 0 skipped; finished in 1.52s (1.53s CPU time)\n\nRan 1 test for test/invariants/SourceAuctionInvariant.t.sol:SourceAuctionInvariantTest\n[PASS]\nSourceAuctionInvariantTest invariants:\n[PASS] invariant_auctionConservation\n[PASS] invariant_highBidMonotone\n[PASS] invariant_settlementIsFinal\n SourceAuctionInvariantTest invariants (runs: 96, calls: 5760, reverts: 0)\n\n╭----------------+--------------------+-------+---------+----------╮\n| Contract       | Selector           | Calls | Reverts | Discards |\n+==================================================================+\n| AuctionHandler | bid                | 851   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | payloadStaysLocked | 829   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | recordHigh         | 828   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | setAuction         | 794   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | settle             | 834   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | warp               | 852   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | withdrawRefund     | 772   | 0       | 0        |\n╰----------------+--------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 694\n  Bound result 1583096506078419801\n  Bound result 437\n  Bound result 1321\n  Bound result 2000000000000000128\n  Bound result 400\n  Bound result 1800\n  Bound result 401\n  Bound result 3497\n  Bound result 4000000000000000405\n  Bound result 1078\n  Bound result 425\n  Bound result 1562\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.80s (1.79s CPU time)\n\nRan 12 tests for test/Gate.t.sol:GateTest\n[PASS] test_aHostileMembershipContractCountsAsNotMember() (gas: 62498695)\n[PASS] test_auction_gateFixedFromTheFirstBid() (gas: 714509)\n[PASS] test_auction_holdersFirstThenAnyone() (gas: 948469)\n[PASS] test_auction_membersBid_andTheMemberGateIsFixedFromTheFirstBid() (gas: 1006851)\n[PASS] test_brokenSeatContractCountsAsNotHeld() (gas: 61030979)\n[PASS] test_editions_gateFixedOnceTheSaleOpens() (gas: 61529270)\n[PASS] test_editions_holdersFirstThenAnyone() (gas: 62031088)\n[PASS] test_editions_membersBuyInTheWindow_asTokenHoldersDo() (gas: 62059353)\n[PASS] test_editions_noGateMeansOpen() (gas: 61274007)\n[PASS] test_editions_seatBuysUpToFivePerSeatWhereverItGoes() (gas: 62695785)\n[PASS] test_gateRules() (gas: 239527)\n[PASS] test_memberGateRules() (gas: 61261926)\nSuite result: ok. 12 passed; 0 failed; 0 skipped; finished in 2.13s (316.32ms CPU time)\n\nRan 7 tests for test/Adversarial.t.sol:SourceEdgeTest\n[PASS] testFuzz_minimumRaiseIsCeilingOfFivePercent(uint96,uint96) (runs: 512, μ: 629588, ~: 629679)\nLogs:\n  Bound result 60141942638\n  Bound result 476213683457539704\n\n[PASS] testFuzz_rendererHashIsKeccakOfConcatenation(bytes,bytes,bytes) (runs: 64, μ: 419785, ~: 416599)\n[PASS] test_bidBoundaries() (gas: 901651)\n[PASS] test_payloadChunkLimits() (gas: 5443288)\n[PASS] test_setAuctionEdges() (gas: 459334)\n[PASS] test_settleEdges_brokerSplit() (gas: 6966012)\n[PASS] test_settleWithUnapprovedBrokerPaysTheBurn() (gas: 5869414)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 2.24s (2.26s CPU time)\n\nRan 21 tests for test/ArtHouse.t.sol:ArtHouseTest\n[PASS] testFuzz_ethSplitInvariant(uint96,bool,bool) (runs: 64, μ: 1218374, ~: 1239979)\n[PASS] testFuzz_imdSplitInvariant(uint96,bool) (runs: 64, μ: 1311545, ~: 1314827)\n[PASS] test_artistPayoutOnlyArtist_keptOnReapproval() (gas: 179207)\n[PASS] test_collectionMintOnlyHouse() (gas: 73967)\n[PASS] test_curationFlow_andFailures() (gas: 938837)\n[PASS] test_customSplit() (gas: 1124713)\n[PASS] test_deploymentWiring() (gas: 93139)\n[PASS] test_imdBuybackIsReleasedAndBurned() (gas: 1882866)\n[PASS] test_mintFailures() (gas: 1550882)\n[PASS] test_onlyCuratorApproves() (gas: 123827)\n[PASS] test_pieceOver100KBRejected() (gas: 21310484)\n[PASS] test_recordSaleOnlyModules() (gas: 120446)\n[PASS] test_reentrancyOnWithdrawBlocked() (gas: 1838346)\n[PASS] test_revokedArtistLosesCuration() (gas: 582575)\n[PASS] test_sealNeedsEveryPieceFinalized() (gas: 527413)\n[PASS] test_setHouseOnce() (gas: 78294)\n[PASS] test_submissions() (gas: 260658)\n[PASS] test_tokenURIOnChain() (gas: 1190981)\n[PASS] test_twoStepOwnership_noRenounce() (gas: 198046)\n[PASS] test_withdrawNothingReverts_andHouseGoesToCurrentOwner() (gas: 1241987)\n[PASS] test_wrongHashIsCorrectable() (gas: 777075)\nSuite result: ok. 21 passed; 0 failed; 0 skipped; finished in 2.24s (112.52ms CPU time)\n\nRan 16 tests for test/Artifacts.t.sol:ArtifactsFactoryTest\n[PASS] test_buyFailures() (gas: 60997239)\n[PASS] test_buyMany_cannotPassSupply() (gas: 98935498)\n[PASS] test_buyMany_fivePerWallet() (gas: 63860710)\n[PASS] test_buyRecordsSaleAndAssignsEveryEditionOnce() (gas: 178065420)\n[PASS] test_claimFlow_andFailures() (gas: 67458014)\n[PASS] test_postWrappedKeysInOneBatch() (gas: 67755786)\n[PASS] test_publishAndLock_accessAndFailures() (gas: 60947985)\n[PASS] test_rerequestAtOnceWhenTheCoordinatorAnsweredButTheCallbackFailed() (gas: 61875354)\n[PASS] test_rerequestRandomnessAfterDroppedRequest() (gas: 62033982)\n[PASS] test_saleControl() (gas: 61043179)\n[PASS] test_sealTokenURIMatchesR8Frame() (gas: 970414031)\n[PASS] test_viewingKeyZeroRejected() (gas: 33301)\n[PASS] test_vrfCallbackCannotBeReplayed() (gas: 61629805)\n[PASS] test_vrfCallbackGasIsTheCuratorsToTune() (gas: 61431482)\n[PASS] test_vrfCorrectableUntilTheSaleOpens_thenLockedForever() (gas: 62248774)\n[PASS] test_vrfMustBeConfiguredBeforeSelling() (gas: 46850)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 2.93s (3.69s CPU time)\n\nRan 11 tests for test/ReviewRound4.t.sol:ReviewRound4Test\n[PASS] testFuzz_gateViewsNeverRevert(address,address,address) (runs: 64, μ: 147459, ~: 147548)\n[PASS] testFuzz_theFallbackResultStandsAgainstAnyLateWord(uint256,bytes32) (runs: 64, μ: 61602125, ~: 61602134)\n[PASS] test_aDeadFallbackDrawCanBeRerequested() (gas: 62342387)\n[PASS] test_aLiveFallbackDrawStillCannotBeRerequested() (gas: 61855098)\n[PASS] test_gateSeats_dirtyOwnerWord_isNotHeld() (gas: 61073739)\n[PASS] test_gateSeats_noCode_isNotHeld() (gas: 61538697)\n[PASS] test_gateSeats_withCode_unchanged() (gas: 61870940)\n[PASS] test_gateToken_noCode_isNotHeld_andMembersStillBuy() (gas: 62065872)\n[PASS] test_noChainlinkAnswerOnceTheFallbackHashIsPublic() (gas: 61639787)\n[PASS] test_noFallbackOnARequestChainlinkMayStillAnswer() (gas: 61638100)\n[PASS] test_source_gateNoCode_bidsRefusedNotReverted_membersBid() (gas: 998508)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 2.92s (2.21s CPU time)\n\nRan 1 test for test/invariants/PieceEscrowInvariant.t.sol:PieceEscrowInvariantTest\n[PASS]\nPieceEscrowInvariantTest invariants:\n[PASS] invariant_escrowConservation\n[PASS] invariant_escrowSellerOwns\n[PASS] invariant_royaltyAndIdentity\n[PASS] invariant_singleToken\n PieceEscrowInvariantTest invariants (runs: 96, calls: 5760, reverts: 0)\n\n╭---------------+--------------------+-------+---------+----------╮\n| Contract      | Selector           | Calls | Reverts | Discards |\n+=================================================================+\n| EscrowHandler | approveAndTransfer | 387   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | buy                | 370   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | cancel             | 387   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | delist             | 402   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | list               | 390   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | postKey            | 413   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | proveFake          | 367   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | refundBuyer        | 354   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | registerKey        | 387   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | release            | 391   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | rewrap             | 402   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | transfer           | 407   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | warp               | 366   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | withdraw           | 355   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | withdrawRoyalty    | 382   | 0       | 0        |\n╰---------------+--------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 17083\n  Bound result 14264337593543950335\n  Bound result 735\n  Bound result 20337108042\n  Bound result 111059\n  Bound result 34646\n  Bound result 4037\n  Bound result 4660\n  Bound result 576000\n  Bound result 20880797823880349362\n  Bound result 1000\n  Bound result 15121\n  Bound result 336000\n  Bound result 47915958131739435367\n  Bound result 9999\n  Bound result 3811\n  Bound result 149144\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.05s (2.96s CPU time)\n\nRan 1 test for test/invariants/ArtifactsFactoryInvariant.t.sol:ArtifactsFactoryInvariantTest\n[PASS]\nArtifactsFactoryInvariantTest invariants:\n[PASS] invariant_claimedPiecesBelongToBuyers\n[PASS] invariant_counts\n[PASS] invariant_ledgerHoldsEveryPurchase\n[PASS] invariant_lockedAndPriced\n[PASS] invariant_walletLimit\n ArtifactsFactoryInvariantTest invariants (runs: 96, calls: 5760, reverts: 0)\n\n╭----------------+-------------------+-------+---------+----------╮\n| Contract       | Selector          | Calls | Reverts | Discards |\n+=================================================================+\n| FactoryHandler | buy               | 534   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | buyMany           | 495   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | claim             | 552   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | fulfil            | 497   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | lockedForever     | 508   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | replay            | 536   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | rerequest         | 507   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | setPrice          | 494   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | strangerFulfil    | 564   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | strangerRerequest | 534   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | toggleSale        | 539   | 0       | 0        |\n╰----------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 338193125\n  Bound result 51638143296626\n  Bound result 0\n  Bound result 2574237282764180103\n  Bound result 4264337593543950335\n  Bound result 4\n  Bound result 5\n  Bound result 6\n  Bound result 1\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.38s (3.31s CPU time)\n\nRan 1 test for test/invariants/ArtHouseInvariant.t.sol:ArtHouseInvariantTest\n[PASS]\nArtHouseInvariantTest invariants:\n[PASS] invariant_constants\n[PASS] invariant_ethConservation\n[PASS] invariant_imdConservation\n[PASS] invariant_noOverWithdrawal\n[PASS] invariant_supplyAndSeal\n ArtHouseInvariantTest invariants (runs: 128, calls: 5120, reverts: 0)\n\n╭---------------+----------------+-------+---------+----------╮\n| Contract      | Selector       | Calls | Reverts | Discards |\n+=============================================================+\n| LedgerHandler | handOver       | 380   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | mintETH        | 369   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | mintIMD        | 414   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | moduleSale     | 377   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | releaseBuyback | 413   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setBroker      | 396   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setPayout      | 404   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setPrices      | 429   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setSaleOpen    | 378   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setSplit       | 413   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | strangerCalls  | 361   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | withdraw       | 377   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | withdrawHouse  | 409   | 0       | 0        |\n╰---------------+----------------+-------+---------+----------╯\n\nLogs:\n  Bound result 18882627285399\n  Bound result 685\n  Bound result 1073742068\n  Bound result 61765395460014508990\n  Bound result 9\n  Bound result 986\n  Bound result 127\n  Bound result 1074\n  Bound result 5569\n  Bound result 4058\n  Bound result 6\n  Bound result 14264337593543950335\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 7.12s (7.11s CPU time)\n\nRan 13 tests for test/Adversarial.t.sol:ArtifactsEdgeTest\n[PASS] testFuzz_anyWordsAssignDistinctEditions(uint256[8]) (runs: 256, μ: 64665126, ~: 64666799)\n[PASS] testFuzz_sealFramesAnyTraits(uint8,uint8,uint8,uint8,uint8) (runs: 16, μ: 519807370, ~: 519808015)\nLogs:\n  Bound result 7\n\n[PASS] test_buyRevertsAtomicallyWhenCoordinatorReverts() (gas: 59197366)\n[PASS] test_callbackWithNoWordsReverts() (gas: 61551984)\n[PASS] test_claimedPieceIsAFullCopyOfTheImplementation() (gas: 67249308)\n[PASS] test_configureVRFRejectsZeroes() (gas: 211437)\n[PASS] test_duplicateRequestIdRejected() (gas: 59391685)\n[PASS] test_nonOwnerCannotRunTheSale() (gas: 60818098)\n[PASS] test_rerequestIsAtomicWhenCoordinatorReverts() (gas: 59885766)\n[PASS] test_rerequestWindowBoundaryAndChaining() (gas: 67823748)\n[PASS] test_setPieceEdges() (gas: 61051490)\n[PASS] test_unapprovedBuyerAsBrokerEarnsNothing_andOneWeiPriceWorks() (gas: 61489495)\n[PASS] test_wrappedKeyEdges() (gas: 67231974)\nSuite result: ok. 13 passed; 0 failed; 0 skipped; finished in 19.01s (21.82s CPU time)\n\nRan 30 test suites in 19.02s (50.54s CPU time): 244 tests passed, 0 failed, 2 skipped (246 total tests)\n","passed":true},{"durationMs":205,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"ArtCollection.approve(address,uint256)\",\"ArtCollection.initialize(address,string,string)\",\"ArtCollection.mint(address,uint256)\",\"ArtCollection.safeTransferFrom(address,address,uint256)\",\"ArtCollection.safeTransferFrom(address,address,uint256,bytes)\",\"ArtCollection.setApprovalForAll(address,bool)\",\"ArtCollection.transferFrom(address,address,uint256)\",\"ArtHouse.acceptOwnership()\",\"ArtHouse.approveArtist(address,string)\",\"ArtHouse.clearPiece(address,uint256)\",\"ArtHouse.createCollection(string,string,address)\",\"ArtHouse.decideSubmission(uint256,bool)\",\"ArtHouse.finalizePiece(address,uint256)\",\"ArtHouse.mint(address,uint256,address)\",\"ArtHouse.mintWithIMD(address,uint256,address,uint256)\",\"ArtHouse.recordResale(address,uint256,uint256)\",\"ArtHouse.recordSale(address,address,address)\",\"ArtHouse.registerModuleCollection(address,address)\",\"ArtHouse.registerPiece(address,uint256,bytes32,string,string)\",\"ArtHouse.releaseBuyback(address)\",\"ArtHouse.revokeArtist(address)\",\"ArtHouse.sealCollection(address)\",\"ArtHouse.setBroker(address,bool)\",\"ArtHouse.setBrokerPass(address)\",\"ArtHouse.setBuybackBurner(address)\",\"ArtHouse.setPayout(address)\",\"ArtHouse.setPrices(address,uint256,uint256)\",\"ArtHouse.setSaleModule(address,bool)\",\"ArtHouse.setSaleOpen(address,bool)\",\"ArtHouse.setSplit(address,uint16,uint16,uint16,uint16)\",\"ArtHouse.submit(bytes32,string)\",\"ArtHouse.transferOwnership(address)\",\"ArtHouse.updatePiece(address,uint256,bytes32,string,string)\",\"ArtHouse.uploadChunk(address,uint256,uint256,bytes)\",\"ArtHouse.withdraw(address)\",\"ArtHouse.withdrawHouse(address)\",\"ArtStorage.acceptOwnership()\",\"ArtStorage.clear(address,uint256)\",\"ArtStorage.setHouse(address)\",\"ArtStorage.transferOwnership(address)\",\"ArtStorage.write(address,uint256,uint256,bytes)\",\"ArtifactsFactory.acceptOwnership()\",\"ArtifactsFactory.buy(address)\",\"ArtifactsFactory.buyMany(uint256,address)\",\"ArtifactsFactory.buyWithSeat(uint256,uint256,address)\",\"ArtifactsFactory.claim(uint256)\",\"ArtifactsFactory.claimMany(uint256[])\",\"ArtifactsFactory.configureVRF(address,bytes32,uint256,bool)\",\"ArtifactsFactory.endSale()\",\"ArtifactsFactory.finishFallbackDraw(uint256)\",\"ArtifactsFactory.lock()\",\"ArtifactsFactory.postWrappedKey(uint256,bytes)\",\"ArtifactsFactory.postWrappedKeys(uint256[],bytes[])\",\"ArtifactsFactory.rawFulfillRandomWords(uint256,uint256[])\",\"ArtifactsFactory.registerViewingKey(bytes32)\",\"ArtifactsFactory.rerequestRandomness(uint256)\",\"ArtifactsFactory.setGate(address,address,uint256,uint64)\",\"ArtifactsFactory.setMemberGate(address,bytes4,uint256)\",\"ArtifactsFactory.setMintPhases(uint64,uint8,uint64,uint8)\",\"ArtifactsFactory.setPiece(uint256,(string,string,uint8,string),bytes,bytes32)\",\"ArtifactsFactory.setPrice(uint256)\",\"ArtifactsFactory.setSaleOpen(bool)\",\"ArtifactsFactory.setVRFCallbackGas(uint32)\",\"ArtifactsFactory.startFallbackDraw(uint256)\",\"ArtifactsFactory.transferOwnership(address)\",\"ArtifactsPiece.approve(address,uint256)\",\"ArtifactsPiece.buy(bytes32,address)\",\"ArtifactsPiece.cancel()\",\"ArtifactsPiece.delist()\",\"ArtifactsPiece.initialize(address,address,uint256,address,(string,string,uint8,string),address,bytes32,bytes,bool,bytes32)\",\"ArtifactsPiece.list(uint256)\",\"ArtifactsPiece.postEscrowKey(bytes,address,uint256)\",\"ArtifactsPiece.proveFakeKey((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256))\",\"ArtifactsPiece.refundBuyer()\",\"ArtifactsPiece.registerViewingKey(bytes32)\",\"ArtifactsPiece.release()\",\"ArtifactsPiece.reveal(bytes32)\",\"ArtifactsPiece.rewrapFor(bytes)\",\"ArtifactsPiece.safeTransferFrom(address,address,uint256)\",\"ArtifactsPiece.safeTransferFrom(address,address,uint256,bytes)\",\"ArtifactsPiece.setApprovalForAll(address,bool)\",\"ArtifactsPiece.transferFrom(address,address,uint256)\",\"ArtifactsPiece.withdraw()\",\"ArtifactsSource.acceptOwnership()\",\"ArtifactsSource.bid(address)\",\"ArtifactsSource.deliverKey(bytes)\",\"ArtifactsSource.lock(bytes32,bytes32)\",\"ArtifactsSource.resetRenderer()\",\"ArtifactsSource.setAuction(uint256,uint64)\",\"ArtifactsSource.setGate(address,address,uint256,uint64)\",\"ArtifactsSource.setMemberGate(address,bytes4,uint256)\",\"ArtifactsSource.settle()\",\"ArtifactsSource.storeRendererChunk(bytes)\",\"ArtifactsSource.transferOwnership(address)\",\"ArtifactsSource.voidUnsettled()\",\"ArtifactsSource.withdrawRefund()\",\"BrokerPass.approve(address,uint256)\",\"BrokerPass.claimWithPiece(uint256)\",\"BrokerPass.claimWithSeat(uint256)\",\"BrokerPass.safeTransferFrom(address,address,uint256)\",\"BrokerPass.safeTransferFrom(address,address,uint256,bytes)\",\"BrokerPass.setApprovalForAll(address,bool)\",\"BrokerPass.setClaimsOpenAt(uint64)\",\"BrokerPass.transferFrom(address,address,uint256)\",\"ImdBuybackBurner.burnEth(uint256,uint256,uint256)\",\"ImdBuybackBurner.burnImd()\",\"ImdBuybackBurner.receive()\",\"ImdBuybackBurner.unlockCallback(bytes)\",\"SubmissionReviews.applyAsBroker(string)\",\"SubmissionReviews.postThesis(uint256,string)\",\"SubmissionReviews.reviewAsPiece(uint256,uint256,uint8,string)\",\"SubmissionReviews.reviewAsSeat(uint256,uint256,uint8,string)\"],\"files\":{\".gitignore\":3,\"ADAPTATION.md\":356,\"README.md\":272,\"foundry.toml\":25,\"launch.burner.json\":17,\"launch.json\":63,\"reference/PROTOCOL.md\":99,\"reference/RULES.md\":137,\"reference/audit/V13Audit.t.sol.txt\":381,\"reference/check-framed.js\":25,\"reference/framed/framed-003.svg\":1,\"reference/framed/framed-MASTER.svg\":1,\"reference/rules.js\":145,\"reference/the-source.renderer.html\":148,\"remappings.txt\":1,\"script/Deploy.s.sol\":39,\"src/ArtCollection.sol\":55,\"src/ArtHouse.sol\":609,\"src/ArtStorage.sol\":82,\"src/ArtifactsFactory.sol\":635,\"src/ArtifactsPiece.sol\":457,\"src/ArtifactsSource.sol\":271,\"src/BrokerPass.sol\":142,\"src/ImdBuybackBurner.sol\":163,\"src/KeyProof.sol\":154,\"src/SubmissionReviews.sol\":215,\"src/base/ERC721Lite.sol\":122,\"src/base/HolderGate.sol\":113,\"src/base/ReentrancyGuard.sol\":15,\"src/base/TwoStepOwnable.sol\":40,\"src/interfaces/Interfaces.sol\":93,\"src/libs/Clones.sol\":19,\"src/libs/Encoding.sol\":79,\"src/libs/SSTORE2.sol\":41,\"src/libs/Seal.sol\":102,\"test/Adversarial.t.sol\":1409,\"test/ArtHouse.t.sol\":463,\"test/Artifacts.t.sol\":673,\"test/AuditRound3.t.sol\":151,\"test/BrokerPass.t.sol\":373,\"test/Burner.t.sol\":161,\"test/ClaimEnd.t.sol\":152,\"test/Fixture.sol\":230,\"test/Gate.t.sol\":295,\"test/KeyProof.t.sol\":134,\"test/LaunchAudit.t.sol\":338,\"test/LaunchDeployment.t.sol\":191,\"test/NothingStuck.t.sol\":594,\"test/Phases.t.sol\":130,\"test/ReviewRound4.t.sol\":262,\"test/Reviews.t.sol\":264,\"test/Source.t.sol\":396,\"test/audit/KeyProofEdges.t.sol\":178,\"test/audit/KeyReuseLeak.t.sol\":38,\"test/fixtures/keyproof.json\":81,\"test/fork/BurnerFork.t.sol\":70,\"test/fork/VrfFork.t.sol\":131,\"test/invariants/ArtHouseInvariant.t.sol\":444,\"test/invariants/ArtifactsFactoryInvariant.t.sol\":323,\"test/invariants/PieceEscrowInvariant.t.sol\":445,\"test/invariants/SourceAuctionInvariant.t.sol\":227,\"test/mocks/AdversarialMocks.sol\":134,\"test/mocks/MockPoolManager.sol\":57,\"test/mocks/MockSeats.sol\":27,\"test/mocks/Mocks.sol\":149,\"test/mocks/TestVRFCoordinator.sol\":46,\"test/utils/Base64Decode.sol\":83},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":23049,"exitCode":0,"name":"slither","output":"[high/medium] arbitrary-send-eth at src/ArtHouse.sol:559: ArtHouse._pay(address,address,uint256) (src/ArtHouse.sol#559-566) sends eth to arbitrary user\n[high/medium] weak-prng at src/ArtifactsFactory.sol:482: ArtifactsFactory._assign(uint256,uint256) (src/ArtifactsFactory.sol#482-498) uses a weak PRNG: \"idx = uint16(word % left) (src/ArtifactsFactory.sol#487)\"\n[high/medium] reentrancy-balance at src/ArtHouse.sol:431: Reentrancy in ArtHouse._pullIMD(address,uint256) (src/ArtHouse.sol#431-436):\n[high/medium] reentrancy-eth at src/ArtifactsPiece.sol:294: Reentrancy in ArtifactsPiece.release() (src/ArtifactsPiece.sol#294-330):\n[medium/medium] divide-before-multiply at src/libs/Encoding.sol:8: Encoding.base64(bytes) (src/libs/Encoding.sol#8-37) performs a multiplication on the result of a division:\n[medium/high] incorrect-equality at src/ArtifactsFactory.sol:455: ArtifactsFactory._fallbackLive(uint256) (src/ArtifactsFactory.sol#455-459) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/ArtifactsFactory.sol:463: ArtifactsFactory.finishFallbackDraw(uint256) (src/ArtifactsFactory.sol#463-472) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/ArtifactsSource.sol:182: ArtifactsSource.gateEndsAt() (src/ArtifactsSource.sol#182-184) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/ArtifactsFactory.sol:475: ArtifactsFactory._hashOf(uint256) (src/ArtifactsFactory.sol#475-480) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/ImdBuybackBurner.sol:136: ImdBuybackBurner.burnImd() (src/ImdBuybackBurner.sol#136-142) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/ArtifactsFactory.sol:463: ArtifactsFactory.finishFallbackDraw(uint256) (src/ArtifactsFactory.sol#463-472) uses a dangerous strict equality:\n[medium/medium] uninitialized-local at src/SubmissionReviews.sol:103: SubmissionReviews.reviewAsSeat(uint256,uint256,SubmissionReviews.Verdict,string).holder (src/SubmissionReviews.sol#103) is a local variable never initialized\n[medium/medium] uninitialized-local at src/BrokerPass.sol:85: BrokerPass.claimWithPiece(uint256).piece (src/BrokerPass.sol#85) is a local variable never initialized\n[medium/medium] uninitialized-local at src/ArtifactsPiece.sol:308: ArtifactsPiece.release().brokerShare (src/ArtifactsPiece.sol#308) is a local variable never initialized\n[medium/medium] uninitialized-local at src/SubmissionReviews.sol:115: SubmissionReviews.reviewAsPiece(uint256,uint256,SubmissionReviews.Verdict,string).piece (src/SubmissionReviews.sol#115) is a local variable never initialized\n[medium/medium] uninitialized-local at src/ArtifactsPiece.sol:438: ArtifactsPiece._revealedURI().page (src/ArtifactsPiece.sol#438) is a local variable never initialized\n[medium/medium] unused-return at src/SubmissionReviews.sol:123: SubmissionReviews._review(uint256,uint256,SubmissionReviews.Verdict,string) (src/SubmissionReviews.sol#123-139) ignores return value by (None,None,None,status) = house.submissions(submissionId) (src/SubmissionReviews.sol#127)\n[medium/medium] unused-return at src/ArtHouse.sol:353: ArtHouse.uploadChunk(address,uint256,uint256,bytes) (src/ArtHouse.sol#353-364) ignores return value by artStorage.write(collection,pieceId,index,data) (src/ArtHouse.sol#363)\n[medium/medium] unused-return at src/SubmissionReviews.sol:160: SubmissionReviews._thesis(uint256,string) (src/SubmissionReviews.sol#160-169) ignores return value by (None,None,None,status) = house.submissions(submissionId) (src/SubmissionReviews.sol#164)\n[medium/medium] unused-return at src/ImdBuybackBurner.sol:146: ImdBuybackBurner.unlockCallback(bytes) (src/ImdBuybackBurner.sol#146-162) ignores return value by poolManager.settle{value: ethIn}() (src/ImdBuybackBurner.sol#159)\n[low/medium] missing-zero-check at src/ArtifactsSource.sol:186: ArtifactsSource.bid(address).broker (src/ArtifactsSource.sol#186) lacks a zero-check on :\n[low/medium] missing-zero-check at src/ArtifactsPiece.sol:123: ArtifactsPiece.initialize(address,address,uint256,address,Traits,address,bytes32,bytes,bool,bytes32).ciphertext_ (src/ArtifactsPiece.sol#123) lacks a zero-check on :\n[low/medium] missing-zero-check at src/ImdBuybackBurner.sol:91: ImdBuybackBurner.constructor(address,address,address,uint24,int24,address).poolHooks_ (src/ImdBuybackBurner.sol#91) lacks a zero-check on :\n[low/medium] calls-loop at src/ArtifactsFactory.sol:401: ArtifactsFactory._requestRandomness(address,uint256) (src/ArtifactsFactory.sol#401-416) has external calls inside a loop: requestId = vrfCoordinator.requestRandomWords(IVRFCoordinatorV2Plus.RandomWordsRequest({keyHash:vrfKeyHash,subId:vrfSubscriptionId,requestConfirmations:VRF_CONFIRMATIONS,callbackGasLimit:vrfCallbackGas,numWords:1,extraArgs:abi.encodeWithSelector(bytes4(keccak256(bytes)(VRF ExtraArgsV1)),vrfNativePayment)})) (src/ArtifactsFactory.sol#402-411)\n[low/medium] calls-loop at src/ArtifactsFactory.sol:558: ArtifactsFactory._claim(uint256) (src/ArtifactsFactory.sol#558-584) has external calls inside a loop: IArtifactsPiece(piece).initialize(address(this),address(house),edition,buyer,p.traits,p.ciphertext,p.commitment,wrapped,false,viewingKeyOf[buyer]) (src/ArtifactsFactory.sol#570-582)\n[low/medium] calls-loop at src/ArtifactsFactory.sol:401: ArtifactsFactory._requestRandomness(address,uint256) (src/ArtifactsFactory.sol#401-416) has external calls inside a loop: requestId = vrfCoordinator.requestRandomWords(IVRFCoordinatorV2Plus.RandomWordsRequest({keyHash:vrfKeyHash,subId:vrfSubscriptionId,requestConfirmations:VRF_CONFIRMATIONS,callbackGasLimit:vrfCallbackGas,numWords:1,extraArgs:abi.encodeWithSelector(bytes4(keccak256(bytes)(VRF ExtraArgsV1)),vrfNativePayment)})) (src/ArtifactsFactory.sol#402-411)\n[low/medium] calls-loop at src/ArtifactsFactory.sol:522: ArtifactsFactory._postWrappedKey(uint256,bytes) (src/ArtifactsFactory.sol#522-541) has external calls inside a loop: IArtifactsPiece(piece).rewrapFor(wrapped) (src/ArtifactsFactory.sol#530)\n[low/medium] calls-loop at src/ArtifactsFactory.sol:401: ArtifactsFactory._requestRandomness(address,uint256) (src/ArtifactsFactory.sol#401-416) has external calls inside a loop: requestId = vrfCoordinator.requestRandomWords(IVRFCoordinatorV2Plus.RandomWordsRequest({keyHash:vrfKeyHash,subId:vrfSubscriptionId,requestConfirmations:VRF_CONFIRMATIONS,callbackGasLimit:vrfCallbackGas,numWords:1,extraArgs:abi.encodeWithSelector(bytes4(keccak256(bytes)(VRF ExtraArgsV1)),vrfNativePayment)})) (src/ArtifactsFactory.sol#402-411)\n[low/medium] reentrancy-benign at src/ArtifactsFactory.sol:350: Reentrancy in ArtifactsFactory._buy(uint256,address) (src/ArtifactsFactory.sol#350-366):\n[low/medium] reentrancy-benign at src/ImdBuybackBurner.sol:136: Reentrancy in ImdBuybackBurner.burnImd() (src/ImdBuybackBurner.sol#136-142):\n[low/medium] reentrancy-benign at src/ArtifactsFactory.sol:401: Reentrancy in ArtifactsFactory._requestRandomness(address,uint256) (src/ArtifactsFactory.sol#401-416):\n[low/medium] reentrancy-benign at src/ImdBuybackBurner.sol:110: Reentrancy in ImdBuybackBurner.burnEth(uint256,uint256,uint256) (src/ImdBuybackBurner.sol#110-133):\n[low/medium] reentrancy-benign at src/ArtHouse.sol:237: Reentrancy in ArtHouse.createCollection(string,string,address) (src/ArtHouse.sol#237-247):\n[low/medium] reentrancy-events at src/ImdBuybackBurner.sol:136: Reentrancy in ImdBuybackBurner.burnImd() (src/ImdBuybackBurner.sol#136-142):\n[low/medium] reentrancy-events at src/ArtifactsFactory.sol:373: Reentrancy in ArtifactsFactory.rerequestRandomness(uint256) (src/ArtifactsFactory.sol#373-391):\n[low/medium] reentrancy-events at src/ArtHouse.sol:367: Reentrancy in ArtHouse.clearPiece(address,uint256) (src/ArtHouse.sol#367-375):\n[low/medium] reentrancy-events at src/ImdBuybackBurner.sol:110: Reentrancy in ImdBuybackBurner.burnEth(uint256,uint256,uint256) (src/ImdBuybackBurner.sol#110-133):\n[low/medium] reentrancy-events at src/ArtHouse.sol:237: Reentrancy in ArtHouse.createCollection(string,string,address) (src/ArtHouse.sol#237-247):\n[low/medium] reentrancy-events at src/ArtifactsSource.sol:138: Reentrancy in ArtifactsSource.deliverKey(bytes) (src/ArtifactsSource.sol#138-145):\n[low/medium] timestamp at src/ArtifactsFactory.sol:273: ArtifactsFactory.gateEndsAt() (src/ArtifactsFactory.sol#273-275) uses timestamp for comparisons\n[low/medium] timestamp at src/BrokerPass.sol:67: BrokerPass.setClaimsOpenAt(uint64) (src/BrokerPass.sol#67-73) uses timestamp for comparisons\n[low/medium] timestamp at src/BrokerPass.sol:76: BrokerPass.claimsOpen() (src/BrokerPass.sol#76-78) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsPiece.sol:294: ArtifactsPiece.release() (src/ArtifactsPiece.sol#294-330) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsPiece.sol:278: ArtifactsPiece.cancel() (src/ArtifactsPiece.sol#278-290) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:558: ArtifactsFactory._claim(uint256) (src/ArtifactsFactory.sol#558-584) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:260: ArtifactsFactory.setGate(address,address,uint256,uint64) (src/ArtifactsFactory.sol#260-263) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:232: ArtifactsFactory.configureVRF(address,bytes32,uint256,bool) (src/ArtifactsFactory.sol#232-243) uses timestamp for comparisons\n[low/medium] timestamp at src/ImdBuybackBurner.sol:110: ImdBuybackBurner.burnEth(uint256,uint256,uint256) (src/ImdBuybackBurner.sol#110-133) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:297: ArtifactsFactory.currentPhase() (src/ArtifactsFactory.sol#297-305) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:280: ArtifactsFactory.setMintPhases(uint64,uint8,uint64,uint8) (src/ArtifactsFactory.sol#280-293) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsSource.sol:182: ArtifactsSource.gateEndsAt() (src/ArtifactsSource.sol#182-184) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsSource.sol:245: ArtifactsSource.voidUnsettled() (src/ArtifactsSource.sol#245-257) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsSource.sol:186: ArtifactsSource.bid(address) (src/ArtifactsSource.sol#186-201) uses timestamp for comparisons\n[low/medium] timestamp at src/base/HolderGate.sol:73: HolderGate._inGate(uint256) (src/base/HolderGate.sol#73-75) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsSource.sol:151: ArtifactsSource.setAuction(uint256,uint64) (src/ArtifactsSource.sol#151-163) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:218: ArtifactsFactory.endSale() (src/ArtifactsFactory.sol#218-227) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:267: ArtifactsFactory.setMemberGate(address,bytes4,uint256) (src/ArtifactsFactory.sol#267-270) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:203: ArtifactsFactory.setSaleOpen(bool) (src/ArtifactsFactory.sol#203-213) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsSource.sol:213: ArtifactsSource.settle() (src/ArtifactsSource.sol#213-241) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsPiece.sol:201: ArtifactsPiece.delist() (src/ArtifactsPiece.sol#201-206) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:249: ArtifactsFactory.setVRFCallbackGas(uint32) (src/ArtifactsFactory.sol#249-254) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsPiece.sol:353: ArtifactsPiece._beforeTransfer(address,address,uint256) (src/ArtifactsPiece.sol#353-361) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:346: ArtifactsFactory._tokenGate() (src/ArtifactsFactory.sol#346-348) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsPiece.sol:370: ArtifactsPiece.reveal(bytes32) (src/ArtifactsPiece.sol#370-384) uses timestamp for comparisons","passed":true},{"durationMs":1144,"exitCode":0,"name":"aderyn","output":"[high] abi-encode-packed-hash-collision at src/ArtCollection.sol:44: `abi.encodePacked()` Hash Collision (6 places)\n[high] contract-locks-ether at src/ArtifactsFactory.sol:13: Contract locks Ether without a withdraw function (2 places)\n[high] eth-send-unchecked-address at src/ArtifactsPiece.sol:341: ETH transferred without address checks (2 places)\n[high] reentrancy-state-change at src/ArtHouse.sol:360: Reentrancy: State change after external call (18 places)\n[low] centralization-risk at src/ArtHouse.sol:176: Centralization Risk (36 places)\n[low] costly-loop at src/ArtifactsFactory.sol:362: Costly operations inside loop (3 places)\n[low] empty-block at src/base/ERC721Lite.sol:121: Empty Block\n[low] large-numeric-literal at src/ArtHouse.sol:15: Large Numeric Literal (11 places)\n[low] literal-instead-of-constant at src/ArtifactsFactory.sol:398: Literal Instead of Constant (35 places)\n[low] require-revert-in-loop at src/ArtHouse.sol:394: Loop Contains `require`/`revert` (4 places)\n[low] state-change-without-event at src/ArtCollection.sol:20: State Change Without Event (5 places)\n[low] state-no-address-check at src/ArtifactsPiece.sol:132: Address State Variable Set Without Checks (3 places)\n[low] storage-array-length-not-cached at src/ArtifactsSource.sol:120: Storage Array Length not Cached\n[low] unchecked-return at src/ArtCollection.sol:42: Unchecked Return (5 places)\n[low] uninitialized-local-variable at src/ArtHouse.sol:394: Uninitialized Local Variable (6 places)\n[low] unsafe-erc20-operation at src/ArtHouse.sol:434: Unsafe ERC20 Operation (3 places)","passed":true},{"durationMs":40043,"exitCode":0,"name":"proof 07f1616add6c","output":"Compiling 46 files with Solc 0.8.26\nSolc 0.8.26 finished in 38.89s\nCompiler run successful!\n\nRan 1 test for test/imd-proof-2c2d742e/Proof_07f1616add6c.t.sol:FallbackChoiceTest\n[PASS] test_noChainlinkAnswerAfterTheFallbackHashIsKnown() (gas: 554327)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 31.78ms (287.34µs CPU time)\n\nRan 1 test suite in 34.80ms (31.78ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)\n","passed":true},{"durationMs":19181,"exitCode":0,"name":"proof 20ca2ef1fdca","output":"2026-10-18T22:01:50.818326Z ERROR foundry_compilers_artifacts_solc::sources: error=\"/tmp/imd-verify-tYcAR1/repo/test/imd-proof-2c2d742e/Proof_07f1616add6c.t.sol\": No such file or directory (os error 2)\nCompiling 1 files with Solc 0.8.26\nSolc 0.8.26 finished in 18.16s\nCompiler run successful!\n\nRan 3 tests for test/imd-proof-30dfd928/Proof_20ca2ef1fdca.t.sol:GateNoCodeTest\n[PASS] test_holdsToken_noCode_returnsFalse() (gas: 17928)\n[PASS] test_member_canBuy_duringWindow_whenTokenHasNoCode() (gas: 325555)\n[PASS] test_nonHolder_revertsNotEligible() (gas: 80339)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 36.97ms (934.88µs CPU time)\n\nRan 1 test suite in 39.29ms (36.97ms CPU time): 3 tests passed, 0 failed, 0 skipped (3 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"a40d91eafc3bfc824bdab13c0b51505462ee4346f93508298f9f7f52e5e3c116","verifiedTreeHash":"ef2219feb583b8fff6a9045c65718382011d1986","verifierVersion":"0.1.0+a6ee6548"},{"checks":[{"durationMs":746260,"exitCode":0,"name":"build","output":"Compiling 71 files with Solc 0.8.26\nSolc 0.8.26 finished in 746.03s\nCompiler run successful with warnings:\nWarning (5667): Unused function parameter. Remove or comment out the variable name to silence this warning.\n   --> test/invariants/ArtHouseInvariant.t.sol:105:9:\n    |\n105 |         address buyer,\n    |         ^^^^^^^^^^^^^\n\n","passed":true},{"durationMs":22665,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/fork/BurnerFork.t.sol:BurnerForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 4.90ms (0.00ns CPU time)\n\nRan 1 test for test/fork/VrfFork.t.sol:VrfForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 7.99ms (0.00ns CPU time)\n\nRan 5 tests for test/audit/KeyProofEdges.t.sol:KeyProofEdgesTest\n[PASS] test_adversarialE_isProvable() (gas: 107849)\n[PASS] test_adversarialE_proofIsActuallyChecked() (gas: 23615)\n[PASS] test_negatedSCannotFrame() (gas: 60700)\n[PASS] test_oddYWrapThatOpensIsNotFake() (gas: 37558)\n[PASS] test_xEqualsN_isMalformed() (gas: 13218)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 8.41ms (3.58ms CPU time)\n\nRan 4 tests for test/AuditRound3.t.sol:AuditRound3Test\n[PASS] test_aReturnDataBombCostsThePayerNothing() (gas: 694152)\n[PASS] test_aShareThatWaitsInTheLedgerIsAnnounced() (gas: 339919)\n[PASS] test_theArtistsPayoutCantMoveThePieceDuringARelease() (gas: 415877)\n[PASS] test_theArtistsPayoutCantRelistDuringARelease() (gas: 600564)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 57.68ms (1.64ms CPU time)\n\nRan 18 tests for test/BrokerPass.t.sol:BrokerPassTest\n[PASS] test_capIs100() (gas: 19752778)\n[PASS] test_claimWithPiece_onceEverPerPiece() (gas: 6679912)\n[PASS] test_claimWithSeat_onceEverPerSeat() (gas: 376003)\n[PASS] test_claimWithTheSource() (gas: 6010301)\n[PASS] test_claimsWaitForTheStartTime_setOnceByTheCurator() (gas: 489742)\n[PASS] test_oneClaimPerWallet() (gas: 6980812)\n[PASS] test_passHolderCanBrokerTheirOwnBuy() (gas: 1019992)\n[PASS] test_passHolderEarnsOnMint_andTheRightMovesWithThePass() (gas: 2081372)\n[PASS] test_recordResaleRejectsAnythingButAPiece() (gas: 298286)\n[PASS] test_resaleBrokerShare_creditedInTheLedger() (gas: 7295006)\n[PASS] test_resaleBuyerWithAPassCanBrokerTheirOwnBuy() (gas: 7232310)\n[PASS] test_resaleFallsBackToThePieceWhenTheLedgerRefuses() (gas: 7247411)\n[PASS] test_resaleSellerCannotBeBroker() (gas: 7144850)\n[PASS] test_resaleWithoutEligibleBroker_sellerKeepsTheShare() (gas: 6934008)\n[PASS] test_setBrokerPassOnce() (gas: 64999)\n[PASS] test_sourceSplit_brokerAndArtistOnly() (gas: 6162142)\n[PASS] test_sourceSplit_noBrokerBurns() (gas: 5919583)\n[PASS] test_tokenURIIsOnChainJson() (gas: 388848)\nSuite result: ok. 18 passed; 0 failed; 0 skipped; finished in 57.70ms (20.04ms CPU time)\n\nRan 10 tests for test/Artifacts.t.sol:ArtifactsPieceEscrowTest\n[PASS] test_escrowCancelBeforeKey_andDelist() (gas: 501042)\n[PASS] test_escrowHappyPath_buyerConfirms() (gas: 1181854)\n[PASS] test_escrowKeyMustNotBeEmpty() (gas: 310921)\n[PASS] test_escrowTimeoutRelease() (gas: 728994)\n[PASS] test_pieceViewingKeyZeroRejected() (gas: 168689)\n[PASS] test_plainTransferClearsKey_previousOwnerRekeys() (gas: 506819)\n[PASS] test_reentrancyOnEscrowWithdrawBlocked() (gas: 844317)\n[PASS] test_rewrapIsOneShotAndNonEmpty() (gas: 284134)\n[PASS] test_sellerCannotOverwriteKeyAfterRelease() (gas: 913301)\n[PASS] test_sourceOnlyReveal() (gas: 35552)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 72.16ms (6.07ms CPU time)\n\nRan 4 tests for test/Phases.t.sol:PhasesTest\n[PASS] test_aSeatFollowsThePhases_whereverItGoes() (gas: 1747729)\n[PASS] test_afterTheWindow_anyoneUpToFive() (gas: 1042332)\n[PASS] test_capsRise_1_then_2_then_5_forAnImdHolder() (gas: 1740786)\n[PASS] test_setOnlyBeforeTheSaleOpens_andChecked() (gas: 322444)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 88.98ms (4.62ms CPU time)\n\nRan 6 tests for test/Adversarial.t.sol:PieceEdgeTest\n[PASS] test_cancelThenSecondBuyerAndRoyaltyToChangedPayout() (gas: 1087998)\n[PASS] test_listingEdges() (gas: 1002975)\n[PASS] test_releaseAtExactly72HoursByStranger() (gas: 914016)\n[PASS] test_revealNeedsTheSourceLocked_andEmptyRendererURI() (gas: 6265659)\n[PASS] test_safeTransferReceivers() (gas: 670237)\n[PASS] test_transferAuthEdges() (gas: 350213)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 92.60ms (14.54ms CPU time)\n\nRan 5 tests for test/ClaimEnd.t.sol:ClaimEndTest\n[PASS] test_claimMany_claimsEveryOneInOneCall() (gas: 18151497)\n[PASS] test_claimMany_emptyRefused_andTheCuratorCanClaimForBuyers() (gas: 12311987)\n[PASS] test_claimMany_isAllOrNothing() (gas: 18205777)\n[PASS] test_endSale_isFinal() (gas: 6923933)\n[PASS] test_endSale_needsTheSaleToHaveOpened_andWorksWhileClosed() (gas: 96083)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 99.93ms (13.14ms CPU time)\n\nRan 11 tests for test/Reviews.t.sol:ReviewsTest\n[PASS] testFuzz_tallyMatchesVoices(uint8[12]) (runs: 64, μ: 1440828, ~: 1442051)\n[PASS] test_aClaimedPieceIsAVoice_andAnUnclaimedOneIsNot() (gas: 67621657)\n[PASS] test_aMovedSeatStillHasOneVoice() (gas: 441792)\n[PASS] test_aSeatAndAPieceInOneWalletAreTwoVoices() (gas: 67346389)\n[PASS] test_anyoneAppliesToBeABroker() (gas: 224553)\n[PASS] test_anyonePublishesTheses() (gas: 810776)\n[PASS] test_changingAReviewMovesItsVote() (gas: 305393)\n[PASS] test_frozenOnceTheCuratorDecides_andAdvisoryOnly() (gas: 349039)\n[PASS] test_inputChecks() (gas: 307196)\n[PASS] test_onlyTheSeatHolderReviews() (gas: 97570)\n[PASS] test_seatsReview_andTheTallyFollows() (gas: 457095)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 124.42ms (149.21ms CPU time)\n\nRan 1 test for test/ClaimEnd.t.sol:EndBeforeOpenTest\n[PASS] test_endSale_beforeOpening_refused() (gas: 60691353)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 147.65ms (110.18ms CPU time)\n\nRan 1 test for test/audit/KeyReuseLeak.t.sol:KeyReuseLeakTest\n[PASS] test_copiedE_cantBePosted(uint256,uint256) (runs: 64, μ: 602945, ~: 603239)\nLogs:\n  Bound result 6677771717396745857438524715775791381032702405673290885595687978682\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 157.14ms (139.54ms CPU time)\n\nRan 7 tests for test/Adversarial.t.sol:SourceEdgeTest\n[PASS] testFuzz_minimumRaiseIsCeilingOfFivePercent(uint96,uint96) (runs: 512, μ: 629587, ~: 629679)\nLogs:\n  Bound result 60141942638\n  Bound result 476213683457539704\n\n[PASS] testFuzz_rendererHashIsKeccakOfConcatenation(bytes,bytes,bytes) (runs: 64, μ: 419784, ~: 416599)\n[PASS] test_bidBoundaries() (gas: 901651)\n[PASS] test_payloadChunkLimits() (gas: 5443288)\n[PASS] test_setAuctionEdges() (gas: 459334)\n[PASS] test_settleEdges_brokerSplit() (gas: 6966012)\n[PASS] test_settleWithUnapprovedBrokerPaysTheBurn() (gas: 5869414)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 171.09ms (182.85ms CPU time)\n\nRan 7 tests for test/Burner.t.sol:BurnerTest\n[PASS] test_anyoneBurnsHeldImd() (gas: 169949)\n[PASS] test_anyoneSwapsInSmallStepsAfter60QuietDays() (gas: 845755)\n[PASS] test_constructorChecks() (gas: 8711)\n[PASS] test_editionSaleToBurnedImd() (gas: 61798551)\n[PASS] test_onlyTheCuratorSwaps_withAMinimumAndADeadline() (gas: 653639)\n[PASS] test_onlyThePoolManagerCallsBack() (gas: 32189)\n[PASS] test_theNewOwnerSwapsAfterAHandover() (gas: 304000)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 207.79ms (191.44ms CPU time)\n\nRan 21 tests for test/ArtHouse.t.sol:ArtHouseTest\n[PASS] testFuzz_ethSplitInvariant(uint96,bool,bool) (runs: 64, μ: 1218376, ~: 1239979)\n[PASS] testFuzz_imdSplitInvariant(uint96,bool) (runs: 64, μ: 1311558, ~: 1314827)\n[PASS] test_artistPayoutOnlyArtist_keptOnReapproval() (gas: 179207)\n[PASS] test_collectionMintOnlyHouse() (gas: 73967)\n[PASS] test_curationFlow_andFailures() (gas: 938837)\n[PASS] test_customSplit() (gas: 1124713)\n[PASS] test_deploymentWiring() (gas: 93139)\n[PASS] test_imdBuybackIsReleasedAndBurned() (gas: 1882866)\n[PASS] test_mintFailures() (gas: 1550882)\n[PASS] test_onlyCuratorApproves() (gas: 123827)\n[PASS] test_pieceOver100KBRejected() (gas: 21310484)\n[PASS] test_recordSaleOnlyModules() (gas: 120446)\n[PASS] test_reentrancyOnWithdrawBlocked() (gas: 1838346)\n[PASS] test_revokedArtistLosesCuration() (gas: 582575)\n[PASS] test_sealNeedsEveryPieceFinalized() (gas: 527413)\n[PASS] test_setHouseOnce() (gas: 78294)\n[PASS] test_submissions() (gas: 260658)\n[PASS] test_tokenURIOnChain() (gas: 1190981)\n[PASS] test_twoStepOwnership_noRenounce() (gas: 198046)\n[PASS] test_withdrawNothingReverts_andHouseGoesToCurrentOwner() (gas: 1241987)\n[PASS] test_wrongHashIsCorrectable() (gas: 777075)\nSuite result: ok. 21 passed; 0 failed; 0 skipped; finished in 254.10ms (226.00ms CPU time)\n\nRan 2 tests for test/LaunchDeployment.t.sol:LaunchDeploymentTest\n[PASS] test_allEightConstructorsAcceptCodeLessDependencies() (gas: 75376878)\n[PASS] test_manifestOrderAndOwnerConfigurationRemainIntact() (gas: 82011018)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 333.40ms (405.51ms CPU time)\n\nRan 12 tests for test/Gate.t.sol:GateTest\n[PASS] test_aHostileMembershipContractCountsAsNotMember() (gas: 62498580)\n[PASS] test_auction_gateFixedFromTheFirstBid() (gas: 714486)\n[PASS] test_auction_holdersFirstThenAnyone() (gas: 948357)\n[PASS] test_auction_membersBid_andTheMemberGateIsFixedFromTheFirstBid() (gas: 1006759)\n[PASS] test_brokenSeatContractCountsAsNotHeld() (gas: 61030533)\n[PASS] test_editions_gateFixedOnceTheSaleOpens() (gas: 61529270)\n[PASS] test_editions_holdersFirstThenAnyone() (gas: 62031024)\n[PASS] test_editions_membersBuyInTheWindow_asTokenHoldersDo() (gas: 62059284)\n[PASS] test_editions_noGateMeansOpen() (gas: 61274007)\n[PASS] test_editions_seatBuysUpToFivePerSeatWhereverItGoes() (gas: 62695849)\n[PASS] test_gateRules() (gas: 239527)\n[PASS] test_memberGateRules() (gas: 61261926)\nSuite result: ok. 12 passed; 0 failed; 0 skipped; finished in 417.40ms (435.70ms CPU time)\n\nRan 8 tests for test/KeyProof.t.sol:KeyProofTest\n[PASS] test_aJunkKeyIsProvenFake() (gas: 369871)\nLogs:\n  gas to check a fake-key proof: 44805\n\n[PASS] test_aKeyThatOpensIsNeverProvenFake() (gas: 368087)\n[PASS] test_aProofOnlyHoldsForItsBuyerPieceAndChain() (gas: 416867)\n[PASS] test_aProofOnlyHoldsForItsOwnWrappedKey() (gas: 416275)\n[PASS] test_aTamperedProofFails() (gas: 768976)\n[PASS] test_madeUpBytesAndTheOldFormatAreFake() (gas: 690806)\n[PASS] test_theRightKeyForSomeoneElseIsProvenFake() (gas: 368314)\n[PASS] test_viewingKeys() (gas: 34725)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 430.41ms (11.51ms CPU time)\n\nRan 15 tests for test/LaunchAudit.t.sol:LaunchAuditTest\n[PASS] testFuzz_memberReplyMustBeExactlyOneWord(uint16,uint256,uint256) (runs: 64, μ: 433408, ~: 434781)\nLogs:\n  Bound result 255600\n\n[PASS] test_attackerCannotInitializeCollectionAsRealHouse() (gas: 1082634)\n[PASS] test_attackerCannotInitializePieceAsRealFactory() (gas: 5034126)\n[PASS] test_attackerCannotInitializePieceAsRealSource() (gas: 5024422)\n[PASS] test_brokenBrokerPassDoesNotBlockEditionPurchase() (gas: 61673474)\n[PASS] test_brokenBrokerPassDoesNotBlockSourceSettlement() (gas: 19657183)\n[PASS] test_brokenPassDoesNotBlockPlainMintsInEitherCurrency() (gas: 2535075)\n[PASS] test_brokerPassMalformedRepliesCountAsIneligible() (gas: 934454)\n[PASS] test_claimedEditionsAreIndependentRuntimesAndStorage() (gas: 104035491)\n[PASS] test_dynamicMemberReplyCannotBypassEditionWindow() (gas: 61590171)\n[PASS] test_dynamicMemberReplyCannotBypassSourceWindow() (gas: 676706)\n[PASS] test_initializerRejectsEOAController() (gas: 6086143)\n[PASS] test_keyPostEventUnchangedBeforeAndAfterClaim() (gas: 67263357)\n[PASS] test_ownerCanClosePrimarySaleAndChangePendingAuctionSplit() (gas: 73212183)\n[PASS] test_plainCollectionIsIndependentRuntime() (gas: 4127353)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 431.38ms (654.19ms CPU time)\n\nRan 3 tests for test/Adversarial.t.sol:RuntimeTest\n[PASS] test_implementationsAreLocked() (gas: 104926)\n[PASS] test_launchedRuntimesAreBoundedAndHaveNoEscapeOpcodes() (gas: 60540280)\n[PASS] test_noRenounceAnywhere() (gas: 155507)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 456.43ms (441.91ms CPU time)\n\nRan 24 tests for test/NothingStuck.t.sol:NothingStuckTest\n[PASS] test_aBuyerNeedsAViewingKeyAProofCanUse() (gas: 67198049)\n[PASS] test_aJunkKeyIsProvenFake_paymentAndDepositToTheBuyer() (gas: 67782335)\n[PASS] test_aSilentSellerLetsTheBuyerCancelAfter24Hours() (gas: 67369506)\n[PASS] test_anAuctionClosedInTimeCannotBeVoided() (gas: 5846482)\n[PASS] test_anAuctionNobodyCanCloseGivesTheBidBack() (gas: 6134344)\n[PASS] test_callbackGasCanOnlyGoUpOnceTheSaleOpens() (gas: 60960821)\n[PASS] test_claimWithoutAKey_after30Days_thenTheKeyGoesIntoThePiece() (gas: 67149952)\n[PASS] test_curatorReKeysAPieceItsPreviousOwnerNeverDid() (gas: 67306108)\n[PASS] test_fallbackDraw_aStartedDrawsResultStands_finishedFromTheHistory() (gas: 61879528)\n[PASS] test_fallbackDraw_chainlinkStillWinsIfItAnswersFirst() (gas: 61646048)\n[PASS] test_fallbackDraw_countsFromThePurchase() (gas: 61768699)\n[PASS] test_fallbackDraw_oneAtATime() (gas: 62757333)\n[PASS] test_fallbackDraw_onlyAfterThreeDays_fromABlockNobodyKnew() (gas: 61803340)\n[PASS] test_fallbackDraw_startsAgainOnlyOnceItsHashIsGone() (gas: 61648636)\n[PASS] test_noProofBeforeAKey_andTheSellerCantDodgeOne() (gas: 67729653)\n[PASS] test_onlyAKeyTheSellerMadeCanBePosted() (gas: 67791236)\n[PASS] test_realKeys_aJunkKeyIsProvenFake() (gas: 907133)\nLogs:\n  gas for the buyer's proveFakeKey: 170130\n\n[PASS] test_realKeys_anHonestKeyCanNeverBeProvenFake() (gas: 1254953)\n[PASS] test_realKeys_theBuyerCantSwapViewingKeysToFrameTheSeller() (gas: 888070)\n[PASS] test_realKeys_theRightKeyWrappedToAnotherKeyIsFake() (gas: 894751)\n[PASS] test_the72HoursCountFromTheKey() (gas: 67790866)\n[PASS] test_theBuyerCantCancelUnderAPendingKey() (gas: 67565859)\n[PASS] test_theDepositIsExactly10Percent() (gas: 67670165)\n[PASS] test_theSellerCanRefundBeforeSendingAKey() (gas: 67476941)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 518.29ms (1.44s CPU time)\n\nRan 5 tests for test/invariants/BuybackConservation.t.sol:BuybackConservationTest\n[PASS]\nBuybackConservationTest invariants:\n[PASS] invariant_ethGoesOnlyToPool\n[PASS] invariant_imdGoesOnlyToBurnDestination\n BuybackConservationTest invariants (runs: 96, calls: 6144, reverts: 0)\n\n╭----------------------------+----------------------+-------+---------+----------╮\n| Contract                   | Selector             | Calls | Reverts | Discards |\n+================================================================================+\n| BuybackConservationHandler | advanceTime          | 656   | 0       | 0        |\n|----------------------------+----------------------+-------+---------+----------|\n| BuybackConservationHandler | burnIMD              | 678   | 0       | 0        |\n|----------------------------+----------------------+-------+---------+----------|\n| BuybackConservationHandler | curatorSwap          | 702   | 0       | 0        |\n|----------------------------+----------------------+-------+---------+----------|\n| BuybackConservationHandler | donateETH            | 679   | 0       | 0        |\n|----------------------------+----------------------+-------+---------+----------|\n| BuybackConservationHandler | donateIMD            | 715   | 0       | 0        |\n|----------------------------+----------------------+-------+---------+----------|\n| BuybackConservationHandler | handover             | 687   | 0       | 0        |\n|----------------------------+----------------------+-------+---------+----------|\n| BuybackConservationHandler | publicSwap           | 711   | 0       | 0        |\n|----------------------------+----------------------+-------+---------+----------|\n| BuybackConservationHandler | rejectedSwap         | 646   | 0       | 0        |\n|----------------------------+----------------------+-------+---------+----------|\n| BuybackConservationHandler | unauthorizedCallback | 670   | 0       | 0        |\n╰----------------------------+----------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 6431\n  Bound result 11099\n  Bound result 11033\n  Bound result 8\n  Bound result 8575\n  Bound result 3389\n  Bound result 5313\n  Bound result 15\n  Bound result 8424\n  Bound result 19728792003956564819967\n  Bound result 1100000000000000000\n  Bound result 1284\n  Bound result 1322\n  Bound result 895\n  Bound result 2616\n  Bound result 51266717031750953809339\n  Bound result 404\n  Bound result 191250000000000000000\n  Bound result 6562\n  Bound result 4832\n\n[PASS] testFuzz_fundingBurnRoundTrip(uint96,uint96) (runs: 1000, μ: 645486, ~: 645550)\nLogs:\n  Bound result 4264337593543950335\n  Bound result 62514264337593543950335\n\n[PASS] test_failedCuratorSwapDoesNotPostponePublicLiveness() (gas: 896798)\nLogs:\n  Bound result 1000000000000000000\n  Bound result 3\n\n[PASS] test_oneWeiSwapAndDirectBurnConserveFunds() (gas: 603515)\nLogs:\n  Bound result 1\n  Bound result 1\n\n[PASS] test_publicSwapDrainsRemainderBelowTheDailyCap() (gas: 334842)\nLogs:\n  Bound result 1\n\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 1.81s (2.24s CPU time)\n\nRan 12 tests for test/Source.t.sol:ArtifactsSourceTest\n[PASS] testFuzz_revealOpensTheSealedSeed(bytes32,bytes32) (runs: 64, μ: 5893771, ~: 5893850)\n[PASS] test_auctionNeedsTheHouseToAcceptTheSale() (gas: 3285282)\n[PASS] test_auctionNeedsTheSourceLocked() (gas: 620659)\n[PASS] test_auctionReopensWhenNoBids() (gas: 441150)\n[PASS] test_auctionRules() (gas: 6733129)\n[PASS] test_bidReentrancyAndRefundPull() (gas: 767944)\n[PASS] test_deliverKeyOnceToTheWinner() (gas: 9241958)\n[PASS] test_noRevealWhileABuyerIsInEscrow() (gas: 9012360)\n[PASS] test_revealServesTheRendererWithItsSeed() (gas: 512490433)\nLogs:\n  revealed tokenURI gas: 2897251\n\n[PASS] test_revealTakesDownAListingWithNoBuyer() (gas: 8943770)\n[PASS] test_storedSeedIsSealed() (gas: 8734200)\n[PASS] test_tinyBidsMustStrictlyExceed() (gas: 940816)\nSuite result: ok. 12 passed; 0 failed; 0 skipped; finished in 1.87s (1.87s CPU time)\n\nRan 1 test for test/invariants/SourceAuctionInvariant.t.sol:SourceAuctionInvariantTest\n[PASS]\nSourceAuctionInvariantTest invariants:\n[PASS] invariant_auctionConservation\n[PASS] invariant_highBidMonotone\n[PASS] invariant_settlementIsFinal\n SourceAuctionInvariantTest invariants (runs: 96, calls: 5760, reverts: 0)\n\n╭----------------+--------------------+-------+---------+----------╮\n| Contract       | Selector           | Calls | Reverts | Discards |\n+==================================================================+\n| AuctionHandler | bid                | 851   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | payloadStaysLocked | 829   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | recordHigh         | 828   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | setAuction         | 794   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | settle             | 834   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | warp               | 852   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | withdrawRefund     | 772   | 0       | 0        |\n╰----------------+--------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 920\n  Bound result 2000000000000003632\n  Bound result 238\n  Bound result 4000000000000004685\n  Bound result 1697\n  Bound result 6000000000000000098\n  Bound result 1199\n  Bound result 8000000000000051970\n  Bound result 737\n  Bound result 200\n  Bound result 8000000000000000406\n  Bound result 546\n  Bound result 707\n  Bound result 724\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.97s (1.96s CPU time)\n\nRan 23 tests for test/Adversarial.t.sol:ArtHouseEdgeTest\n[PASS] testFuzz_everyoneWithdrawsExactlyTheirShare(uint96,uint96,uint96) (runs: 256, μ: 2048171, ~: 2051364)\nLogs:\n  Bound result 1687053956312409914\n  Bound result 29410530796336771647\n  Bound result 1215619572\n\n[PASS] testFuzz_splitConservesAndHouseTakesRounding(uint16,uint16,uint16,uint96,uint8) (runs: 512, μ: 261053, ~: 262826)\nLogs:\n  Bound result 15\n  Bound result 0\n  Bound result 5363\n  Bound result 28723682549529592863503981\n\n[PASS] test_artistEdges() (gas: 1210240)\n[PASS] test_buybackOnlyToTheBurnerSetOnce() (gas: 460935)\n[PASS] test_clearThenReuploadKeepsSizeAccounting() (gas: 40763894)\n[PASS] test_collectionErc721Edges() (gas: 1436052)\n[PASS] test_constructorsDoNotCallDependencies() (gas: 36654)\n[PASS] test_constructorsRejectZeroDependencies() (gas: 4550)\n[PASS] test_curationEdges() (gas: 780836)\n[PASS] test_defaultSplit_agentHouseBurn() (gas: 381579)\n[PASS] test_mintWithIMD_falseReturnRejected() (gas: 2073855)\n[PASS] test_mintWithIMD_feeOnTransferRejected() (gas: 2297085)\n[PASS] test_mintWithIMD_stalePriceRejected() (gas: 1250853)\n[PASS] test_mintZeroPricesReject() (gas: 943137)\n[PASS] test_moduleCollectionsHaveNoPlainCuration() (gas: 376256)\n[PASS] test_pendingOwnerHasNoPowerBeforeAccepting() (gas: 197527)\n[PASS] test_registerModuleCollectionTwiceReverts() (gas: 44789)\n[PASS] test_revokedBrokerKeepsEarnedBalance_butEarnsNoMore() (gas: 1291624)\n[PASS] test_sealEmptyCollectionRevertsAndSealIsOnce() (gas: 657864)\n[PASS] test_splitExtremes() (gas: 1284500)\n[PASS] test_submissionEdges() (gas: 246348)\n[PASS] test_updatePieceAccessEdges() (gas: 1976561)\n[PASS] test_withdrawToRevertingPayoutKeepsBalance() (gas: 1372032)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 2.44s (2.70s CPU time)\n\nRan 16 tests for test/Artifacts.t.sol:ArtifactsFactoryTest\n[PASS] test_buyFailures() (gas: 60997224)\n[PASS] test_buyMany_cannotPassSupply() (gas: 98935498)\n[PASS] test_buyMany_fivePerWallet() (gas: 63854050)\n[PASS] test_buyRecordsSaleAndAssignsEveryEditionOnce() (gas: 177499320)\n[PASS] test_claimFlow_andFailures() (gas: 67455794)\n[PASS] test_postWrappedKeysInOneBatch() (gas: 67751346)\n[PASS] test_publishAndLock_accessAndFailures() (gas: 60947985)\n[PASS] test_rerequestAtOnceWhenTheCoordinatorAnsweredButTheCallbackFailed() (gas: 61872452)\n[PASS] test_rerequestRandomnessAfterDroppedRequest() (gas: 62028891)\n[PASS] test_saleControl() (gas: 61043179)\n[PASS] test_sealTokenURIMatchesR8Frame() (gas: 970411811)\n[PASS] test_viewingKeyZeroRejected() (gas: 33301)\n[PASS] test_vrfCallbackCannotBeReplayed() (gas: 61623145)\n[PASS] test_vrfCallbackGasIsTheCuratorsToTune() (gas: 61431482)\n[PASS] test_vrfCorrectableUntilTheSaleOpens_thenLockedForever() (gas: 62246539)\n[PASS] test_vrfMustBeConfiguredBeforeSelling() (gas: 46850)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 3.51s (4.34s CPU time)\n\nRan 1 test for test/invariants/ArtifactsFactoryInvariant.t.sol:ArtifactsFactoryInvariantTest\n[PASS]\nArtifactsFactoryInvariantTest invariants:\n[PASS] invariant_claimedPiecesBelongToBuyers\n[PASS] invariant_counts\n[PASS] invariant_ledgerHoldsEveryPurchase\n[PASS] invariant_lockedAndPriced\n[PASS] invariant_walletLimit\n ArtifactsFactoryInvariantTest invariants (runs: 96, calls: 5760, reverts: 0)\n\n╭----------------+-------------------+-------+---------+----------╮\n| Contract       | Selector          | Calls | Reverts | Discards |\n+=================================================================+\n| FactoryHandler | buy               | 534   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | buyMany           | 495   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | claim             | 552   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | fulfil            | 497   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | lockedForever     | 508   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | replay            | 536   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | rerequest         | 507   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | setPrice          | 494   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | strangerFulfil    | 564   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | strangerRerequest | 534   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | toggleSale        | 539   | 0       | 0        |\n╰----------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 10008\n  Bound result 51638143296626\n  Bound result 0\n  Bound result 2574237282764180103\n  Bound result 4264337593543950335\n  Bound result 3\n  Bound result 5\n  Bound result 0\n  Bound result 1\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.73s (3.61s CPU time)\n\nRan 1 test for test/invariants/PieceEscrowInvariant.t.sol:PieceEscrowInvariantTest\n[PASS]\nPieceEscrowInvariantTest invariants:\n[PASS] invariant_escrowConservation\n[PASS] invariant_escrowSellerOwns\n[PASS] invariant_royaltyAndIdentity\n[PASS] invariant_singleToken\n PieceEscrowInvariantTest invariants (runs: 96, calls: 5760, reverts: 0)\n\n╭---------------+--------------------+-------+---------+----------╮\n| Contract      | Selector           | Calls | Reverts | Discards |\n+=================================================================+\n| EscrowHandler | approveAndTransfer | 387   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | buy                | 370   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | cancel             | 387   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | delist             | 402   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | list               | 390   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | postKey            | 413   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | proveFake          | 367   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | refundBuyer        | 354   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | registerKey        | 387   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | release            | 391   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | rewrap             | 402   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | transfer           | 407   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | warp               | 366   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | withdraw           | 355   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | withdrawRoyalty    | 382   | 0       | 0        |\n╰---------------+--------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 16105\n  Bound result 50000000000000000000\n  Bound result 20337108042\n  Bound result 111059\n  Bound result 34646\n  Bound result 4070\n  Bound result 1248000\n  Bound result 20880797823880349362\n  Bound result 15077\n  Bound result 576000\n  Bound result 23452612018272603307\n  Bound result 7713\n  Bound result 285478\n  Bound result 149144\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.82s (3.58s CPU time)\n\nRan 1 test for test/invariants/ArtHouseInvariant.t.sol:ArtHouseInvariantTest\n[PASS]\nArtHouseInvariantTest invariants:\n[PASS] invariant_constants\n[PASS] invariant_ethConservation\n[PASS] invariant_imdConservation\n[PASS] invariant_noOverWithdrawal\n[PASS] invariant_supplyAndSeal\n ArtHouseInvariantTest invariants (runs: 128, calls: 5120, reverts: 0)\n\n╭---------------+----------------+-------+---------+----------╮\n| Contract      | Selector       | Calls | Reverts | Discards |\n+=============================================================+\n| LedgerHandler | handOver       | 380   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | mintETH        | 369   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | mintIMD        | 414   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | moduleSale     | 377   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | releaseBuyback | 413   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setBroker      | 396   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setPayout      | 404   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setPrices      | 429   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setSaleOpen    | 378   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setSplit       | 413   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | strangerCalls  | 361   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | withdraw       | 377   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | withdrawHouse  | 409   | 0       | 0        |\n╰---------------+----------------+-------+---------+----------╯\n\nLogs:\n  Bound result 18882627285399\n  Bound result 685\n  Bound result 39746600\n  Bound result 9192389604273781004\n  Bound result 9999\n  Bound result 0\n  Bound result 0\n  Bound result 1073\n  Bound result 5431\n  Bound result 3988\n  Bound result 195\n  Bound result 100000000000000000000\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 7.62s (7.59s CPU time)\n\nRan 4 tests for test/invariants/BrokerClaimsInvariant.t.sol:BrokerClaimsInvariantTest\n[PASS]\nBrokerClaimsInvariantTest invariants:\n[PASS] invariant_claimHistorySurvivesTransfers\n[PASS] invariant_ownershipBalancesAndBrokerRightsAgree\n BrokerClaimsInvariantTest invariants (runs: 96, calls: 6144, reverts: 0)\n\n╭---------------------+------------------+-------+---------+----------╮\n| Contract            | Selector         | Calls | Reverts | Discards |\n+=====================================================================+\n| BrokerClaimsHandler | advanceTime      | 914   | 0       | 0        |\n|---------------------+------------------+-------+---------+----------|\n| BrokerClaimsHandler | claimPiece       | 861   | 0       | 0        |\n|---------------------+------------------+-------+---------+----------|\n| BrokerClaimsHandler | claimSeat        | 869   | 0       | 0        |\n|---------------------+------------------+-------+---------+----------|\n| BrokerClaimsHandler | movePass         | 871   | 0       | 0        |\n|---------------------+------------------+-------+---------+----------|\n| BrokerClaimsHandler | movePiece        | 845   | 0       | 0        |\n|---------------------+------------------+-------+---------+----------|\n| BrokerClaimsHandler | moveSeat         | 891   | 0       | 0        |\n|---------------------+------------------+-------+---------+----------|\n| BrokerClaimsHandler | rejectedTransfer | 893   | 0       | 0        |\n╰---------------------+------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 65536\n  Bound result 9066\n  Bound result 17058\n  Bound result 70400\n  Bound result 47979\n  Bound result 5169\n  Bound result 96\n  Bound result 147852\n  Bound result 127901\n  Bound result 3391\n\n[PASS] test_seatAndPassTransfersDoNotResetEitherClaimLimit() (gas: 1553655)\n[PASS] test_sourceClaimAlsoConsumesTheWalletsSeatEntitlement() (gas: 1137627)\n[PASS] test_startIsInclusiveAndClosedClaimsLeaveNoHistory() (gas: 1893855)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 8.65s (8.56s CPU time)\n\nRan 3 tests for test/invariants/ReviewHistoryInvariant.t.sol:ReviewHistoryInvariantTest\n[PASS]\nReviewHistoryInvariantTest invariants:\n[PASS] invariant_pagesKeepFirstReviewOrderAndLatestContents\n[PASS] invariant_thesisCountsDistinctAuthorsWithoutGrantingBrokerPowers\n[PASS] invariant_votesArePerCredentialAndFinalDecisionsFreezeRecords\n ReviewHistoryInvariantTest invariants (runs: 96, calls: 6144, reverts: 0)\n\n╭----------------------+---------------+-------+---------+----------╮\n| Contract             | Selector      | Calls | Reverts | Discards |\n+===================================================================+\n| ReviewHistoryHandler | advanceTime   | 1002  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| ReviewHistoryHandler | decide        | 963   | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| ReviewHistoryHandler | invalidReview | 1031  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| ReviewHistoryHandler | moveSeat      | 1013  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| ReviewHistoryHandler | review        | 1084  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| ReviewHistoryHandler | thesis        | 1051  | 0       | 0        |\n╰----------------------+---------------+-------+---------+----------╯\n\nLogs:\n  Bound result 77\n  Bound result 14474\n  Bound result 1860768\n  Bound result 3480\n  Bound result 4\n  Bound result 2050137\n  Bound result 2080000\n\n[PASS] test_finalDecisionsFreezeOldAndNewHolderReviews() (gas: 1951545)\n[PASS] test_transferredSeatEditsOneExistingVoiceInPlace() (gas: 1175361)\nLogs:\n  Bound result 1\n\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 12.15s (12.14s CPU time)\n\nRan 13 tests for test/Adversarial.t.sol:ArtifactsEdgeTest\n[PASS] testFuzz_anyWordsAssignDistinctEditions(uint256[8]) (runs: 256, μ: 64646915, ~: 64649001)\n[PASS] testFuzz_sealFramesAnyTraits(uint8,uint8,uint8,uint8,uint8) (runs: 16, μ: 519807080, ~: 519808212)\nLogs:\n  Bound result 7\n\n[PASS] test_buyRevertsAtomicallyWhenCoordinatorReverts() (gas: 59197366)\n[PASS] test_callbackWithNoWordsReverts() (gas: 61547541)\n[PASS] test_claimedPieceIsAFullCopyOfTheImplementation() (gas: 67247088)\n[PASS] test_configureVRFRejectsZeroes() (gas: 211437)\n[PASS] test_duplicateRequestIdRejected() (gas: 59391685)\n[PASS] test_nonOwnerCannotRunTheSale() (gas: 60818098)\n[PASS] test_rerequestIsAtomicWhenCoordinatorReverts() (gas: 59883161)\n[PASS] test_rerequestWindowBoundaryAndChaining() (gas: 67816052)\n[PASS] test_setPieceEdges() (gas: 61051490)\n[PASS] test_unapprovedBuyerAsBrokerEarnsNothing_andOneWeiPriceWorks() (gas: 61487275)\n[PASS] test_wrappedKeyEdges() (gas: 67229754)\nSuite result: ok. 13 passed; 0 failed; 0 skipped; finished in 22.44s (25.77s CPU time)\n\nRan 32 test suites in 22.45s (74.15s CPU time): 244 tests passed, 0 failed, 2 skipped (246 total tests)\n","passed":true},{"durationMs":210,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"ArtCollection.approve(address,uint256)\",\"ArtCollection.initialize(address,string,string)\",\"ArtCollection.mint(address,uint256)\",\"ArtCollection.safeTransferFrom(address,address,uint256)\",\"ArtCollection.safeTransferFrom(address,address,uint256,bytes)\",\"ArtCollection.setApprovalForAll(address,bool)\",\"ArtCollection.transferFrom(address,address,uint256)\",\"ArtHouse.acceptOwnership()\",\"ArtHouse.approveArtist(address,string)\",\"ArtHouse.clearPiece(address,uint256)\",\"ArtHouse.createCollection(string,string,address)\",\"ArtHouse.decideSubmission(uint256,bool)\",\"ArtHouse.finalizePiece(address,uint256)\",\"ArtHouse.mint(address,uint256,address)\",\"ArtHouse.mintWithIMD(address,uint256,address,uint256)\",\"ArtHouse.recordResale(address,uint256,uint256)\",\"ArtHouse.recordSale(address,address,address)\",\"ArtHouse.registerModuleCollection(address,address)\",\"ArtHouse.registerPiece(address,uint256,bytes32,string,string)\",\"ArtHouse.releaseBuyback(address)\",\"ArtHouse.revokeArtist(address)\",\"ArtHouse.sealCollection(address)\",\"ArtHouse.setBroker(address,bool)\",\"ArtHouse.setBrokerPass(address)\",\"ArtHouse.setBuybackBurner(address)\",\"ArtHouse.setPayout(address)\",\"ArtHouse.setPrices(address,uint256,uint256)\",\"ArtHouse.setSaleModule(address,bool)\",\"ArtHouse.setSaleOpen(address,bool)\",\"ArtHouse.setSplit(address,uint16,uint16,uint16,uint16)\",\"ArtHouse.submit(bytes32,string)\",\"ArtHouse.transferOwnership(address)\",\"ArtHouse.updatePiece(address,uint256,bytes32,string,string)\",\"ArtHouse.uploadChunk(address,uint256,uint256,bytes)\",\"ArtHouse.withdraw(address)\",\"ArtHouse.withdrawHouse(address)\",\"ArtStorage.acceptOwnership()\",\"ArtStorage.clear(address,uint256)\",\"ArtStorage.setHouse(address)\",\"ArtStorage.transferOwnership(address)\",\"ArtStorage.write(address,uint256,uint256,bytes)\",\"ArtifactsFactory.acceptOwnership()\",\"ArtifactsFactory.buy(address)\",\"ArtifactsFactory.buyMany(uint256,address)\",\"ArtifactsFactory.buyWithSeat(uint256,uint256,address)\",\"ArtifactsFactory.claim(uint256)\",\"ArtifactsFactory.claimMany(uint256[])\",\"ArtifactsFactory.configureVRF(address,bytes32,uint256,bool)\",\"ArtifactsFactory.endSale()\",\"ArtifactsFactory.finishFallbackDraw(uint256)\",\"ArtifactsFactory.lock()\",\"ArtifactsFactory.postWrappedKey(uint256,bytes)\",\"ArtifactsFactory.postWrappedKeys(uint256[],bytes[])\",\"ArtifactsFactory.rawFulfillRandomWords(uint256,uint256[])\",\"ArtifactsFactory.registerViewingKey(bytes32)\",\"ArtifactsFactory.rerequestRandomness(uint256)\",\"ArtifactsFactory.setGate(address,address,uint256,uint64)\",\"ArtifactsFactory.setMemberGate(address,bytes4,uint256)\",\"ArtifactsFactory.setMintPhases(uint64,uint8,uint64,uint8)\",\"ArtifactsFactory.setPiece(uint256,(string,string,uint8,string),bytes,bytes32)\",\"ArtifactsFactory.setPrice(uint256)\",\"ArtifactsFactory.setSaleOpen(bool)\",\"ArtifactsFactory.setVRFCallbackGas(uint32)\",\"ArtifactsFactory.startFallbackDraw(uint256)\",\"ArtifactsFactory.transferOwnership(address)\",\"ArtifactsPiece.approve(address,uint256)\",\"ArtifactsPiece.buy(bytes32,address)\",\"ArtifactsPiece.cancel()\",\"ArtifactsPiece.delist()\",\"ArtifactsPiece.initialize(address,address,uint256,address,(string,string,uint8,string),address,bytes32,bytes,bool,bytes32)\",\"ArtifactsPiece.list(uint256)\",\"ArtifactsPiece.postEscrowKey(bytes,address,uint256)\",\"ArtifactsPiece.proveFakeKey((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256))\",\"ArtifactsPiece.refundBuyer()\",\"ArtifactsPiece.registerViewingKey(bytes32)\",\"ArtifactsPiece.release()\",\"ArtifactsPiece.reveal(bytes32)\",\"ArtifactsPiece.rewrapFor(bytes)\",\"ArtifactsPiece.safeTransferFrom(address,address,uint256)\",\"ArtifactsPiece.safeTransferFrom(address,address,uint256,bytes)\",\"ArtifactsPiece.setApprovalForAll(address,bool)\",\"ArtifactsPiece.transferFrom(address,address,uint256)\",\"ArtifactsPiece.withdraw()\",\"ArtifactsSource.acceptOwnership()\",\"ArtifactsSource.bid(address)\",\"ArtifactsSource.deliverKey(bytes)\",\"ArtifactsSource.lock(bytes32,bytes32)\",\"ArtifactsSource.resetRenderer()\",\"ArtifactsSource.setAuction(uint256,uint64)\",\"ArtifactsSource.setGate(address,address,uint256,uint64)\",\"ArtifactsSource.setMemberGate(address,bytes4,uint256)\",\"ArtifactsSource.settle()\",\"ArtifactsSource.storeRendererChunk(bytes)\",\"ArtifactsSource.transferOwnership(address)\",\"ArtifactsSource.voidUnsettled()\",\"ArtifactsSource.withdrawRefund()\",\"BrokerPass.approve(address,uint256)\",\"BrokerPass.claimWithPiece(uint256)\",\"BrokerPass.claimWithSeat(uint256)\",\"BrokerPass.safeTransferFrom(address,address,uint256)\",\"BrokerPass.safeTransferFrom(address,address,uint256,bytes)\",\"BrokerPass.setApprovalForAll(address,bool)\",\"BrokerPass.setClaimsOpenAt(uint64)\",\"BrokerPass.transferFrom(address,address,uint256)\",\"ImdBuybackBurner.burnEth(uint256,uint256,uint256)\",\"ImdBuybackBurner.burnImd()\",\"ImdBuybackBurner.receive()\",\"ImdBuybackBurner.unlockCallback(bytes)\",\"SubmissionReviews.applyAsBroker(string)\",\"SubmissionReviews.postThesis(uint256,string)\",\"SubmissionReviews.reviewAsPiece(uint256,uint256,uint8,string)\",\"SubmissionReviews.reviewAsSeat(uint256,uint256,uint8,string)\"],\"files\":{\".gitignore\":3,\"ADAPTATION.md\":248,\"README.md\":261,\"foundry.toml\":25,\"launch.burner.json\":17,\"launch.json\":63,\"reference/PROTOCOL.md\":99,\"reference/RULES.md\":137,\"reference/audit/V13Audit.t.sol.txt\":381,\"reference/check-framed.js\":25,\"reference/framed/framed-003.svg\":1,\"reference/framed/framed-MASTER.svg\":1,\"reference/rules.js\":145,\"reference/the-source.renderer.html\":148,\"remappings.txt\":1,\"script/Deploy.s.sol\":39,\"src/ArtCollection.sol\":55,\"src/ArtHouse.sol\":609,\"src/ArtStorage.sol\":82,\"src/ArtifactsFactory.sol\":622,\"src/ArtifactsPiece.sol\":457,\"src/ArtifactsSource.sol\":271,\"src/BrokerPass.sol\":142,\"src/ImdBuybackBurner.sol\":163,\"src/KeyProof.sol\":154,\"src/SubmissionReviews.sol\":215,\"src/base/ERC721Lite.sol\":122,\"src/base/HolderGate.sol\":109,\"src/base/ReentrancyGuard.sol\":15,\"src/base/TwoStepOwnable.sol\":40,\"src/interfaces/Interfaces.sol\":93,\"src/libs/Clones.sol\":19,\"src/libs/Encoding.sol\":79,\"src/libs/SSTORE2.sol\":41,\"src/libs/Seal.sol\":102,\"test/Adversarial.t.sol\":1409,\"test/ArtHouse.t.sol\":463,\"test/Artifacts.t.sol\":673,\"test/AuditRound3.t.sol\":151,\"test/BrokerPass.t.sol\":373,\"test/Burner.t.sol\":161,\"test/ClaimEnd.t.sol\":152,\"test/Fixture.sol\":230,\"test/Gate.t.sol\":295,\"test/KeyProof.t.sol\":134,\"test/LaunchAudit.t.sol\":338,\"test/LaunchDeployment.t.sol\":191,\"test/NothingStuck.t.sol\":568,\"test/Phases.t.sol\":130,\"test/Reviews.t.sol\":264,\"test/Source.t.sol\":396,\"test/audit/KeyProofEdges.t.sol\":178,\"test/audit/KeyReuseLeak.t.sol\":38,\"test/fixtures/keyproof.json\":81,\"test/fork/BurnerFork.t.sol\":70,\"test/fork/VrfFork.t.sol\":131,\"test/invariants/ADDED_COVERAGE.md\":19,\"test/invariants/ArtHouseInvariant.t.sol\":444,\"test/invariants/ArtifactsFactoryInvariant.t.sol\":323,\"test/invariants/BrokerClaimsInvariant.t.sol\":275,\"test/invariants/BuybackConservation.t.sol\":246,\"test/invariants/PieceEscrowInvariant.t.sol\":445,\"test/invariants/ReviewHistoryInvariant.t.sol\":245,\"test/invariants/SourceAuctionInvariant.t.sol\":227,\"test/mocks/AdversarialMocks.sol\":134,\"test/mocks/MockPoolManager.sol\":57,\"test/mocks/MockSeats.sol\":27,\"test/mocks/Mocks.sol\":149,\"test/mocks/TestVRFCoordinator.sol\":46,\"test/utils/Base64Decode.sol\":83},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"c44a54d365dd12f1b5b9154b2b0b9b2c7cbb7760ecfde1d7f5001bc15ec62814","verifiedTreeHash":"ab0f3bd9707ad43d3598f55700d958387af06854","verifierVersion":"0.1.0+745c1db4"},{"checks":[{"durationMs":376617,"exitCode":0,"name":"build","output":"Compiling 68 files with Solc 0.8.26\nSolc 0.8.26 finished in 376.49s\nCompiler run successful with warnings:\nWarning (5667): Unused function parameter. Remove or comment out the variable name to silence this warning.\n   --> test/invariants/ArtHouseInvariant.t.sol:105:9:\n    |\n105 |         address buyer,\n    |         ^^^^^^^^^^^^^\n\n","passed":true},{"durationMs":11240,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 1 test for test/fork/BurnerFork.t.sol:BurnerForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 433.14µs (0.00ns CPU time)\n\nRan 1 test for test/fork/VrfFork.t.sol:VrfForkTest\n[SKIP: skipped] setUp() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 1 skipped; finished in 796.26µs (0.00ns CPU time)\n\nRan 5 tests for test/audit/KeyProofEdges.t.sol:KeyProofEdgesTest\n[PASS] test_adversarialE_isProvable() (gas: 107849)\n[PASS] test_adversarialE_proofIsActuallyChecked() (gas: 23615)\n[PASS] test_negatedSCannotFrame() (gas: 60700)\n[PASS] test_oddYWrapThatOpensIsNotFake() (gas: 37558)\n[PASS] test_xEqualsN_isMalformed() (gas: 13218)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 1.98ms (2.89ms CPU time)\n\nRan 1 test for test/ClaimEnd.t.sol:EndBeforeOpenTest\n[PASS] test_endSale_beforeOpening_refused() (gas: 60691353)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 17.95ms (15.47ms CPU time)\n\nRan 4 tests for test/AuditRound3.t.sol:AuditRound3Test\n[PASS] test_aReturnDataBombCostsThePayerNothing() (gas: 694152)\n[PASS] test_aShareThatWaitsInTheLedgerIsAnnounced() (gas: 339919)\n[PASS] test_theArtistsPayoutCantMoveThePieceDuringARelease() (gas: 415877)\n[PASS] test_theArtistsPayoutCantRelistDuringARelease() (gas: 600564)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 28.94ms (916.63µs CPU time)\n\nRan 5 tests for test/ClaimEnd.t.sol:ClaimEndTest\n[PASS] test_claimMany_claimsEveryOneInOneCall() (gas: 18151497)\n[PASS] test_claimMany_emptyRefused_andTheCuratorCanClaimForBuyers() (gas: 12311987)\n[PASS] test_claimMany_isAllOrNothing() (gas: 18205777)\n[PASS] test_endSale_isFinal() (gas: 6923933)\n[PASS] test_endSale_needsTheSaleToHaveOpened_andWorksWhileClosed() (gas: 96083)\nSuite result: ok. 5 passed; 0 failed; 0 skipped; finished in 30.71ms (4.60ms CPU time)\n\nRan 10 tests for test/Artifacts.t.sol:ArtifactsPieceEscrowTest\n[PASS] test_escrowCancelBeforeKey_andDelist() (gas: 501042)\n[PASS] test_escrowHappyPath_buyerConfirms() (gas: 1181854)\n[PASS] test_escrowKeyMustNotBeEmpty() (gas: 310921)\n[PASS] test_escrowTimeoutRelease() (gas: 728994)\n[PASS] test_pieceViewingKeyZeroRejected() (gas: 168689)\n[PASS] test_plainTransferClearsKey_previousOwnerRekeys() (gas: 506819)\n[PASS] test_reentrancyOnEscrowWithdrawBlocked() (gas: 844317)\n[PASS] test_rewrapIsOneShotAndNonEmpty() (gas: 284134)\n[PASS] test_sellerCannotOverwriteKeyAfterRelease() (gas: 913301)\n[PASS] test_sourceOnlyReveal() (gas: 35552)\nSuite result: ok. 10 passed; 0 failed; 0 skipped; finished in 32.14ms (3.91ms CPU time)\n\nRan 1 test for test/audit/KeyReuseLeak.t.sol:KeyReuseLeakTest\n[PASS] test_copiedE_cantBePosted(uint256,uint256) (runs: 64, μ: 603054, ~: 603215)\nLogs:\n  Bound result 6677771717396745857438524715775791381032702405673290885595687978682\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 39.78ms (35.73ms CPU time)\n\nRan 18 tests for test/BrokerPass.t.sol:BrokerPassTest\n[PASS] test_capIs100() (gas: 19752778)\n[PASS] test_claimWithPiece_onceEverPerPiece() (gas: 6679912)\n[PASS] test_claimWithSeat_onceEverPerSeat() (gas: 376003)\n[PASS] test_claimWithTheSource() (gas: 6010301)\n[PASS] test_claimsWaitForTheStartTime_setOnceByTheCurator() (gas: 489742)\n[PASS] test_oneClaimPerWallet() (gas: 6980812)\n[PASS] test_passHolderCanBrokerTheirOwnBuy() (gas: 1019992)\n[PASS] test_passHolderEarnsOnMint_andTheRightMovesWithThePass() (gas: 2081372)\n[PASS] test_recordResaleRejectsAnythingButAPiece() (gas: 298286)\n[PASS] test_resaleBrokerShare_creditedInTheLedger() (gas: 7295006)\n[PASS] test_resaleBuyerWithAPassCanBrokerTheirOwnBuy() (gas: 7232310)\n[PASS] test_resaleFallsBackToThePieceWhenTheLedgerRefuses() (gas: 7247411)\n[PASS] test_resaleSellerCannotBeBroker() (gas: 7144850)\n[PASS] test_resaleWithoutEligibleBroker_sellerKeepsTheShare() (gas: 6934008)\n[PASS] test_setBrokerPassOnce() (gas: 64999)\n[PASS] test_sourceSplit_brokerAndArtistOnly() (gas: 6162142)\n[PASS] test_sourceSplit_noBrokerBurns() (gas: 5919583)\n[PASS] test_tokenURIIsOnChainJson() (gas: 388848)\nSuite result: ok. 18 passed; 0 failed; 0 skipped; finished in 50.59ms (20.78ms CPU time)\n\nRan 6 tests for test/Adversarial.t.sol:PieceEdgeTest\n[PASS] test_cancelThenSecondBuyerAndRoyaltyToChangedPayout() (gas: 1087998)\n[PASS] test_listingEdges() (gas: 1002975)\n[PASS] test_releaseAtExactly72HoursByStranger() (gas: 914016)\n[PASS] test_revealNeedsTheSourceLocked_andEmptyRendererURI() (gas: 6265659)\n[PASS] test_safeTransferReceivers() (gas: 670237)\n[PASS] test_transferAuthEdges() (gas: 350213)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 54.10ms (5.96ms CPU time)\n\nRan 21 tests for test/ArtHouse.t.sol:ArtHouseTest\n[PASS] testFuzz_ethSplitInvariant(uint96,bool,bool) (runs: 64, μ: 1218376, ~: 1239979)\n[PASS] testFuzz_imdSplitInvariant(uint96,bool) (runs: 64, μ: 1311558, ~: 1314827)\n[PASS] test_artistPayoutOnlyArtist_keptOnReapproval() (gas: 179207)\n[PASS] test_collectionMintOnlyHouse() (gas: 73967)\n[PASS] test_curationFlow_andFailures() (gas: 938837)\n[PASS] test_customSplit() (gas: 1124713)\n[PASS] test_deploymentWiring() (gas: 93139)\n[PASS] test_imdBuybackIsReleasedAndBurned() (gas: 1882866)\n[PASS] test_mintFailures() (gas: 1550882)\n[PASS] test_onlyCuratorApproves() (gas: 123827)\n[PASS] test_pieceOver100KBRejected() (gas: 21310484)\n[PASS] test_recordSaleOnlyModules() (gas: 120446)\n[PASS] test_reentrancyOnWithdrawBlocked() (gas: 1838346)\n[PASS] test_revokedArtistLosesCuration() (gas: 582575)\n[PASS] test_sealNeedsEveryPieceFinalized() (gas: 527413)\n[PASS] test_setHouseOnce() (gas: 78294)\n[PASS] test_submissions() (gas: 260658)\n[PASS] test_tokenURIOnChain() (gas: 1190981)\n[PASS] test_twoStepOwnership_noRenounce() (gas: 198046)\n[PASS] test_withdrawNothingReverts_andHouseGoesToCurrentOwner() (gas: 1241987)\n[PASS] test_wrongHashIsCorrectable() (gas: 777075)\nSuite result: ok. 21 passed; 0 failed; 0 skipped; finished in 55.38ms (59.05ms CPU time)\n\nRan 4 tests for test/Phases.t.sol:PhasesTest\n[PASS] test_aSeatFollowsThePhases_whereverItGoes() (gas: 1747729)\n[PASS] test_afterTheWindow_anyoneUpToFive() (gas: 1042332)\n[PASS] test_capsRise_1_then_2_then_5_forAnImdHolder() (gas: 1740786)\n[PASS] test_setOnlyBeforeTheSaleOpens_andChecked() (gas: 322444)\nSuite result: ok. 4 passed; 0 failed; 0 skipped; finished in 62.22ms (4.89ms CPU time)\n\nRan 12 tests for test/Gate.t.sol:GateTest\n[PASS] test_aHostileMembershipContractCountsAsNotMember() (gas: 62498580)\n[PASS] test_auction_gateFixedFromTheFirstBid() (gas: 714486)\n[PASS] test_auction_holdersFirstThenAnyone() (gas: 948357)\n[PASS] test_auction_membersBid_andTheMemberGateIsFixedFromTheFirstBid() (gas: 1006759)\n[PASS] test_brokenSeatContractCountsAsNotHeld() (gas: 61030533)\n[PASS] test_editions_gateFixedOnceTheSaleOpens() (gas: 61529270)\n[PASS] test_editions_holdersFirstThenAnyone() (gas: 62031024)\n[PASS] test_editions_membersBuyInTheWindow_asTokenHoldersDo() (gas: 62059284)\n[PASS] test_editions_noGateMeansOpen() (gas: 61274007)\n[PASS] test_editions_seatBuysUpToFivePerSeatWhereverItGoes() (gas: 62695849)\n[PASS] test_gateRules() (gas: 239527)\n[PASS] test_memberGateRules() (gas: 61261926)\nSuite result: ok. 12 passed; 0 failed; 0 skipped; finished in 123.52ms (141.99ms CPU time)\n\nRan 11 tests for test/Reviews.t.sol:ReviewsTest\n[PASS] testFuzz_tallyMatchesVoices(uint8[12]) (runs: 64, μ: 1441587, ~: 1442057)\n[PASS] test_aClaimedPieceIsAVoice_andAnUnclaimedOneIsNot() (gas: 67621657)\n[PASS] test_aMovedSeatStillHasOneVoice() (gas: 441792)\n[PASS] test_aSeatAndAPieceInOneWalletAreTwoVoices() (gas: 67346389)\n[PASS] test_anyoneAppliesToBeABroker() (gas: 224553)\n[PASS] test_anyonePublishesTheses() (gas: 810776)\n[PASS] test_changingAReviewMovesItsVote() (gas: 305393)\n[PASS] test_frozenOnceTheCuratorDecides_andAdvisoryOnly() (gas: 349039)\n[PASS] test_inputChecks() (gas: 307196)\n[PASS] test_onlyTheSeatHolderReviews() (gas: 97570)\n[PASS] test_seatsReview_andTheTallyFollows() (gas: 457095)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 123.47ms (84.06ms CPU time)\n\nRan 2 tests for test/LaunchDeployment.t.sol:LaunchDeploymentTest\n[PASS] test_allEightConstructorsAcceptCodeLessDependencies() (gas: 75376878)\n[PASS] test_manifestOrderAndOwnerConfigurationRemainIntact() (gas: 82011018)\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 127.77ms (240.58ms CPU time)\n\nRan 15 tests for test/LaunchAudit.t.sol:LaunchAuditTest\n[PASS] testFuzz_memberReplyMustBeExactlyOneWord(uint16,uint256,uint256) (runs: 64, μ: 432924, ~: 434817)\nLogs:\n  Bound result 300000\n\n[PASS] test_attackerCannotInitializeCollectionAsRealHouse() (gas: 1082634)\n[PASS] test_attackerCannotInitializePieceAsRealFactory() (gas: 5034126)\n[PASS] test_attackerCannotInitializePieceAsRealSource() (gas: 5024422)\n[PASS] test_brokenBrokerPassDoesNotBlockEditionPurchase() (gas: 61673474)\n[PASS] test_brokenBrokerPassDoesNotBlockSourceSettlement() (gas: 19657183)\n[PASS] test_brokenPassDoesNotBlockPlainMintsInEitherCurrency() (gas: 2535075)\n[PASS] test_brokerPassMalformedRepliesCountAsIneligible() (gas: 934454)\n[PASS] test_claimedEditionsAreIndependentRuntimesAndStorage() (gas: 104035491)\n[PASS] test_dynamicMemberReplyCannotBypassEditionWindow() (gas: 61590171)\n[PASS] test_dynamicMemberReplyCannotBypassSourceWindow() (gas: 676706)\n[PASS] test_initializerRejectsEOAController() (gas: 6086143)\n[PASS] test_keyPostEventUnchangedBeforeAndAfterClaim() (gas: 67263357)\n[PASS] test_ownerCanClosePrimarySaleAndChangePendingAuctionSplit() (gas: 73212183)\n[PASS] test_plainCollectionIsIndependentRuntime() (gas: 4127353)\nSuite result: ok. 15 passed; 0 failed; 0 skipped; finished in 131.22ms (225.69ms CPU time)\n\nRan 3 tests for test/Adversarial.t.sol:RuntimeTest\n[PASS] test_implementationsAreLocked() (gas: 104926)\n[PASS] test_launchedRuntimesAreBoundedAndHaveNoEscapeOpcodes() (gas: 60540280)\n[PASS] test_noRenounceAnywhere() (gas: 155507)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 150.83ms (147.13ms CPU time)\n\nRan 8 tests for test/KeyProof.t.sol:KeyProofTest\n[PASS] test_aJunkKeyIsProvenFake() (gas: 369871)\nLogs:\n  gas to check a fake-key proof: 44805\n\n[PASS] test_aKeyThatOpensIsNeverProvenFake() (gas: 368087)\n[PASS] test_aProofOnlyHoldsForItsBuyerPieceAndChain() (gas: 416867)\n[PASS] test_aProofOnlyHoldsForItsOwnWrappedKey() (gas: 416275)\n[PASS] test_aTamperedProofFails() (gas: 768976)\n[PASS] test_madeUpBytesAndTheOldFormatAreFake() (gas: 690806)\n[PASS] test_theRightKeyForSomeoneElseIsProvenFake() (gas: 368314)\n[PASS] test_viewingKeys() (gas: 34725)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 157.37ms (7.35ms CPU time)\n\nRan 7 tests for test/Adversarial.t.sol:SourceEdgeTest\n[PASS] testFuzz_minimumRaiseIsCeilingOfFivePercent(uint96,uint96) (runs: 512, μ: 629587, ~: 629679)\nLogs:\n  Bound result 3354463538038\n  Bound result 1000000006029917588\n\n[PASS] testFuzz_rendererHashIsKeccakOfConcatenation(bytes,bytes,bytes) (runs: 64, μ: 419688, ~: 416599)\n[PASS] test_bidBoundaries() (gas: 901651)\n[PASS] test_payloadChunkLimits() (gas: 5443288)\n[PASS] test_setAuctionEdges() (gas: 459334)\n[PASS] test_settleEdges_brokerSplit() (gas: 6966012)\n[PASS] test_settleWithUnapprovedBrokerPaysTheBurn() (gas: 5869414)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 157.40ms (80.85ms CPU time)\n\nRan 23 tests for test/Adversarial.t.sol:ArtHouseEdgeTest\n[PASS] testFuzz_everyoneWithdrawsExactlyTheirShare(uint96,uint96,uint96) (runs: 256, μ: 2048171, ~: 2051364)\nLogs:\n  Bound result 1991214\n  Bound result 88966114747433248107\n  Bound result 150691221\n\n[PASS] testFuzz_splitConservesAndHouseTakesRounding(uint16,uint16,uint16,uint96,uint8) (runs: 512, μ: 261218, ~: 262826)\nLogs:\n  Bound result 85\n  Bound result 9\n  Bound result 7039\n  Bound result 5412\n\n[PASS] test_artistEdges() (gas: 1210240)\n[PASS] test_buybackOnlyToTheBurnerSetOnce() (gas: 460935)\n[PASS] test_clearThenReuploadKeepsSizeAccounting() (gas: 40763894)\n[PASS] test_collectionErc721Edges() (gas: 1436052)\n[PASS] test_constructorsDoNotCallDependencies() (gas: 36654)\n[PASS] test_constructorsRejectZeroDependencies() (gas: 4550)\n[PASS] test_curationEdges() (gas: 780836)\n[PASS] test_defaultSplit_agentHouseBurn() (gas: 381579)\n[PASS] test_mintWithIMD_falseReturnRejected() (gas: 2073855)\n[PASS] test_mintWithIMD_feeOnTransferRejected() (gas: 2297085)\n[PASS] test_mintWithIMD_stalePriceRejected() (gas: 1250853)\n[PASS] test_mintZeroPricesReject() (gas: 943137)\n[PASS] test_moduleCollectionsHaveNoPlainCuration() (gas: 376256)\n[PASS] test_pendingOwnerHasNoPowerBeforeAccepting() (gas: 197527)\n[PASS] test_registerModuleCollectionTwiceReverts() (gas: 44789)\n[PASS] test_revokedBrokerKeepsEarnedBalance_butEarnsNoMore() (gas: 1291624)\n[PASS] test_sealEmptyCollectionRevertsAndSealIsOnce() (gas: 657864)\n[PASS] test_splitExtremes() (gas: 1284500)\n[PASS] test_submissionEdges() (gas: 246348)\n[PASS] test_updatePieceAccessEdges() (gas: 1976561)\n[PASS] test_withdrawToRevertingPayoutKeepsBalance() (gas: 1372032)\nSuite result: ok. 23 passed; 0 failed; 0 skipped; finished in 175.62ms (204.31ms CPU time)\n\nRan 7 tests for test/Burner.t.sol:BurnerTest\n[PASS] test_anyoneBurnsHeldImd() (gas: 169949)\n[PASS] test_anyoneSwapsInSmallStepsAfter60QuietDays() (gas: 845755)\n[PASS] test_constructorChecks() (gas: 8711)\n[PASS] test_editionSaleToBurnedImd() (gas: 61798551)\n[PASS] test_onlyTheCuratorSwaps_withAMinimumAndADeadline() (gas: 653639)\n[PASS] test_onlyThePoolManagerCallsBack() (gas: 32189)\n[PASS] test_theNewOwnerSwapsAfterAHandover() (gas: 304000)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 212.90ms (28.33ms CPU time)\n\nRan 12 tests for test/Source.t.sol:ArtifactsSourceTest\n[PASS] testFuzz_revealOpensTheSealedSeed(bytes32,bytes32) (runs: 64, μ: 5893765, ~: 5893838)\n[PASS] test_auctionNeedsTheHouseToAcceptTheSale() (gas: 3285282)\n[PASS] test_auctionNeedsTheSourceLocked() (gas: 620659)\n[PASS] test_auctionReopensWhenNoBids() (gas: 441150)\n[PASS] test_auctionRules() (gas: 6733129)\n[PASS] test_bidReentrancyAndRefundPull() (gas: 767944)\n[PASS] test_deliverKeyOnceToTheWinner() (gas: 9241958)\n[PASS] test_noRevealWhileABuyerIsInEscrow() (gas: 9012360)\n[PASS] test_revealServesTheRendererWithItsSeed() (gas: 512490433)\nLogs:\n  revealed tokenURI gas: 2897251\n\n[PASS] test_revealTakesDownAListingWithNoBuyer() (gas: 8943770)\n[PASS] test_storedSeedIsSealed() (gas: 8734200)\n[PASS] test_tinyBidsMustStrictlyExceed() (gas: 940816)\nSuite result: ok. 12 passed; 0 failed; 0 skipped; finished in 861.71ms (879.88ms CPU time)\n\nRan 1 test for test/invariants/SourceAuctionInvariant.t.sol:SourceAuctionInvariantTest\n[PASS]\nSourceAuctionInvariantTest invariants:\n[PASS] invariant_auctionConservation\n[PASS] invariant_highBidMonotone\n[PASS] invariant_settlementIsFinal\n SourceAuctionInvariantTest invariants (runs: 96, calls: 5760, reverts: 0)\n\n╭----------------+--------------------+-------+---------+----------╮\n| Contract       | Selector           | Calls | Reverts | Discards |\n+==================================================================+\n| AuctionHandler | bid                | 851   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | payloadStaysLocked | 829   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | recordHigh         | 828   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | setAuction         | 794   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | settle             | 834   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | warp               | 852   | 0       | 0        |\n|----------------+--------------------+-------+---------+----------|\n| AuctionHandler | withdrawRefund     | 772   | 0       | 0        |\n╰----------------+--------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 920\n  Bound result 2000000000000003632\n  Bound result 238\n  Bound result 4000000000000004685\n  Bound result 1697\n  Bound result 511\n  Bound result 6000000000000022905\n  Bound result 8000000000000000990\n  Bound result 1400\n  Bound result 600\n  Bound result 3493\n  Bound result 10000000000000000407\n  Bound result 10000000000818771063\n  Bound result 523\n  Bound result 97\n  Bound result 10000000000000000255\n  Bound result 606\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 880.36ms (876.01ms CPU time)\n\nRan 24 tests for test/NothingStuck.t.sol:NothingStuckTest\n[PASS] test_aBuyerNeedsAViewingKeyAProofCanUse() (gas: 67198049)\n[PASS] test_aJunkKeyIsProvenFake_paymentAndDepositToTheBuyer() (gas: 67782335)\n[PASS] test_aSilentSellerLetsTheBuyerCancelAfter24Hours() (gas: 67369506)\n[PASS] test_anAuctionClosedInTimeCannotBeVoided() (gas: 5846482)\n[PASS] test_anAuctionNobodyCanCloseGivesTheBidBack() (gas: 6134344)\n[PASS] test_callbackGasCanOnlyGoUpOnceTheSaleOpens() (gas: 60960821)\n[PASS] test_claimWithoutAKey_after30Days_thenTheKeyGoesIntoThePiece() (gas: 67149952)\n[PASS] test_curatorReKeysAPieceItsPreviousOwnerNeverDid() (gas: 67306108)\n[PASS] test_fallbackDraw_aStartedDrawsResultStands_finishedFromTheHistory() (gas: 61879528)\n[PASS] test_fallbackDraw_chainlinkStillWinsIfItAnswersFirst() (gas: 61646048)\n[PASS] test_fallbackDraw_countsFromThePurchase() (gas: 61768699)\n[PASS] test_fallbackDraw_oneAtATime() (gas: 62757333)\n[PASS] test_fallbackDraw_onlyAfterThreeDays_fromABlockNobodyKnew() (gas: 61803340)\n[PASS] test_fallbackDraw_startsAgainOnlyOnceItsHashIsGone() (gas: 61648636)\n[PASS] test_noProofBeforeAKey_andTheSellerCantDodgeOne() (gas: 67729653)\n[PASS] test_onlyAKeyTheSellerMadeCanBePosted() (gas: 67791236)\n[PASS] test_realKeys_aJunkKeyIsProvenFake() (gas: 907133)\nLogs:\n  gas for the buyer's proveFakeKey: 170130\n\n[PASS] test_realKeys_anHonestKeyCanNeverBeProvenFake() (gas: 1254953)\n[PASS] test_realKeys_theBuyerCantSwapViewingKeysToFrameTheSeller() (gas: 888070)\n[PASS] test_realKeys_theRightKeyWrappedToAnotherKeyIsFake() (gas: 894751)\n[PASS] test_the72HoursCountFromTheKey() (gas: 67790866)\n[PASS] test_theBuyerCantCancelUnderAPendingKey() (gas: 67565859)\n[PASS] test_theDepositIsExactly10Percent() (gas: 67670165)\n[PASS] test_theSellerCanRefundBeforeSendingAKey() (gas: 67476941)\nSuite result: ok. 24 passed; 0 failed; 0 skipped; finished in 1.19s (462.71ms CPU time)\n\nRan 1 test for test/invariants/PieceEscrowInvariant.t.sol:PieceEscrowInvariantTest\n[PASS]\nPieceEscrowInvariantTest invariants:\n[PASS] invariant_escrowConservation\n[PASS] invariant_escrowSellerOwns\n[PASS] invariant_royaltyAndIdentity\n[PASS] invariant_singleToken\n PieceEscrowInvariantTest invariants (runs: 96, calls: 5760, reverts: 0)\n\n╭---------------+--------------------+-------+---------+----------╮\n| Contract      | Selector           | Calls | Reverts | Discards |\n+=================================================================+\n| EscrowHandler | approveAndTransfer | 387   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | buy                | 370   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | cancel             | 387   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | delist             | 402   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | list               | 390   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | postKey            | 413   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | proveFake          | 367   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | refundBuyer        | 354   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | registerKey        | 387   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | release            | 391   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | rewrap             | 402   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | transfer           | 407   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | warp               | 366   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | withdraw           | 355   | 0       | 0        |\n|---------------+--------------------+-------+---------+----------|\n| EscrowHandler | withdrawRoyalty    | 382   | 0       | 0        |\n╰---------------+--------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 16105\n  Bound result 1500000000000000000\n  Bound result 4274151582\n  Bound result 20337108042\n  Bound result 111059\n  Bound result 34646\n  Bound result 4070\n  Bound result 1000000000000000000\n  Bound result 544000\n  Bound result 20880797823880349362\n  Bound result 259200\n  Bound result 104089\n  Bound result 544000\n  Bound result 47915958131739435367\n  Bound result 10000\n  Bound result 285478\n  Bound result 149144\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.47s (1.42s CPU time)\n\nRan 16 tests for test/Artifacts.t.sol:ArtifactsFactoryTest\n[PASS] test_buyFailures() (gas: 60997224)\n[PASS] test_buyMany_cannotPassSupply() (gas: 98935498)\n[PASS] test_buyMany_fivePerWallet() (gas: 63854050)\n[PASS] test_buyRecordsSaleAndAssignsEveryEditionOnce() (gas: 177499320)\n[PASS] test_claimFlow_andFailures() (gas: 67455794)\n[PASS] test_postWrappedKeysInOneBatch() (gas: 67751346)\n[PASS] test_publishAndLock_accessAndFailures() (gas: 60947985)\n[PASS] test_rerequestAtOnceWhenTheCoordinatorAnsweredButTheCallbackFailed() (gas: 61872452)\n[PASS] test_rerequestRandomnessAfterDroppedRequest() (gas: 62028891)\n[PASS] test_saleControl() (gas: 61043179)\n[PASS] test_sealTokenURIMatchesR8Frame() (gas: 970411811)\n[PASS] test_viewingKeyZeroRejected() (gas: 33301)\n[PASS] test_vrfCallbackCannotBeReplayed() (gas: 61623145)\n[PASS] test_vrfCallbackGasIsTheCuratorsToTune() (gas: 61431482)\n[PASS] test_vrfCorrectableUntilTheSaleOpens_thenLockedForever() (gas: 62246539)\n[PASS] test_vrfMustBeConfiguredBeforeSelling() (gas: 46850)\nSuite result: ok. 16 passed; 0 failed; 0 skipped; finished in 1.67s (2.19s CPU time)\n\nRan 1 test for test/invariants/ArtifactsFactoryInvariant.t.sol:ArtifactsFactoryInvariantTest\n[PASS]\nArtifactsFactoryInvariantTest invariants:\n[PASS] invariant_claimedPiecesBelongToBuyers\n[PASS] invariant_counts\n[PASS] invariant_ledgerHoldsEveryPurchase\n[PASS] invariant_lockedAndPriced\n[PASS] invariant_walletLimit\n ArtifactsFactoryInvariantTest invariants (runs: 96, calls: 5760, reverts: 0)\n\n╭----------------+-------------------+-------+---------+----------╮\n| Contract       | Selector          | Calls | Reverts | Discards |\n+=================================================================+\n| FactoryHandler | buy               | 534   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | buyMany           | 495   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | claim             | 552   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | fulfil            | 497   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | lockedForever     | 508   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | replay            | 536   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | rerequest         | 507   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | setPrice          | 494   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | strangerFulfil    | 564   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | strangerRerequest | 534   | 0       | 0        |\n|----------------+-------------------+-------+---------+----------|\n| FactoryHandler | toggleSale        | 539   | 0       | 0        |\n╰----------------+-------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 10008\n  Bound result 51638143296626\n  Bound result 0\n  Bound result 2574237282764180103\n  Bound result 4264337593543950335\n  Bound result 3\n  Bound result 5\n  Bound result 3\n  Bound result 1\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.71s (1.66s CPU time)\n\nRan 1 test for test/invariants/ArtHouseInvariant.t.sol:ArtHouseInvariantTest\n[PASS]\nArtHouseInvariantTest invariants:\n[PASS] invariant_constants\n[PASS] invariant_ethConservation\n[PASS] invariant_imdConservation\n[PASS] invariant_noOverWithdrawal\n[PASS] invariant_supplyAndSeal\n ArtHouseInvariantTest invariants (runs: 128, calls: 5120, reverts: 0)\n\n╭---------------+----------------+-------+---------+----------╮\n| Contract      | Selector       | Calls | Reverts | Discards |\n+=============================================================+\n| LedgerHandler | handOver       | 380   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | mintETH        | 369   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | mintIMD        | 414   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | moduleSale     | 377   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | releaseBuyback | 413   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setBroker      | 396   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setPayout      | 404   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setPrices      | 429   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setSaleOpen    | 378   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | setSplit       | 413   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | strangerCalls  | 361   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | withdraw       | 377   | 0       | 0        |\n|---------------+----------------+-------+---------+----------|\n| LedgerHandler | withdrawHouse  | 409   | 0       | 0        |\n╰---------------+----------------+-------+---------+----------╯\n\nLogs:\n  Bound result 18882627285399\n  Bound result 685\n  Bound result 9797\n  Bound result 61765395460014508990\n  Bound result 9999\n  Bound result 1\n  Bound result 0\n  Bound result 1073\n  Bound result 5568\n  Bound result 4262\n  Bound result 93\n  Bound result 1500000000000000000\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.63s (3.62s CPU time)\n\nRan 13 tests for test/Adversarial.t.sol:ArtifactsEdgeTest\n[PASS] testFuzz_anyWordsAssignDistinctEditions(uint256[8]) (runs: 256, μ: 64647046, ~: 64649037)\n[PASS] testFuzz_sealFramesAnyTraits(uint8,uint8,uint8,uint8,uint8) (runs: 16, μ: 519807520, ~: 519807826)\nLogs:\n  Bound result 7\n\n[PASS] test_buyRevertsAtomicallyWhenCoordinatorReverts() (gas: 59197366)\n[PASS] test_callbackWithNoWordsReverts() (gas: 61547541)\n[PASS] test_claimedPieceIsAFullCopyOfTheImplementation() (gas: 67247088)\n[PASS] test_configureVRFRejectsZeroes() (gas: 211437)\n[PASS] test_duplicateRequestIdRejected() (gas: 59391685)\n[PASS] test_nonOwnerCannotRunTheSale() (gas: 60818098)\n[PASS] test_rerequestIsAtomicWhenCoordinatorReverts() (gas: 59883161)\n[PASS] test_rerequestWindowBoundaryAndChaining() (gas: 67816052)\n[PASS] test_setPieceEdges() (gas: 61051490)\n[PASS] test_unapprovedBuyerAsBrokerEarnsNothing_andOneWeiPriceWorks() (gas: 61487275)\n[PASS] test_wrappedKeyEdges() (gas: 67229754)\nSuite result: ok. 13 passed; 0 failed; 0 skipped; finished in 11.09s (12.48s CPU time)\n\nRan 29 test suites in 11.09s (24.23s CPU time): 232 tests passed, 0 failed, 2 skipped (234 total tests)\n","passed":true},{"durationMs":131,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"ArtCollection.approve(address,uint256)\",\"ArtCollection.initialize(address,string,string)\",\"ArtCollection.mint(address,uint256)\",\"ArtCollection.safeTransferFrom(address,address,uint256)\",\"ArtCollection.safeTransferFrom(address,address,uint256,bytes)\",\"ArtCollection.setApprovalForAll(address,bool)\",\"ArtCollection.transferFrom(address,address,uint256)\",\"ArtHouse.acceptOwnership()\",\"ArtHouse.approveArtist(address,string)\",\"ArtHouse.clearPiece(address,uint256)\",\"ArtHouse.createCollection(string,string,address)\",\"ArtHouse.decideSubmission(uint256,bool)\",\"ArtHouse.finalizePiece(address,uint256)\",\"ArtHouse.mint(address,uint256,address)\",\"ArtHouse.mintWithIMD(address,uint256,address,uint256)\",\"ArtHouse.recordResale(address,uint256,uint256)\",\"ArtHouse.recordSale(address,address,address)\",\"ArtHouse.registerModuleCollection(address,address)\",\"ArtHouse.registerPiece(address,uint256,bytes32,string,string)\",\"ArtHouse.releaseBuyback(address)\",\"ArtHouse.revokeArtist(address)\",\"ArtHouse.sealCollection(address)\",\"ArtHouse.setBroker(address,bool)\",\"ArtHouse.setBrokerPass(address)\",\"ArtHouse.setBuybackBurner(address)\",\"ArtHouse.setPayout(address)\",\"ArtHouse.setPrices(address,uint256,uint256)\",\"ArtHouse.setSaleModule(address,bool)\",\"ArtHouse.setSaleOpen(address,bool)\",\"ArtHouse.setSplit(address,uint16,uint16,uint16,uint16)\",\"ArtHouse.submit(bytes32,string)\",\"ArtHouse.transferOwnership(address)\",\"ArtHouse.updatePiece(address,uint256,bytes32,string,string)\",\"ArtHouse.uploadChunk(address,uint256,uint256,bytes)\",\"ArtHouse.withdraw(address)\",\"ArtHouse.withdrawHouse(address)\",\"ArtStorage.acceptOwnership()\",\"ArtStorage.clear(address,uint256)\",\"ArtStorage.setHouse(address)\",\"ArtStorage.transferOwnership(address)\",\"ArtStorage.write(address,uint256,uint256,bytes)\",\"ArtifactsFactory.acceptOwnership()\",\"ArtifactsFactory.buy(address)\",\"ArtifactsFactory.buyMany(uint256,address)\",\"ArtifactsFactory.buyWithSeat(uint256,uint256,address)\",\"ArtifactsFactory.claim(uint256)\",\"ArtifactsFactory.claimMany(uint256[])\",\"ArtifactsFactory.configureVRF(address,bytes32,uint256,bool)\",\"ArtifactsFactory.endSale()\",\"ArtifactsFactory.finishFallbackDraw(uint256)\",\"ArtifactsFactory.lock()\",\"ArtifactsFactory.postWrappedKey(uint256,bytes)\",\"ArtifactsFactory.postWrappedKeys(uint256[],bytes[])\",\"ArtifactsFactory.rawFulfillRandomWords(uint256,uint256[])\",\"ArtifactsFactory.registerViewingKey(bytes32)\",\"ArtifactsFactory.rerequestRandomness(uint256)\",\"ArtifactsFactory.setGate(address,address,uint256,uint64)\",\"ArtifactsFactory.setMemberGate(address,bytes4,uint256)\",\"ArtifactsFactory.setMintPhases(uint64,uint8,uint64,uint8)\",\"ArtifactsFactory.setPiece(uint256,(string,string,uint8,string),bytes,bytes32)\",\"ArtifactsFactory.setPrice(uint256)\",\"ArtifactsFactory.setSaleOpen(bool)\",\"ArtifactsFactory.setVRFCallbackGas(uint32)\",\"ArtifactsFactory.startFallbackDraw(uint256)\",\"ArtifactsFactory.transferOwnership(address)\",\"ArtifactsPiece.approve(address,uint256)\",\"ArtifactsPiece.buy(bytes32,address)\",\"ArtifactsPiece.cancel()\",\"ArtifactsPiece.delist()\",\"ArtifactsPiece.initialize(address,address,uint256,address,(string,string,uint8,string),address,bytes32,bytes,bool,bytes32)\",\"ArtifactsPiece.list(uint256)\",\"ArtifactsPiece.postEscrowKey(bytes,address,uint256)\",\"ArtifactsPiece.proveFakeKey((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256))\",\"ArtifactsPiece.refundBuyer()\",\"ArtifactsPiece.registerViewingKey(bytes32)\",\"ArtifactsPiece.release()\",\"ArtifactsPiece.reveal(bytes32)\",\"ArtifactsPiece.rewrapFor(bytes)\",\"ArtifactsPiece.safeTransferFrom(address,address,uint256)\",\"ArtifactsPiece.safeTransferFrom(address,address,uint256,bytes)\",\"ArtifactsPiece.setApprovalForAll(address,bool)\",\"ArtifactsPiece.transferFrom(address,address,uint256)\",\"ArtifactsPiece.withdraw()\",\"ArtifactsSource.acceptOwnership()\",\"ArtifactsSource.bid(address)\",\"ArtifactsSource.deliverKey(bytes)\",\"ArtifactsSource.lock(bytes32,bytes32)\",\"ArtifactsSource.resetRenderer()\",\"ArtifactsSource.setAuction(uint256,uint64)\",\"ArtifactsSource.setGate(address,address,uint256,uint64)\",\"ArtifactsSource.setMemberGate(address,bytes4,uint256)\",\"ArtifactsSource.settle()\",\"ArtifactsSource.storeRendererChunk(bytes)\",\"ArtifactsSource.transferOwnership(address)\",\"ArtifactsSource.voidUnsettled()\",\"ArtifactsSource.withdrawRefund()\",\"BrokerPass.approve(address,uint256)\",\"BrokerPass.claimWithPiece(uint256)\",\"BrokerPass.claimWithSeat(uint256)\",\"BrokerPass.safeTransferFrom(address,address,uint256)\",\"BrokerPass.safeTransferFrom(address,address,uint256,bytes)\",\"BrokerPass.setApprovalForAll(address,bool)\",\"BrokerPass.setClaimsOpenAt(uint64)\",\"BrokerPass.transferFrom(address,address,uint256)\",\"ImdBuybackBurner.burnEth(uint256,uint256,uint256)\",\"ImdBuybackBurner.burnImd()\",\"ImdBuybackBurner.receive()\",\"ImdBuybackBurner.unlockCallback(bytes)\",\"SubmissionReviews.applyAsBroker(string)\",\"SubmissionReviews.postThesis(uint256,string)\",\"SubmissionReviews.reviewAsPiece(uint256,uint256,uint8,string)\",\"SubmissionReviews.reviewAsSeat(uint256,uint256,uint8,string)\"],\"files\":{\".gitignore\":3,\"ADAPTATION.md\":248,\"README.md\":261,\"foundry.toml\":25,\"launch.burner.json\":17,\"launch.json\":63,\"reference/PROTOCOL.md\":99,\"reference/RULES.md\":137,\"reference/audit/V13Audit.t.sol.txt\":381,\"reference/check-framed.js\":25,\"reference/framed/framed-003.svg\":1,\"reference/framed/framed-MASTER.svg\":1,\"reference/rules.js\":145,\"reference/the-source.renderer.html\":148,\"remappings.txt\":1,\"script/Deploy.s.sol\":39,\"src/ArtCollection.sol\":55,\"src/ArtHouse.sol\":609,\"src/ArtStorage.sol\":82,\"src/ArtifactsFactory.sol\":622,\"src/ArtifactsPiece.sol\":457,\"src/ArtifactsSource.sol\":271,\"src/BrokerPass.sol\":142,\"src/ImdBuybackBurner.sol\":163,\"src/KeyProof.sol\":154,\"src/SubmissionReviews.sol\":215,\"src/base/ERC721Lite.sol\":122,\"src/base/HolderGate.sol\":109,\"src/base/ReentrancyGuard.sol\":15,\"src/base/TwoStepOwnable.sol\":40,\"src/interfaces/Interfaces.sol\":93,\"src/libs/Clones.sol\":19,\"src/libs/Encoding.sol\":79,\"src/libs/SSTORE2.sol\":41,\"src/libs/Seal.sol\":102,\"test/Adversarial.t.sol\":1409,\"test/ArtHouse.t.sol\":463,\"test/Artifacts.t.sol\":673,\"test/AuditRound3.t.sol\":151,\"test/BrokerPass.t.sol\":373,\"test/Burner.t.sol\":161,\"test/ClaimEnd.t.sol\":152,\"test/Fixture.sol\":230,\"test/Gate.t.sol\":295,\"test/KeyProof.t.sol\":134,\"test/LaunchAudit.t.sol\":338,\"test/LaunchDeployment.t.sol\":191,\"test/NothingStuck.t.sol\":568,\"test/Phases.t.sol\":130,\"test/Reviews.t.sol\":264,\"test/Source.t.sol\":396,\"test/audit/KeyProofEdges.t.sol\":178,\"test/audit/KeyReuseLeak.t.sol\":38,\"test/fixtures/keyproof.json\":81,\"test/fork/BurnerFork.t.sol\":70,\"test/fork/VrfFork.t.sol\":131,\"test/invariants/ArtHouseInvariant.t.sol\":444,\"test/invariants/ArtifactsFactoryInvariant.t.sol\":323,\"test/invariants/PieceEscrowInvariant.t.sol\":445,\"test/invariants/SourceAuctionInvariant.t.sol\":227,\"test/mocks/AdversarialMocks.sol\":134,\"test/mocks/MockPoolManager.sol\":57,\"test/mocks/MockSeats.sol\":27,\"test/mocks/Mocks.sol\":149,\"test/mocks/TestVRFCoordinator.sol\":46,\"test/utils/Base64Decode.sol\":83},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":13360,"exitCode":0,"name":"slither","output":"[high/medium] arbitrary-send-eth at src/ArtHouse.sol:559: ArtHouse._pay(address,address,uint256) (src/ArtHouse.sol#559-566) sends eth to arbitrary user\n[high/medium] weak-prng at src/ArtifactsFactory.sol:469: ArtifactsFactory._assign(uint256,uint256) (src/ArtifactsFactory.sol#469-485) uses a weak PRNG: \"idx = uint16(word % left) (src/ArtifactsFactory.sol#474)\"\n[high/medium] reentrancy-balance at src/ArtHouse.sol:431: Reentrancy in ArtHouse._pullIMD(address,uint256) (src/ArtHouse.sol#431-436):\n[high/medium] reentrancy-eth at src/ArtifactsPiece.sol:294: Reentrancy in ArtifactsPiece.release() (src/ArtifactsPiece.sol#294-330):\n[medium/medium] divide-before-multiply at src/libs/Encoding.sol:8: Encoding.base64(bytes) (src/libs/Encoding.sol#8-37) performs a multiplication on the result of a division:\n[medium/high] incorrect-equality at src/ArtifactsSource.sol:182: ArtifactsSource.gateEndsAt() (src/ArtifactsSource.sol#182-184) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/ArtifactsFactory.sol:450: ArtifactsFactory.finishFallbackDraw(uint256) (src/ArtifactsFactory.sol#450-459) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/ArtifactsFactory.sol:442: ArtifactsFactory._fallbackLive(uint256) (src/ArtifactsFactory.sol#442-446) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/ArtifactsFactory.sol:462: ArtifactsFactory._hashOf(uint256) (src/ArtifactsFactory.sol#462-467) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/ImdBuybackBurner.sol:136: ImdBuybackBurner.burnImd() (src/ImdBuybackBurner.sol#136-142) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/ArtifactsFactory.sol:450: ArtifactsFactory.finishFallbackDraw(uint256) (src/ArtifactsFactory.sol#450-459) uses a dangerous strict equality:\n[medium/medium] uninitialized-local at src/SubmissionReviews.sol:103: SubmissionReviews.reviewAsSeat(uint256,uint256,SubmissionReviews.Verdict,string).holder (src/SubmissionReviews.sol#103) is a local variable never initialized\n[medium/medium] uninitialized-local at src/BrokerPass.sol:85: BrokerPass.claimWithPiece(uint256).piece (src/BrokerPass.sol#85) is a local variable never initialized\n[medium/medium] uninitialized-local at src/ArtifactsPiece.sol:308: ArtifactsPiece.release().brokerShare (src/ArtifactsPiece.sol#308) is a local variable never initialized\n[medium/medium] uninitialized-local at src/SubmissionReviews.sol:115: SubmissionReviews.reviewAsPiece(uint256,uint256,SubmissionReviews.Verdict,string).piece (src/SubmissionReviews.sol#115) is a local variable never initialized\n[medium/medium] uninitialized-local at src/ArtifactsPiece.sol:438: ArtifactsPiece._revealedURI().page (src/ArtifactsPiece.sol#438) is a local variable never initialized\n[medium/medium] unused-return at src/SubmissionReviews.sol:123: SubmissionReviews._review(uint256,uint256,SubmissionReviews.Verdict,string) (src/SubmissionReviews.sol#123-139) ignores return value by (None,None,None,status) = house.submissions(submissionId) (src/SubmissionReviews.sol#127)\n[medium/medium] unused-return at src/ArtHouse.sol:353: ArtHouse.uploadChunk(address,uint256,uint256,bytes) (src/ArtHouse.sol#353-364) ignores return value by artStorage.write(collection,pieceId,index,data) (src/ArtHouse.sol#363)\n[medium/medium] unused-return at src/SubmissionReviews.sol:160: SubmissionReviews._thesis(uint256,string) (src/SubmissionReviews.sol#160-169) ignores return value by (None,None,None,status) = house.submissions(submissionId) (src/SubmissionReviews.sol#164)\n[medium/medium] unused-return at src/ImdBuybackBurner.sol:146: ImdBuybackBurner.unlockCallback(bytes) (src/ImdBuybackBurner.sol#146-162) ignores return value by poolManager.settle{value: ethIn}() (src/ImdBuybackBurner.sol#159)\n[low/medium] missing-zero-check at src/ArtifactsSource.sol:186: ArtifactsSource.bid(address).broker (src/ArtifactsSource.sol#186) lacks a zero-check on :\n[low/medium] missing-zero-check at src/ArtifactsPiece.sol:123: ArtifactsPiece.initialize(address,address,uint256,address,Traits,address,bytes32,bytes,bool,bytes32).ciphertext_ (src/ArtifactsPiece.sol#123) lacks a zero-check on :\n[low/medium] missing-zero-check at src/ImdBuybackBurner.sol:91: ImdBuybackBurner.constructor(address,address,address,uint24,int24,address).poolHooks_ (src/ImdBuybackBurner.sol#91) lacks a zero-check on :\n[low/medium] calls-loop at src/ArtifactsFactory.sol:398: ArtifactsFactory._requestRandomness(address,uint256) (src/ArtifactsFactory.sol#398-413) has external calls inside a loop: requestId = vrfCoordinator.requestRandomWords(IVRFCoordinatorV2Plus.RandomWordsRequest({keyHash:vrfKeyHash,subId:vrfSubscriptionId,requestConfirmations:VRF_CONFIRMATIONS,callbackGasLimit:vrfCallbackGas,numWords:1,extraArgs:abi.encodeWithSelector(bytes4(keccak256(bytes)(VRF ExtraArgsV1)),vrfNativePayment)})) (src/ArtifactsFactory.sol#399-408)\n[low/medium] calls-loop at src/ArtifactsFactory.sol:398: ArtifactsFactory._requestRandomness(address,uint256) (src/ArtifactsFactory.sol#398-413) has external calls inside a loop: requestId = vrfCoordinator.requestRandomWords(IVRFCoordinatorV2Plus.RandomWordsRequest({keyHash:vrfKeyHash,subId:vrfSubscriptionId,requestConfirmations:VRF_CONFIRMATIONS,callbackGasLimit:vrfCallbackGas,numWords:1,extraArgs:abi.encodeWithSelector(bytes4(keccak256(bytes)(VRF ExtraArgsV1)),vrfNativePayment)})) (src/ArtifactsFactory.sol#399-408)\n[low/medium] calls-loop at src/ArtifactsFactory.sol:398: ArtifactsFactory._requestRandomness(address,uint256) (src/ArtifactsFactory.sol#398-413) has external calls inside a loop: requestId = vrfCoordinator.requestRandomWords(IVRFCoordinatorV2Plus.RandomWordsRequest({keyHash:vrfKeyHash,subId:vrfSubscriptionId,requestConfirmations:VRF_CONFIRMATIONS,callbackGasLimit:vrfCallbackGas,numWords:1,extraArgs:abi.encodeWithSelector(bytes4(keccak256(bytes)(VRF ExtraArgsV1)),vrfNativePayment)})) (src/ArtifactsFactory.sol#399-408)\n[low/medium] calls-loop at src/ArtifactsFactory.sol:545: ArtifactsFactory._claim(uint256) (src/ArtifactsFactory.sol#545-571) has external calls inside a loop: IArtifactsPiece(piece).initialize(address(this),address(house),edition,buyer,p.traits,p.ciphertext,p.commitment,wrapped,false,viewingKeyOf[buyer]) (src/ArtifactsFactory.sol#557-569)\n[low/medium] calls-loop at src/ArtifactsFactory.sol:509: ArtifactsFactory._postWrappedKey(uint256,bytes) (src/ArtifactsFactory.sol#509-528) has external calls inside a loop: IArtifactsPiece(piece).rewrapFor(wrapped) (src/ArtifactsFactory.sol#517)\n[low/medium] reentrancy-benign at src/ImdBuybackBurner.sol:136: Reentrancy in ImdBuybackBurner.burnImd() (src/ImdBuybackBurner.sol#136-142):\n[low/medium] reentrancy-benign at src/ImdBuybackBurner.sol:110: Reentrancy in ImdBuybackBurner.burnEth(uint256,uint256,uint256) (src/ImdBuybackBurner.sol#110-133):\n[low/medium] reentrancy-benign at src/ArtifactsFactory.sol:350: Reentrancy in ArtifactsFactory._buy(uint256,address) (src/ArtifactsFactory.sol#350-366):\n[low/medium] reentrancy-benign at src/ArtHouse.sol:237: Reentrancy in ArtHouse.createCollection(string,string,address) (src/ArtHouse.sol#237-247):\n[low/medium] reentrancy-benign at src/ArtifactsFactory.sol:398: Reentrancy in ArtifactsFactory._requestRandomness(address,uint256) (src/ArtifactsFactory.sol#398-413):\n[low/medium] reentrancy-events at src/ImdBuybackBurner.sol:136: Reentrancy in ImdBuybackBurner.burnImd() (src/ImdBuybackBurner.sol#136-142):\n[low/medium] reentrancy-events at src/ArtHouse.sol:367: Reentrancy in ArtHouse.clearPiece(address,uint256) (src/ArtHouse.sol#367-375):\n[low/medium] reentrancy-events at src/ImdBuybackBurner.sol:110: Reentrancy in ImdBuybackBurner.burnEth(uint256,uint256,uint256) (src/ImdBuybackBurner.sol#110-133):\n[low/medium] reentrancy-events at src/ArtHouse.sol:237: Reentrancy in ArtHouse.createCollection(string,string,address) (src/ArtHouse.sol#237-247):\n[low/medium] reentrancy-events at src/ArtifactsFactory.sol:372: Reentrancy in ArtifactsFactory.rerequestRandomness(uint256) (src/ArtifactsFactory.sol#372-388):\n[low/medium] reentrancy-events at src/ArtifactsSource.sol:138: Reentrancy in ArtifactsSource.deliverKey(bytes) (src/ArtifactsSource.sol#138-145):\n[low/medium] timestamp at src/ArtifactsFactory.sol:273: ArtifactsFactory.gateEndsAt() (src/ArtifactsFactory.sol#273-275) uses timestamp for comparisons\n[low/medium] timestamp at src/BrokerPass.sol:67: BrokerPass.setClaimsOpenAt(uint64) (src/BrokerPass.sol#67-73) uses timestamp for comparisons\n[low/medium] timestamp at src/BrokerPass.sol:76: BrokerPass.claimsOpen() (src/BrokerPass.sol#76-78) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsPiece.sol:294: ArtifactsPiece.release() (src/ArtifactsPiece.sol#294-330) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsPiece.sol:278: ArtifactsPiece.cancel() (src/ArtifactsPiece.sol#278-290) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:260: ArtifactsFactory.setGate(address,address,uint256,uint64) (src/ArtifactsFactory.sol#260-263) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:232: ArtifactsFactory.configureVRF(address,bytes32,uint256,bool) (src/ArtifactsFactory.sol#232-243) uses timestamp for comparisons\n[low/medium] timestamp at src/ImdBuybackBurner.sol:110: ImdBuybackBurner.burnEth(uint256,uint256,uint256) (src/ImdBuybackBurner.sol#110-133) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:297: ArtifactsFactory.currentPhase() (src/ArtifactsFactory.sol#297-305) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:280: ArtifactsFactory.setMintPhases(uint64,uint8,uint64,uint8) (src/ArtifactsFactory.sol#280-293) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsSource.sol:182: ArtifactsSource.gateEndsAt() (src/ArtifactsSource.sol#182-184) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsSource.sol:245: ArtifactsSource.voidUnsettled() (src/ArtifactsSource.sol#245-257) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsSource.sol:186: ArtifactsSource.bid(address) (src/ArtifactsSource.sol#186-201) uses timestamp for comparisons\n[low/medium] timestamp at src/base/HolderGate.sol:73: HolderGate._inGate(uint256) (src/base/HolderGate.sol#73-75) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsSource.sol:151: ArtifactsSource.setAuction(uint256,uint64) (src/ArtifactsSource.sol#151-163) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:218: ArtifactsFactory.endSale() (src/ArtifactsFactory.sol#218-227) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:267: ArtifactsFactory.setMemberGate(address,bytes4,uint256) (src/ArtifactsFactory.sol#267-270) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:203: ArtifactsFactory.setSaleOpen(bool) (src/ArtifactsFactory.sol#203-213) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsSource.sol:213: ArtifactsSource.settle() (src/ArtifactsSource.sol#213-241) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsPiece.sol:201: ArtifactsPiece.delist() (src/ArtifactsPiece.sol#201-206) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:545: ArtifactsFactory._claim(uint256) (src/ArtifactsFactory.sol#545-571) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:249: ArtifactsFactory.setVRFCallbackGas(uint32) (src/ArtifactsFactory.sol#249-254) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsPiece.sol:353: ArtifactsPiece._beforeTransfer(address,address,uint256) (src/ArtifactsPiece.sol#353-361) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsFactory.sol:346: ArtifactsFactory._tokenGate() (src/ArtifactsFactory.sol#346-348) uses timestamp for comparisons\n[low/medium] timestamp at src/ArtifactsPiece.sol:370: ArtifactsPiece.reveal(bytes32) (src/ArtifactsPiece.sol#370-384) uses timestamp for comparisons","passed":true},{"durationMs":760,"exitCode":0,"name":"aderyn","output":"[high] abi-encode-packed-hash-collision at src/ArtCollection.sol:44: `abi.encodePacked()` Hash Collision (6 places)\n[high] contract-locks-ether at src/ArtifactsFactory.sol:13: Contract locks Ether without a withdraw function (2 places)\n[high] eth-send-unchecked-address at src/ArtifactsPiece.sol:341: ETH transferred without address checks (2 places)\n[high] reentrancy-state-change at src/ArtHouse.sol:360: Reentrancy: State change after external call (18 places)\n[low] centralization-risk at src/ArtHouse.sol:176: Centralization Risk (36 places)\n[low] costly-loop at src/ArtifactsFactory.sol:362: Costly operations inside loop (3 places)\n[low] empty-block at src/base/ERC721Lite.sol:121: Empty Block\n[low] large-numeric-literal at src/ArtHouse.sol:15: Large Numeric Literal (11 places)\n[low] literal-instead-of-constant at src/ArtifactsFactory.sol:395: Literal Instead of Constant (35 places)\n[low] require-revert-in-loop at src/ArtHouse.sol:394: Loop Contains `require`/`revert` (4 places)\n[low] state-change-without-event at src/ArtCollection.sol:20: State Change Without Event (5 places)\n[low] state-no-address-check at src/ArtifactsPiece.sol:132: Address State Variable Set Without Checks (3 places)\n[low] storage-array-length-not-cached at src/ArtifactsSource.sol:120: Storage Array Length not Cached\n[low] unchecked-return at src/ArtCollection.sol:42: Unchecked Return (5 places)\n[low] uninitialized-local-variable at src/ArtHouse.sol:394: Uninitialized Local Variable (6 places)\n[low] unsafe-erc20-operation at src/ArtHouse.sol:434: Unsafe ERC20 Operation (3 places)","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"d9172b6c1162eb1017a6b7bd12855b7159297b2404ccc7e55dd9b31ee670ba33","verifiedTreeHash":"dd56d53d6daaeae0c768610f57e29ebd41022093","verifierVersion":"0.1.0+745c1db4"}]}