{"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":"4a7aca49-e340-4c57-b9b4-daf260d1c78e","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"05452581a3f4744933250af12bc6e97362942d25fc53a8792efa385b6abba83e","dependsOn":["build_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":"2a13d0f1ed26f4520654afaafd06488dc80e0979ad42cb4707af6ed865142a8c","dependsOn":["build_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":"9dc3086b635a898c5713b2c6bdf5b603e2ddac695943aa1e4d1680591c1d78bc","dependsOn":["build_contract_project","write_foundry_tests","manifest","audit_math","audit_permissions","audit_economics","audit_flow"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"3014f1ea5961918ca059453a484bf4c8bcbbfc2248dbe31d94ac7c5cdf8f50bd","skillId":"audit-judge","tools":[]},"key":"audit_judge","kind":"code","role":"review","skillHash":"3014f1ea5961918ca059453a484bf4c8bcbbfc2248dbe31d94ac7c5cdf8f50bd","skillId":"audit-judge","state":"accepted"},{"acceptedSubmissionHash":"94bfe6a561f418b41044515e353ad59d2b0c03ebe7149b17333b72d828f10be7","dependsOn":["build_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":"e90e5fc3d10e7479ab8b315c8b7cdd97bc700bbba26c8ff4cdfa31c73bc62bd1","dependsOn":["build_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":"fccce36f8081670db506e506ac08b9dff5936e661ae699813eca9e7b03874ffa","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"b6503de65ad02f845827887c23da4c3b56ccc5df7a459db263bae6e549d92f7f","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"b6503de65ad02f845827887c23da4c3b56ccc5df7a459db263bae6e549d92f7f","skillId":"build-contract-project","state":"accepted"},{"acceptedSubmissionHash":"37d88024dfe4a61aa92a7a125ef71b18d5f0ffec70065d5e37009da07847361a","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"10da5ddfdd507cb4e1ad101a765aa4ca2a70237d05af7acebfac934458bac2cd","dependsOn":["build_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":"Ochre: one ERC-721 contract that sells and gives away 737 pieces of a wall painted live by workers, paid in a coin that is sent to the dead address. Deploy on Sepolia (chain id 11155111), for a rehearsal: two contracts, MockCoin first (a plain ERC-20 \"Pigment\" / \"PGMT\", 18 decimals, 1,000,000,000 minted to the admin in its constructor, plus a public mint(address,uint256) anyone may call so rehearsal wallets can get it), then Ochre. Nothing is upgradeable, pausable or ownable; the contract never holds funds.\n\nCONSTRUCTOR (static values, no external calls; the verifier deploys it in an empty EVM, so never read another contract in the constructor; the coin has 18 decimals, write that as a constant): coin = $contract:MockCoin; dead 0x000000000000000000000000000000000000dEaD; admin 0x7B8C742F2e1eEB3fB2C10d72967Fa6d4a22f0479; adam 0x7B8C742F2e1eEB3fB2C10d72967Fa6d4a22f0479; seatRoot 0x1111111111111111111111111111111111111111111111111111111111111111 (rehearsal value; the real root comes from the seat list) (Merkle root of keccak256(abi.encodePacked(address)) leaves, sorted pairs); startTime 1791352835 (about six hours after this request) (Unix seconds); labels: seven bytes32, one per wall section (called a cave), in order: \"zto-cave-test5\", \"zto-cave-test4\", \"zto-cave-test3\", \"zto-cave-test2\", \"zto-cave-test5\", \"zto-cave-test4\", \"zto-cave-test3\" (the test caves already published; the real caves get their own). It mints id 0 to adam and id 736 to admin.\n\nPIECES. Ids 0..736. Id 0 is Zero and id 736 is One. For 1..735: cave = (id-1)/105 + 1 (1..7), round = ((id-1) % 105)/5 + 1 (1..21), slot = (id-1) % 5 + 1 (1..5). Slots 1..4 are lines 1..4; slot 5 is the gathering. Nothing else can ever be minted.\n\nDAYS. Cave c opens at startTime + (c-1) * 1 day and stays open after. Day index d = c.\n\nSALE PIECES. In every round, k(d) pieces are for sale, taken in this slot order: 5, 4, 3, 2, 1. k = 1,1,2,3,4,4,4 for caves 1..7, except cave 7 round 21 where k = 5. So caves sell 21,21,42,63,84,84,85 = 400 pieces. The other slots of each round are free pieces: caves 1..6 hold 315 of them for seats; cave 7's 20 free pieces are the admin's reserve.\n\nPRICE. price(c, t) falls in a straight line from startPrice(c) at the cave's open to floorPrice over 20 hours, then stays at floorPrice. startPrice(c) and floorPrice are constructor constants in coin base units: startPrice 400000 for every cave, floorPrice 40000 (rehearsal values, 18 decimals). priceNow(c) is a view.\n\nbuy(c): requires cave c open and a sale piece left in it; takes the next sale piece in id order (round by round, slots as above); charges price(c, now) by coin.transferFrom(msg.sender, dead, price), requiring the returned bool; mints to msg.sender; emits Bought(id, buyer, price). No per-wallet limit. The buyer approves the coin first; the contract never holds it.\n\nclaimSeat(proof): requires msg.sender in seatRoot and not claimed before; takes the next free piece of caves 1..6 in id order, skipping sale slots; mints to msg.sender; emits Claimed(id, wallet). Free, gas only. Available from startTime.\n\nmintReserve(to): admin only; mints the next free piece of cave 7 to `to`; at most 20.\n\nreleaseUnclaimed(): callable by anyone after startTime + 8 days; after it, buy(c) may also take any still-unclaimed free piece of caves 1..6 at floorPrice (sale pieces first, then free ones, in id order).\n\ntokenURI(id): before freeze, \"https://\" + label(c) + \".sites.imd.fun/\" + (\"gathering/\" if slot 5 else \"line-\" + slot + \"/\") + two-digit round + \".json\"; id 0 uses \"https://\" + label(1) + \".sites.imd.fun/zero.json\" and id 736 \"https://\" + label(7) + \".sites.imd.fun/one.json\". freeze(c, base) is admin only, once per cave: afterwards that cave's links use `base` (for example ipfs://<cid>/) in place of \"https://\" + label + \".sites.imd.fun/\". Labels hold up to 32 ASCII bytes, right-padded with zeros.\n\nRULES. supportsInterface for ERC-721 and ERC-721Metadata; name \"Ochre\", symbol \"OCHRE\"; no ERC-2981 royalty. No function may move the coin anywhere but the dead address. Tests against the mock coin: the id arithmetic for every cave/round/slot, the exact sale counts per cave (400 in all), the price line and floor, buy before open reverts, claim with a bad proof reverts, double claim reverts, reserve capped at 20, nothing mintable past 737, releaseUnclaimed timing, freeze once per cave, tokenURI strings for sample ids including 0 and 736, and events. README with the rules and their limits.\n","parentJobId":null,"planHash":"0141cbcd149fb620bbcc4464cb7f11577c065532db912f0a823f6710dd286e8d","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"4a7aca49-e340-4c57-b9b4-daf260d1c78e","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-859-ochre-one-erc-721-contract"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"51027","feedbackHash":"0ac0e5b96855a8247f302085f928c59a2237ec9c339e33e70b8607dabe969e29","nodeKey":"audit_economics","submissionHash":"05452581a3f4744933250af12bc6e97362942d25fc53a8792efa385b6abba83e","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52082","feedbackHash":"9edfec26e2d46c6ecb95ea388a4c4624ca22fa0ece573c66cb9b9b688880e216","nodeKey":"audit_flow","submissionHash":"2a13d0f1ed26f4520654afaafd06488dc80e0979ad42cb4707af6ed865142a8c","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52251","feedbackHash":"4a77184c86b6686cdf8cddbdfa647e2c9eb73e3964ce84304b5522c29d650d4f","nodeKey":"audit_judge","submissionHash":"9dc3086b635a898c5713b2c6bdf5b603e2ddac695943aa1e4d1680591c1d78bc","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"52100","feedbackHash":"68bf494fd40dfaef3c6dbd98f7c0189b0e8d1a05381c4ce34e0c950a0f4e9fbc","nodeKey":"audit_math","submissionHash":"94bfe6a561f418b41044515e353ad59d2b0c03ebe7149b17333b72d828f10be7","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"50959","feedbackHash":"205e7e311376e4d2e157b6731a698edc93c57207eb95ff7628bc6ddfb7967f50","nodeKey":"audit_permissions","submissionHash":"e90e5fc3d10e7479ab8b315c8b7cdd97bc700bbba26c8ff4cdfa31c73bc62bd1","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51325","feedbackHash":"09216ccde4d22ed5f76c632ff44a612888fc5e949e694714f2aba7444a824096","nodeKey":"build_contract_project","submissionHash":"fccce36f8081670db506e506ac08b9dff5936e661ae699813eca9e7b03874ffa","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51330","feedbackHash":"b489fab1be30f02622165319397aed5ccefaca030784ddaae78bfa794d411803","nodeKey":"manifest","submissionHash":"37d88024dfe4a61aa92a7a125ef71b18d5f0ffec70065d5e37009da07847361a","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"50954","feedbackHash":"4d21bc9f2f618553aa4eb5a9dd84580c689915b3594f588fc7fd5da579a96f7f","nodeKey":"write_foundry_tests","submissionHash":"10da5ddfdd507cb4e1ad101a765aa4ca2a70237d05af7acebfac934458bac2cd","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"353a09d8c5793a0cb7ae87a546e38a7cc33ff66c3b13721c78dfc8dc709bc7dc","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":null,"device":"61b4050710026370","findings":[{"citation":"resolved","description":"The brief defines claimSeat(proof) as requiring only that msg.sender is in seatRoot and has not claimed before, available from startTime, and defines releaseUnclaimed() as making still-unclaimed free pieces purchasable at floorPrice. The implementation additionally ends all seat claims the moment anyone calls releaseUnclaimed() (allowed from startTime + 8 days). Because the call is permissionless, any buyer who wants cheap pieces can terminate every remaining seat holder's entitlement at the first eligible second and then buy those seats at the 40000 base-unit floor. The README documents this as a deliberate resolution of an unspecified policy, so this is a design deviation for the author to confirm rather than a coding error; if claims are meant to continue after release, claimSeat must also skip pieces already sold through the release path (the current seatCursor loop only skips sale slots, so it would mint an already-owned id and revert).","line":185,"path":"src/Ochre.sol","reproduction":"Deploy Ochre with seatRoot = keccak256(abi.encodePacked(SEAT)) (single-leaf tree, empty proof). Warp to startTime + 8 days. From any address call releaseUnclaimed() (succeeds). From SEAT call claimSeat([]) -> reverts SeatsClosed, although SEAT is in the root and has never claimed. Then from a funded buyer call buy(1) 22 times: calls 1..21 return ids 5,10,...,105; call 22 returns id 1 at price 40000 and ownerOf(1) == buyer, claimed(SEAT) == false. Expected under the brief as written: claimSeat succeeds for SEAT at any time while a free piece remains (no deadline is stated); actual: the seat is lost to a buyer. Confirmed with test/scratch/Probe.t.sol::test_seatEntitlementEndsOnPermissionlessRelease.","severity":"low","snippet":"        if (unclaimedReleased || seatsMinted == 315) revert SeatsClosed();","title":"claimSeat is permanently closed by the permissionless releaseUnclaimed(), a deadline the brief does not state"},{"citation":"resolved","description":"The brief says sale pieces are 'taken in this slot order: 5, 4, 3, 2, 1' and that buy(c) 'takes the next sale piece in id order (round by round, slots as above)'. The implementation reads this as ascending id order within each round, so in a cave with k >= 2 the line piece (slot 4) sells before the gathering (slot 5). Under the other reading of 'slots as above' the gathering sells first in every round. Which piece the first buyer of a round receives depends on this choice, and the brief's two phrases point in different directions. The README records the ascending-id interpretation; the author should confirm it or flip the within-round order.","line":160,"path":"src/Ochre.sol","reproduction":"Warp to startTime + 2 days (cave 3 open, k = 2). A funded buyer calls buy(3) twice. Actual: first call returns id 214 (cave 3, round 1, slot 4 = line 4) and second returns 215 (slot 5 = gathering). Under the 5,4,3,2,1 reading the expected sequence is 215 then 214. Observed with test/scratch/Probe.t.sol::test_withinRoundOrder (logs first=214 slot 4, second=215 slot 5).","severity":"low","snippet":"        while (offset < 105 && !isSalePiece(first + offset)) ++offset;","title":"Within a round, buy() sells slot 4 before slot 5, while the brief lists sale slots in the order 5, 4, 3, 2, 1"},{"citation":"resolved","description":"Every issue path goes through _issue -> _safeMint, which calls onERC721Received when the recipient has code. A wallet on the seat list that is a contract lacking that hook (a simple multisig, a vault, a contract account without the ERC-721 receiver interface) gets ERC721InvalidReceiver on every claimSeat attempt. The brief says claimSeat 'mints to msg.sender' with no receiver requirement and gives the seat holder no alternative recipient parameter, so such a wallet is locked out for the whole claim window and, combined with finding 1, its piece is sold to a buyer at the floor after release. Gnosis Safe wallets with the default fallback handler are fine; the gap is for contracts without the hook. A fix that preserves the intended behavior is to use _mint in claimSeat (the recipient is the proven seat holder itself) or to accept an explicit recipient.","line":244,"path":"src/Ochre.sol","reproduction":"Deploy a contract W with no functions. Deploy Ochre with seatRoot = keccak256(abi.encodePacked(address(W))). Warp to startTime. vm.prank(address(W)); ochre.claimSeat([]) -> reverts (ERC721InvalidReceiver(W)); claimed(W) == false, seatsMinted == 0. Expected under the brief: W is in the root and has not claimed, so the claim succeeds. Confirmed with test/scratch/Probe.t.sol::test_contractSeatWithoutReceiverCannotClaim.","severity":"low","snippet":"        _safeMint(to, id);","title":"claimSeat uses _safeMint, so a seat wallet that is a contract without onERC721Received can never claim and loses its seat on release"},{"citation":"resolved","description":"The brief says releaseUnclaimed() is 'callable by anyone after startTime + 8 days'. The guard uses a strict less-than, so the call succeeds when block.timestamp == startTime + 8 days. The README and tests treat that second as eligible (inclusive). One-second boundary; harmless unless the author meant strictly after.","line":211,"path":"src/Ochre.sol","reproduction":"vm.warp(startTime + 8 days); releaseUnclaimed() -> succeeds and unclaimedReleased() == true. At startTime + 8 days - 1 it reverts TooEarly. Observed with test/scratch/Probe.t.sol::test_releaseAtExactBoundary.","severity":"info","snippet":"        if (block.timestamp < startTime + 8 days) revert TooEarly();","title":"releaseUnclaimed() is accepted at exactly startTime + 8 days although the brief says 'after'"}],"hash":"05452581a3f4744933250af12bc6e97362942d25fc53a8792efa385b6abba83e","nodeId":"a8ff3a48-0e0a-47f5-b963-a157d1f0ef94","outcome":"completed","summary":"The review is complete. `.imd-findings.json` holds four findings and an 18-row coverage record; the scratch tests were removed and the tree is otherwise untouched.\n\n**Outcome.** No fund-loss, mis-payment or permanent-breakage defect was found in the economics. Every finding is a gap between the brief's wording and the implemented policy, each reproduced against the code.\n\n**Findings written**\n\n- **Low, claim closure on release.** Anyone can call `releaseUnclaimed()` from day 8 and that call ends every remaining seat claim. The brief gives `claimSeat` no deadline. Reproduced: a seat wallet in the root reverts with `SeatsClosed` after release, and a buyer then takes its piece at the floor price.\n- **Low, within-round sale order.** Cave 3's first buy returns id 214 (line 4) and then 215 (gathering). The brief's \"slot order 5, 4, 3, 2, 1\" can be read as selling the gathering first. The README documents the ascending-id choice. The author should confirm which was intended.\n- **Low, contract seat wallets.** Claims mint with `_safeMint`, so a seat wallet that is a contract without the ERC-721 receiver hook can never claim, then loses the piece on release.\n- **Info, release boundary.** Release is accepted at exactly start plus 8 days although the brief says \"after\".\n\n**What held.** The 737-piece partition, the exact 400/315/20 split, the 5-per-second price line and floor, buy-before-open and double-claim reverts, the reserve cap, release-path ordering and floor pricing, the single buyer-to-dead coin transfer, reentrancy guards, and the worst-case release scan gas (about 364k) all checked out. All 14 listed entry points have a row; none is marked unreached.","treeHash":null,"usage":{"cachedInputTokens":683824,"inputTokens":258,"model":"claude-fable-5-1","outputTokens":23954,"runtime":"claude","turns":25,"wallClockMs":339609}},{"artifacts":[],"attempt":2,"bundleHash":"7e88e4c7a48809a65afe9455a89f5b978129016791127f842320ce545f52b237","device":"cc309a7afc70b0b1","findings":[],"hash":"10da5ddfdd507cb4e1ad101a765aa4ca2a70237d05af7acebfac934458bac2cd","nodeId":"66ba0809-0769-4bff-8d76-abb1fca17f8c","outcome":"completed","summary":"Added 17 tests covering failure paths, boundaries, and three stateful invariant campaigns, plus `test/README.md`.\n\nValidation passed offline: **59 tests**, including **65,536 randomized invariant calls**. No contract defects reproduced. All changes are under `test/`.","treeHash":"c41e4a24f3329faec860738198c9611ea590ca67","usage":{"cachedInputTokens":1282560,"inputTokens":83421,"model":"gpt-6-astra","outputTokens":19390,"runtime":"codex","turns":7,"wallClockMs":486965}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"077d2937780a81bc","findings":[{"citation":"resolved","description":"_validateLabel accepts any byte <= 0x7F before the zero padding, so control characters (0x01..0x1F, 0x7F) pass as 'ASCII'. A label built from them deploys fine and tokenURI then returns an https URL whose hostname contains control bytes, which no resolver accepts. Only the deployer supplies labels and the seven rehearsal labels in launch.json are valid lowercase hostnames, so this is a deployment-input hardening note within the brief's 'up to 32 ASCII bytes' wording, not a reachable defect for unprivileged callers.","line":257,"path":"src/Ochre.sol","reproduction":"new Ochre(coin, admin, adam, root, 1791352835, bytes32(abi.encodePacked(bytes1(0x01), bytes1(0x7f))), ...same for all seven) succeeds (expected under the current rule; a stricter rule would revert InvalidConfiguration). tokenURI(0) then returns the 34-byte string \"https://\\x01\\x7f.sites.imd.fun/zero.json\". Verified with a scratch Foundry test on this tree.","severity":"info","snippet":"            else if (ended || uint8(char) > 127) revert InvalidConfiguration();","title":"Label validation admits non-printable ASCII bytes, producing unusable https hostnames"},{"citation":"resolved","description":"The brief says that after releaseUnclaimed() buy(c) may also take still-unclaimed free pieces, but does not say seat claims end. The code ends them: once unclaimedReleased is true every claimSeat reverts SeatsClosed even for a wallet with a valid proof that never claimed. README documents this as the chosen resolution, and it is the coherent choice (open claims after release would collide with releasedCursor and brick claimSeat on an already-minted id), so this is reported for the requester to confirm, not as a defect. If claims were meant to continue after release the design must change, since seatCursor does not skip owned ids.","line":185,"path":"src/Ochre.sol","reproduction":"Deploy with seatRoot = sorted-pair root of leaves keccak256(abi.encodePacked(A)) and keccak256(abi.encodePacked(B)). vm.warp(startTime + 8 days); anyone calls releaseUnclaimed(). Then A calls claimSeat([leafB]) with a valid proof: reverts SeatsClosed; buy(1) by anyone instead takes id 1 (A's would-be seat) for 40000 base units. Verified on this tree.","severity":"info","snippet":"        if (unclaimedReleased || seatsMinted == 315) revert SeatsClosed();","title":"releaseUnclaimed() permanently closes claimSeat, a policy the brief leaves unspecified"},{"citation":"resolved","description":"The brief states 'startPrice 400000 for every cave, floorPrice 40000 (rehearsal values, 18 decimals)' in coin base units. The code follows the base-unit wording literally and never scales by 10**18, so a full-price purchase burns 0.0000000000004 PGMT. README and launch.json notes state this explicitly. If the requester meant 400000 whole PGMT the constants are off by a factor of 1e18; since the brief says 'base units' this is flagged for confirmation only.","line":14,"path":"src/Ochre.sol","reproduction":"vm.warp(1791352835); ochre.priceNow(1) == 400000; MockCoin.decimals() == 18; buy(1) moves exactly 400000 base units (0.0000000000004 PGMT) from buyer to 0x000000000000000000000000000000000000dEaD. Existing testPriceBoundariesEveryCave and testBuyPaymentAndEventNoWalletLimit pin these values.","severity":"info","snippet":"    uint256 public constant START_PRICE = 400_000;","title":"Prices are literal base units (400000 wei of an 18-decimal coin), i.e. 4e-13 PGMT per piece"}],"hash":"2a13d0f1ed26f4520654afaafd06488dc80e0979ad42cb4707af6ed865142a8c","nodeId":"5a2c0f6b-8be1-4ae6-ade5-06ef85fcaa8d","outcome":"completed","summary":"The review is complete. `.imd-findings.json` is written in the repository root with three informational findings and 18 coverage rows. No source, test or config file was changed, and the scratch test I used was deleted.\n\n**Outcome: no defect of severity low or above in the control flow.** I traced every state-changing entry point of Ochre and MockCoin against the brief and the Execution Trace, Periphery and First Principles guides. The id arithmetic, slot-order sale selection, per-cave sale counts, price line, open-time gating, released-seat ordering, reserve ids, supply cap and tokenURI composition all match the brief. The single coin call site sends only to the dead address and requires the returned bool. Cursors are committed before the mint callback and every allocation path is under one reentrancy guard. The existing 42 tests pass, and a scratch test I wrote confirmed the claim/sale/release interleaving, cave 7 reserve exclusion, invalid-cave reverts, freeze before start, and interface ids.\n\n**The three info findings**, each with a concrete reproduction:\n\n- **Label filter accepts control bytes.** Any byte at or below 0x7F passes as ASCII, so a label of 0x01 0x7F deploys and yields an unusable https hostname. Deployer-only input, and the rehearsal labels are valid.\n- **Release closes seat claims.** The brief does not say what happens to claims after release. The code ends them, which the README documents and which avoids a cursor collision. Flagged for the requester to confirm.\n- **Prices are literal base units.** A full-price purchase burns 400000 wei of an 18-decimal coin. This follows the brief's \"base units\" wording and is documented, but is a 1e18 factor if whole PGMT was meant.\n\n**Static-analysis leads** were all checked and dismissed: the uninitialized local is a false positive, timestamp comparisons implement the schedule, and the constructor's plain mint is required by the empty-EVM deploy rule.\n\n**Not reached:** nothing within the assigned area. I did not run Slither or Mythril, which are not installed here.","treeHash":null,"usage":{"cachedInputTokens":866190,"inputTokens":354,"model":"claude-fable-5-1","outputTokens":23101,"runtime":"claude","turns":20,"wallClockMs":356373}},{"artifacts":[],"attempt":1,"bundleHash":"59a956b9c3a9b7fb38bfa587d632e3f44f6a7d18f0ed8fee06ee5c245d550796","device":"c5099ef07f22abee","findings":[],"hash":"37d88024dfe4a61aa92a7a125ef71b18d5f0ffec70065d5e37009da07847361a","nodeId":"3a7d85e4-91f6-4274-b3a2-e1fc3ca86116","outcome":"completed","summary":"Updated [launch.json](/root/.identitymd/work/4a7aca49-e340-4c57-b9b4-daf260d1c78e/3a7d85e4-91f6-4274-b3a2-e1fc3ca86116/launch.json) notes, preserving the approved constructor values and MockCoin → Ochre deployment order.\n\nSchema and ABI checks passed. `forge build` succeeded; `forge test` passed all 43 tests, including the protected deployment probe.\n\nOnly `launch.json` changed for submission.","treeHash":"17e4ddcf23713f614d64201d2ee21d88d5aae302","usage":{"cachedInputTokens":201600,"inputTokens":26129,"model":"gpt-6-astra","outputTokens":4497,"runtime":"codex","turns":4,"wallClockMs":117181}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"8daa15de069e1da9","findings":[],"hash":"8eccbb396983ecbbe90f8ebdedf2688348ca3a08627889ad038476ba69cee047","nodeId":"66ba0809-0769-4bff-8d76-abb1fca17f8c","outcome":"failed","summary":"{\"type\":\"error\",\"status\":400,\"error\":{\"type\":\"invalid_request_error\",\"message\":\"The 'gpt-6-astra' model is not supported when using Codex with a ChatGPT account.\"}}","treeHash":null,"usage":{"cachedInputTokens":0,"inputTokens":0,"model":null,"outputTokens":0,"runtime":"codex","turns":0,"wallClockMs":3179}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"14731ddbc51365d9","findings":[{"citation":"resolved","description":"The brief defines sale pieces as \"taken in this slot order: 5, 4, 3, 2, 1\" and says buy(c) \"takes the next sale piece in id order (round by round, slots as above)\". The parenthetical reads as: advance round by round and, inside a round, through the slots in the order given above, i.e. the gathering (slot 5) first, then line 4, line 3, and so on. The implementation walks a cave's 105 ids strictly ascending and returns the first unsold sale slot, so inside a round the lowest-numbered sale slot (line 2/3/4) sells before the gathering. README.md documents this as a deliberate 'ordering interpretation', so it is a specification ambiguity the requester must settle rather than an arithmetic error. It changes which physical piece each buyer receives in every cave with k>=2 (caves 3 to 7, 358 of the 400 sale pieces). Boundary lens: the id arithmetic itself (piece/pieceId/isSalePiece/saleCount) is exact; only the walk order inside a round differs between readings.","line":160,"path":"src/Ochre.sol","reproduction":"Deploy with the launch.json arguments. vm.warp(startTime + 2 days) so cave 3 is open (k=2: slots 4 and 5 are sale). First buy(3) returns 214 (cave 3, round 1, slot 4 = line 4) and the second returns 215 (slot 5 = gathering). Under the 5,4,3,2,1 reading the first buy should return 215 and the second 214. Likewise in cave 7 round 21 (k=5) the 81st buy(7) returns 731 (line 1); the slot-order reading expects 735 (gathering) first. Confirmed by running these calls against the compiled contract: cave3 first=214, second=215, cave7 round21 first=731.","severity":"low","snippet":"        while (offset < 105 && !isSalePiece(first + offset)) ++offset;","title":"buy() sells the slots of a round in ascending id order, not in the brief's 5,4,3,2,1 slot order"},{"citation":"resolved","description":"The brief's conditions for claimSeat are only 'msg.sender in seatRoot and not claimed before', and releaseUnclaimed is described as letting buy(c) 'also take any still-unclaimed free piece'. The contract adds a third condition: once anyone has called releaseUnclaimed() (callable by anyone from startTime + 8 days), claimSeat reverts with SeatsClosed forever. README.md states this resolves an unspecified policy, but the effect is that a wallet on the seat list that has not claimed by the moment someone calls releaseUnclaimed loses its free piece permanently and can only buy at floorPrice. Because the call is permissionless and the window is exactly 8 days, a competitor or bot can trigger the cutoff in the first block after the threshold. If the intended behaviour is that seat holders may still claim after release (with buyers taking only pieces nobody has claimed yet), the implementation needs claimSeat to stay open and skip pieces already sold, since both allocation paths walk the same free pieces in id order. Reported outside the strict math area because it is a boundary (time threshold) that permanently changes who receives 315 pieces.","line":185,"path":"src/Ochre.sol","reproduction":"Deploy with seatRoot = keccak256(abi.encodePacked(ALICE)) so ALICE is a valid seat holder with an empty proof. vm.warp(startTime + 8 days). Any address calls releaseUnclaimed() (succeeds). ALICE calls claimSeat([]) with a valid proof: expected per brief = mint id 1 to ALICE and emit Claimed(1, ALICE); actual = revert SeatsClosed(). A third party then calls buy(1) 21 times (ids 5,10,...,105) and a 22nd time: it receives id 1, ALICE's seat, for 40000 base units. Confirmed against the compiled contract.","severity":"low","snippet":"        if (unclaimedReleased || seatsMinted == 315) revert SeatsClosed();","title":"releaseUnclaimed() permanently closes claimSeat(); any third party can cut off every unclaimed seat at startTime + 8 days"},{"citation":"resolved","description":"Decimal-mismatch check from the Math Precision guide. The brief says 'startPrice(c) and floorPrice are constructor constants in coin base units: startPrice 400000 for every cave, floorPrice 40000 (rehearsal values, 18 decimals)' and separately 'the coin has 18 decimals, write that as a constant'. The contract follows the literal base-unit reading: a piece at open costs 400000 wei = 0.0000000000004 PGMT and the floor is 40000 wei. COIN_DECIMALS is exposed but no price, transfer or event uses it, so the request to write the decimals as a constant has no effect on behaviour. If the requester intended 400000 and 40000 whole PGMT (i.e. 400000 * 10**COIN_DECIMALS), every purchase is underpriced by a factor of 10**18. The arithmetic is internally consistent under either reading (the line falls exactly 5 wei per second with no rounding), so this is flagged for the requester to confirm the unit, not as a computational defect. README.md documents the literal choice.","line":13,"path":"src/Ochre.sol","reproduction":"Deploy with the launch.json arguments, vm.warp(startTime), approve 400000 and call buy(1). coin.balanceOf(0x...dEaD) becomes exactly 400000 (wei) and Bought(5, buyer, 400000) is emitted. Under the whole-coin reading the expected transfer would be 400000000000000000000000. Confirmed against the compiled contract: dead balance after one purchase at open = 400000.","severity":"info","snippet":"    uint8 public constant COIN_DECIMALS = 18;\n    uint256 public constant START_PRICE = 400_000;\n    uint256 public constant floorPrice = 40_000;","title":"Prices are literal 400000 / 40000 wei of an 18-decimal coin; COIN_DECIMALS is declared but never used in any computation"}],"hash":"94bfe6a561f418b41044515e353ad59d2b0c03ebe7149b17333b72d828f10be7","nodeId":"0676ea0e-eff9-43df-b6c1-195eec341973","outcome":"completed","summary":"Review complete. The findings file is written and the scratch test is removed, so the only change in the tree is `.imd-findings.json`.\n\n**Outcome: the arithmetic holds.** I traced every formula in `src/Ochre.sol` against the Math Precision, Boundary and Numerical Gap guides and found no computational defect. Specifically:\n\n- **Id arithmetic** is a bijection on ids 1 to 735. Sale-slot selection gives 21, 21, 42, 63, 84, 84, 85 pieces per cave, 400 in all, with 315 seats and 20 reserve pieces. The existing exhaustive test confirms it.\n- **Price line** is exact. The discount is 5 base units per second with no rounding, intermediates are tiny, and I verified monotone descent and the floor second by second across the whole 20 hour window and past it.\n- **Boundaries** behave as specified. Claims open at exactly startTime, each cave at exactly its open, release at exactly day 8, and the constructor bound on startTime rules out overflow in every time addition.\n- **Released-sale price** can never diverge from the quoted price, since release always lands at least 20 hours after the last cave opens.\n- **Reserve ids** 631 plus 5 times the counter land on exactly the 20 free cave 7 pieces, disjoint from every other path.\n- The slither uninitialized-local lead on `_validateLabel` is a false positive. The flag is meant to start false.\n\n**Three interpretation gaps reported**, each with a concrete reproduction confirmed against the compiled contract:\n\n1. **Low.** Inside a round, buy sells the lowest-numbered sale slot first. The brief's \"slots as above\" wording suggests gathering first, then line 4, 3, 2. First buy in cave 3 returns 214, not 215.\n2. **Low.** Anyone calling releaseUnclaimed at day 8 permanently closes claimSeat. The brief does not list this condition. A valid seat holder then reverts, and a third party can buy their seat at the floor.\n3. **Info.** Prices are literal wei amounts and the declared decimals constant is never used. One purchase at open burns 400000 wei, which is a vanishingly small fraction of one coin. The brief's base-unit wording supports this, but the requester should confirm.\n\n**Coverage.** All 14 entry points have rows, plus five invariant rows. Eleven hold, three point at the findings above. Nothing was left unreached. No finding reaches high or critical, so no proof test files were attached.","treeHash":null,"usage":{"cachedInputTokens":605196,"inputTokens":226,"model":"claude-fable-5-1","outputTokens":21861,"runtime":"claude","turns":22,"wallClockMs":344987}},{"artifacts":[],"attempt":2,"bundleHash":null,"device":"1731fbfe0c4574fb","findings":[{"citation":"resolved","description":"Merged from audit_flow, audit_math, audit_permissions and audit_economics (same root cause). The brief conditions claimSeat only on 'msg.sender in seatRoot and not claimed before', 'available from startTime', and describes releaseUnclaimed() as letting buy(c) 'also take any still-unclaimed free piece'. The implementation adds a third condition: once anyone has called releaseUnclaimed() (permissionless from startTime + 8 days), every further claimSeat reverts SeatsClosed, so a listed wallet that has not claimed by that moment forfeits its free piece and an unprivileged third party can take it for floorPrice in the same block. README.md ('Release closes seat claims') and test/Ochre.t.sol document this as a deliberate resolution of an unspecified policy, and it is coherent (the seatCursor loop at line 191 does not skip owned ids, so leaving claims open after release would mint an already-owned id and revert). It is reported as a design deviation for the requester to confirm, not a coding slip: if seats are meant to survive release, claimSeat must stay open and its cursor must skip owned ids the way the released branch of buy() does at line 169. Severity low: no funds are misdirected and rehearsal prices are negligible, but the brief's stated guarantee for claimSeat is narrowed.","line":185,"path":"src/Ochre.sol","reproduction":"Deploy Ochre with seatRoot = keccak256(abi.encodePacked(SEAT)) (single-leaf tree, empty proof valid). vm.warp(startTime + 8 days). From BOB (not in the root): releaseUnclaimed() succeeds. From SEAT: claimSeat(new bytes32[](0)) -> actual: revert SeatsClosed(); expected per the brief as written: mints id 1 to SEAT and emits Claimed(1, SEAT). BOB then calls buy(1) 22 times: calls 1..21 return 5,10,...,105 and call 22 returns id 1 for 40000 base units; ownerOf(1) == BOB, claimed(SEAT) == false, dead balance == 22 * 40000. Confirmed with test/scratch/Review.t.sol::test_releaseClosesClaims on this tree.","severity":"low","snippet":"        if (unclaimedReleased || seatsMinted == 315) revert SeatsClosed();","title":"releaseUnclaimed() permanently closes claimSeat(), a deadline the brief never states, and anyone can trigger it"},{"citation":"resolved","description":"Merged from audit_math, audit_permissions and audit_economics. The brief says sale pieces are 'taken in this slot order: 5, 4, 3, 2, 1' and that buy(c) 'takes the next sale piece in id order (round by round, slots as above)'. The code uses the 5,4,3,2,1 priority only to decide which slots are sale pieces (isSalePiece) and then walks the cave's 105 ids strictly ascending, so in any round with k >= 2 the lowest sale slot (a line) sells before the gathering. README.md 'Ordering interpretation' documents this choice. The two brief phrases are in tension ('in id order' supports the code; 'slots as above' supports gathering-first), so this is a specification ambiguity for the requester to settle. It affects which physical piece each buyer receives in caves 3..7 (358 of 400 sale pieces); the sale counts, prices and total allocation are unaffected.","line":160,"path":"src/Ochre.sol","reproduction":"Deploy with the launch.json arguments. vm.warp(startTime + 2 days) so cave 3 is open (k = 2: slots 4 and 5 are sale). buy(3) three times from a funded, approved wallet returns 214, 215, 219 (cave 3 round 1 slot 4, round 1 slot 5, round 2 slot 4). Under the 5,4,3,2,1 reading the sequence would be 215, 214, 220. At startTime + 6 days the 81st buy(7) (round 21, k = 5) returns 731 (line 1); the slot-order reading expects 735 (gathering). Confirmed with test/scratch/Review.t.sol::test_withinRoundOrder (logs: cave3 first 214, second 215, third 219, cave7 81st 731).","severity":"low","snippet":"        while (offset < 105 && !isSalePiece(first + offset)) ++offset;","title":"Within a round, buy() sells sale slots in ascending id order (4 before 5), not in the brief's listed slot order 5,4,3,2,1"},{"citation":"resolved","description":"From audit_economics; reproduced. Every issue path goes through _issue -> _safeMint, which calls onERC721Received when the recipient has code. The brief says claimSeat 'mints to msg.sender' with no receiver requirement and offers no alternative recipient parameter, so a listed wallet that is a contract lacking the hook (a minimal multisig, a vault, an account contract without ERC-721 receiver support) reverts on every attempt, stays unclaimed, and, combined with finding 1, loses its piece to a floor-price buyer after release. Buyers and reserve recipients are unaffected in practice (a buyer chooses to call; mintReserve's recipient is chosen by admin). A minimal fix that preserves intent is to use _mint in claimSeat (the recipient is the proven seat holder itself) or to accept an explicit recipient. Safes with the default fallback handler are fine; the gap is for contracts without the hook.","line":244,"path":"src/Ochre.sol","reproduction":"Deploy a contract W with no functions (contract NoHook {}). Deploy Ochre with seatRoot = keccak256(abi.encodePacked(address(W))). vm.warp(startTime). vm.prank(address(W)); claimSeat(new bytes32[](0)) -> actual: revert ERC721InvalidReceiver(W); claimed(W) == false, seatsMinted == 0. Expected per the brief: W is in the root and has not claimed, so the claim mints id 1 to W. Confirmed with test/scratch/Review.t.sol::test_contractSeatNoHook.","severity":"low","snippet":"        _safeMint(to, id);","title":"claimSeat() mints with _safeMint, so a seat wallet that is a contract without onERC721Received can never claim"},{"citation":"resolved","description":"Merged from audit_flow and audit_math. The brief says 'startPrice(c) and floorPrice are constructor constants in coin base units: startPrice 400000 for every cave, floorPrice 40000 (rehearsal values, 18 decimals)' and separately 'the coin has 18 decimals, write that as a constant'. The code follows the base-unit wording literally: a full-price purchase burns 400000 wei = 0.0000000000004 PGMT, and COIN_DECIMALS (line 13) participates in no computation. README.md and launch.json notes state this explicitly. If the requester meant 400000 whole PGMT the constants are off by 10**18; since the brief says 'base units' this is flagged for confirmation only. The arithmetic is exact under either reading (5 base units per second, no rounding).","line":14,"path":"src/Ochre.sol","reproduction":"vm.warp(1791352835); ochre.priceNow(1) == 400000; MockCoin.decimals() == 18; buy(1) returns id 5 and coin.balanceOf(0x000000000000000000000000000000000000dEaD) == 400000 exactly; at startTime + 1 priceNow(1) == 399995; at startTime + 20 hours - 1 it is 40005; at startTime + 20 hours it is 40000. Confirmed with test/scratch/Review.t.sol::test_priceUnits.","severity":"info","snippet":"    uint256 public constant START_PRICE = 400_000;","title":"Prices are literal 400000 / 40000 base units of an 18-decimal coin; COIN_DECIMALS is declared but never used"},{"citation":"resolved","description":"From audit_economics; reproduced. The guard is a strict less-than, so the call succeeds when block.timestamp == startTime + 8 days (1792044035). README.md and the delivered tests treat that second as eligible. One-second inclusive boundary, consistent with how caveOpen and startTime are treated inclusively elsewhere in the contract; harmless unless strictly-after was intended.","line":211,"path":"src/Ochre.sol","reproduction":"vm.warp(startTime + 8 days - 1); releaseUnclaimed() -> revert TooEarly. vm.warp(startTime + 8 days); releaseUnclaimed() -> succeeds, unclaimedReleased() == true. Confirmed with test/scratch/Review.t.sol::test_releaseBoundary.","severity":"info","snippet":"        if (block.timestamp < startTime + 8 days) revert TooEarly();","title":"releaseUnclaimed() is accepted at exactly startTime + 8 days although the brief says 'after'"},{"citation":"resolved","description":"From audit_flow; reproduced. _validateLabel accepts any byte <= 0x7F before the zero padding, so control characters (0x01..0x1F, 0x7F) pass as ASCII and tokenURI then builds an https URL whose hostname no resolver accepts. Only the deployer supplies labels, the seven rehearsal labels in launch.json are valid lowercase hostnames, and the brief's wording is 'up to 32 ASCII bytes', so this is a deployment-input hardening note, not a reachable defect for unprivileged callers.","line":257,"path":"src/Ochre.sol","reproduction":"new Ochre(coin, admin, adam, root, 1791352835, L, L, L, L, L, L, L) with L = bytes32(abi.encodePacked(bytes1(0x01), bytes1(0x7f))) deploys successfully; tokenURI(0) returns the 34-byte string \"https://\\x01\\x7f.sites.imd.fun/zero.json\". Confirmed with test/scratch/Review.t.sol::test_labelControlChars.","severity":"info","snippet":"            else if (ended || uint8(char) > 127) revert InvalidConfiguration();","title":"Label validation admits non-printable ASCII bytes, producing unusable https hostnames"},{"citation":"resolved","description":"From audit_permissions; reproduced. The rehearsal script hard-requires chain id 11155111, and forge script simulates with chain id 31337 unless --chain-id is passed, so `forge script script/Deploy.s.sol:Deploy --offline` exits with 'script failed: Sepolia only'. README.md documents the required `--chain-id 11155111` flag, launch.json (not this script) drives the factory deployment, and the deployed bytecode is unaffected, so this is an ergonomics note rather than a defect in the delivered contracts. I could not verify the specialist's claim of a network convention requiring 31337 to be accepted, so that part is not kept.","line":15,"path":"script/Deploy.s.sol","reproduction":"In the repository root: `forge script script/Deploy.s.sol:Deploy --offline` -> 'Error: script failed: Sepolia only', exit 1. `forge script script/Deploy.s.sol:Deploy --offline --chain-id 11155111` -> succeeds and returns the MockCoin and Ochre addresses. Both runs executed on this tree.","severity":"info","snippet":"        require(block.chainid == CHAIN_ID, \"Sepolia only\");","title":"Deploy.s.sol run() reverts under forge's default chain id, so a plain offline dry run fails"}],"hash":"9dc3086b635a898c5713b2c6bdf5b603e2ddac695943aa1e4d1680591c1d78bc","nodeId":"697a6046-d224-4fb6-93e7-ac399b7be9e1","outcome":"completed","summary":"The review is complete. `.imd-findings.json` is written at the repository root with 7 findings and 18 coverage rows (all 14 listed entry points plus 4 invariants); every path/line/snippet was verified to match the tree byte-for-byte, and no source or config file was changed.\n\n## What I did\n\n- Built the project and ran the delivered suite (59 tests, all pass, including the 737-piece exhaustion invariants).\n- Wrote `test/scratch/Review.t.sol` (scratch only, not kept) reproducing every specialist claim and probing my own leads — all 10 reproductions ran as described.\n- Re-read `src/Ochre.sol` end to end against the Pashov/x-ray/ToB checklists: constructor, id arithmetic, sale counts, price line, both `buy` branches, Merkle leaf encoding, reentrancy via `onERC721Received`, release/claim interaction, reserve ids, freeze, tokenURI, and the inherited OZ 5.0.2 ERC-721 surface.\n\n## Findings kept (merged and recalibrated)\n\n| # | Sev | Finding | Merged from |\n|---|---|---|---|\n| 1 | low | `releaseUnclaimed()` permanently closes `claimSeat`; anyone can trigger it at day 8 and buy the forfeited seat at floor | flow, math, permissions, economics |\n| 2 | low | Within-round sale order is ascending id (slot 4 before 5), not the brief's 5,4,3,2,1 | math, permissions, economics |\n| 3 | low | `claimSeat` uses `_safeMint`, so a contract seat wallet without the receiver hook can never claim | economics |\n| 4 | info | Prices are literal base units; `COIN_DECIMALS` unused — confirm unit intent | flow, math |\n| 5 | info | `releaseUnclaimed` inclusive at exactly `startTime + 8 days` | economics |\n| 6 | info | Label validation admits control bytes (deployer-only input) | flow |\n| 7 | info | `Deploy.s.sol` fails under forge's default chain id | permissions |\n\nFindings 1–3 are documented design choices in the README rather than coding slips, so I kept them at low: no funds are misdirected and the allocation totals hold, but each narrows or reinterprets a guarantee the brief states, and the requester should confirm. I dropped the specialist's unverifiable claim of a \"network convention\" requiring 31337 acceptance (finding 7 kept only the reproducible part). Nothing critical or high was found, so no proof files were attached.\n\n## My own pass found no additional defects\n\nReentrancy into `buy`/`claimSeat`/`releaseUnclaimed` from the receiver callback reverts with `ReentrancyGuardReentrantCall`; the released branch correctly skips claimed ids and excludes cave 7; full exhaustion reaches exactly 737 with every further mint reverting; the single-hash 20-byte Merkle leaf has no node-confusion exposure; coin can only move buyer → `0xdEaD`; runtime is 9,986 bytes with no forbidden opcodes.","treeHash":null,"usage":{"cachedInputTokens":786442,"inputTokens":25,"model":"claude-fable-5-1","outputTokens":21967,"runtime":"claude","turns":13,"wallClockMs":400262}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"468e82a89b9bfe18","findings":[{"citation":"resolved","description":"Trust-gap seam: access x asymmetry. The brief says claimSeat is 'Available from startTime' with no end, and that releaseUnclaimed() (callable by anyone after startTime + 8 days) makes 'any still-unclaimed free piece' purchasable. The implementation additionally makes release terminate claims: once unclaimedReleased is true, claimSeat reverts SeatsClosed for every wallet in seatRoot that has not yet claimed. Because releaseUnclaimed() is permissionless, an unprivileged actor decides the exact moment the free allocation of every slow seat holder is forfeited, and can take those pieces for the floor price in the same transaction. README.md section 'Buying, seats, and release' documents this as a deliberate resolution of an unspecified policy, and test/Ochre.t.sol:280-282 asserts it, so this is a design decision for the author to confirm rather than an implementation slip. If the intent is that seat holders keep their right until their piece is actually sold, claimSeat must stay open after release and its cursor loop (line 191) must also skip pieces already owned, as buy()'s released branch does at line 169; today the two cursors are asymmetric (buy checks _ownerOf, claimSeat does not), which is what forces the claims to be closed.","line":185,"path":"src/Ochre.sol","reproduction":"Deploy Ochre with seatRoot = keccak256(abi.encodePacked(SEAT)) (single-wallet list, empty proof valid). vm.warp(startTime + 8 days). From BOB (not in root): ochre.releaseUnclaimed() succeeds. From SEAT: ochre.claimSeat(new bytes32[](0)) -> reverts SeatsClosed (expected per brief: mints id 1 to SEAT). BOB then calls buy(1) 22 times: the first 21 return 5,10,...,105 (sale pieces) and the 22nd returns id 1, the seat holder's piece, for 40000 base units. Confirmed with a scratch Foundry test on this tree; the same behaviour is asserted by the delivered test testReleaseBoundaryEventAndRepeat (test/Ochre.t.sol:280-282).","severity":"low","snippet":"        if (unclaimedReleased || seatsMinted == 315) revert SeatsClosed();","title":"releaseUnclaimed() lets any third party end seat claims, which the brief never closes (access x asymmetry)"},{"citation":"resolved","description":"Outside the assigned area, reported because it is reproducible and affects verification. The script is a plain contract (not forge-std Script) and hard-requires chain id 11155111. forge script runs with chain id 31337 unless --chain-id is passed, so the standard offline dry run `EXPECTED_CHAIN_ID=0 forge script script/Deploy.s.sol:Deploy --offline` exits 1 with 'Error: script failed: Sepolia only'. The network convention is that deploy scripts accept 31337 plus the target chain. launch.json, not this script, drives the factory deployment, so the deployed bytecode is unaffected; the defect is that the rehearsal script cannot be executed by the verifier's generic invocation.","line":15,"path":"script/Deploy.s.sol","reproduction":"In the repository root run `EXPECTED_CHAIN_ID=0 forge script script/Deploy.s.sol:Deploy --offline` -> trace shows `Deploy::run()  <- [Revert] Sepolia only`, exit status 1. `forge script script/Deploy.s.sol:Deploy --offline --chain-id 31337` also exits 1. Only `--chain-id 11155111` succeeds (deploys MockCoin and Ochre). Expected: the script accepts 31337 and 11155111, as the README build instructions imply a local dry run is possible.","severity":"low","snippet":"        require(block.chainid == CHAIN_ID, \"Sepolia only\");","title":"Deploy.s.sol run() reverts on every chain except Sepolia, so the offline dry run fails on the default chain"},{"citation":"resolved","description":"The brief says sale pieces are 'taken in this slot order: 5, 4, 3, 2, 1' and that buy 'takes the next sale piece in id order (round by round, slots as above)'. The implementation uses the slot order only to select which slots are sale pieces and then sells them in ascending id order, so in a round with k >= 2 sale pieces the lower slot sells first (slot 4 before slot 5). README.md 'Ordering interpretation' documents this choice. Price is time-based, so no value is misallocated; only the id a given buyer receives differs between the two readings. Recorded so the author can confirm the intended reading; no fix is required if ascending id order is intended.","line":160,"path":"src/Ochre.sol","reproduction":"vm.warp(startTime + 2 days); buy(3) three times from a funded, approved wallet returns 214, 215, 219 (slot 4, slot 5, next round's slot 4). Under the slot-order reading the sequence would be 215, 214, 220. Confirmed with a scratch Foundry test on this tree.","severity":"info","snippet":"        while (offset < 105 && !isSalePiece(first + offset)) ++offset;","title":"Sale pieces within a round are sold in ascending id order, not in the brief's slot order 5,4,3,2,1"}],"hash":"e90e5fc3d10e7479ab8b315c8b7cdd97bc700bbba26c8ff4cdfa31c73bc62bd1","nodeId":"96261fff-b811-4bac-be9a-8335fb8a44c4","outcome":"completed","summary":"The review is complete. Findings are in `.imd-findings.json` with all 14 entry points covered, and no source file was changed.\n\n**Outcome:** the permission model of Ochre and MockCoin holds. No critical, high or medium defect was found in the Access Control, Trust Gap or Asymmetry areas. Three low or informational items were recorded, each with a reproduction I confirmed on this tree.\n\n**What I checked**\n\n- Mapped every role: the immutable admin holds only reserve minting and one-time freeze per cave. Every other entry point is permissionless and gated by time, Merkle proof or cursor exhaustion. Every storage variable has exactly one writer path with a consistent guard.\n- Traced both branches of buy, the claim cursor, the reserve id arithmetic and the released-piece scan. The coin leaves only via one transferFrom to the dead address, and no confused-deputy route can spend a buyer's allowance.\n- Verified the vendored OpenZeppelin 5.0.2 and forge-std 1.9.7 against the upstream archives. Archive hashes match lib/README.md, and the only file differences are forge fmt line wrapping.\n- Scanned the compiled runtime for DELEGATECALL, CALLCODE and SELFDESTRUCT (none), ran the full suite plus a second fuzz seed (all pass), and checked formatting.\n\n**Findings reported**\n\n1. **Low.** Any third party's releaseUnclaimed call closes claimSeat for every seat holder who has not claimed by day 8, and the caller can buy those pieces at the floor in the same transaction. The brief never ends claims. The README documents this as a deliberate choice, so it is for the author to confirm.\n2. **Low, outside my area.** The deploy script rejects every chain except Sepolia, so the generic offline dry run on chain 31337 exits with \"Sepolia only\".\n3. **Info.** Sale pieces within a round sell in ascending id order (214 then 215 in cave 3), while the brief's wording can also be read as slot order 5,4,3,2,1.\n\n**Not reached:** nothing in the assigned area. The ERC-721 transfer and approval functions are unmodified OpenZeppelin code and were covered by inspection rather than new tests.","treeHash":null,"usage":{"cachedInputTokens":1142706,"inputTokens":354,"model":"claude-fable-5-1","outputTokens":26268,"runtime":"claude","turns":28,"wallClockMs":376063}},{"artifacts":[],"attempt":1,"bundleHash":"661e3c561e8a28318df90fed8482db5e7a799025b55ee60fb457eb46ab0303b4","device":"33ce0bb3dec09f0b","findings":[],"hash":"fccce36f8081670db506e506ac08b9dff5936e661ae699813eca9e7b03874ffa","nodeId":"0a1c4745-1ecc-464d-9234-40cf82976569","outcome":"completed","summary":"Implemented MockCoin, Ochre, vendored dependencies, deployment configuration, tests, and [documentation](/root/.identitymd/work/4a7aca49-e340-4c57-b9b4-daf260d1c78e/0a1c4745-1ecc-464d-9234-40cf82976569/README.md).\n\nValidation passed:\n\n- `forge build`\n- `forge test`: **42 tests passed**, including fuzzing\n- `forge fmt --check`\n- Sepolia deployment dry run\n\nDocumented interpretations: literal base-unit prices, ascending token-id sale order, and claims closing upon release.\n\nThe supplied seat root remains a placeholder. No on-chain transactions were broadcast.","treeHash":"112630f6713b2ea8a2bba40a1602b2f35e3d16f6","usage":{"cachedInputTokens":594304,"inputTokens":58607,"model":"gpt-6-astra","outputTokens":28843,"runtime":"codex","turns":8,"wallClockMs":667677}}],"verification":[{"checks":[{"durationMs":4848,"exitCode":0,"name":"build","output":"Compiling 46 files with Solc 0.8.26\nSolc 0.8.26 finished in 4.58s\nCompiler run successful!\nwarning[unsafe-oz-erc721-mint]: `ERC721._mint` does not check that the recipient can receive the token; use `_safeMint`\n   ╭▸ src/Ochre.sol:91:9\n   │\n91 │         _mint(adam_, 0);\n   │         ━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-oz-erc721-mint\n\nwarning[unsafe-oz-erc721-mint]: `ERC721._mint` does not check that the recipient can receive the token; use `_safeMint`\n   ╭▸ src/Ochre.sol:92:9\n   │\n92 │         _mint(admin_, 736);\n   │         ━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-oz-erc721-mint\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Ochre.sol:252:34\n    │\n252 │         if (label == bytes32(0)) revert InvalidConfiguration();\n    │                                  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Ochre.sol:257:50\n    │\n257 │             else if (ended || uint8(char) > 127) revert InvalidConfiguration();\n    │                                                  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Ochre.sol:114:13\n    │\n114 │         if (block.timestamp <= opens) return START_PRICE;\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Ochre.sol:116:13\n    │\n116 │         if (elapsed >= PRICE_DURATION) return floorPrice;\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_owners` is updated\n    ╭▸ src/Ochre.sol:178:14\n    │\n178 │         if (!coin.transferFrom(msg.sender, dead, price)) revert PaymentFailed();\n    │              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Ochre.sol:156:13\n    │\n156 │         if (block.timestamp < caveOpen(cave)) revert NotOpen();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Ochre.sol:180:9\n    │\n180 │         emit Bought(id, msg.sender, price);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Ochre.sol:122:31\n    │\n122 │         if (id >= MAX_SUPPLY) revert InvalidPiece();\n    │                               ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Ochre.sol:248:36\n    │\n248 │         if (cave == 0 || cave > 7) revert InvalidCave();\n    │                                    ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Ochre.sol:137:39\n    │\n137 │         if (round == 0 || round > 21) revert InvalidPiece();\n    │                                       ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Ochre.sol:184:13\n    │\n184 │         if (block.timestamp < startTime) revert NotOpen();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Ochre.sol:197:9\n    │\n197 │         emit Claimed(id, msg.sender);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/Ochre.sol:201:57\n    │\n201 │     function mintReserve(address to) external onlyAdmin nonReentrant returns (uint256 id) {\n    │                                                         ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Ochre.sol:206:9\n    │\n206 │         emit ReserveMinted(id, to);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Ochre.sol:211:13\n    │\n211 │         if (block.timestamp < startTime + 8 days) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/Ochre.sol:222:55\n    │\n222 │         if (raw.length == 0 || raw[raw.length - 1] != bytes1(\"/\")) revert InvalidBase();\n    │                                                       ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'bytes1' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Ochre.sol:257:22\n    │\n257 │             else if (ended || uint8(char) > 127) revert InvalidConfiguration();\n    │                      ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Ochre.sol:263:16\n    │\n263 │         while (length < 32 && label[length] != 0) ++length;\n    │                ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\n","passed":true},{"durationMs":14240,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 7 tests for test/MockCoinAndDeployment.t.sol:MockCoinAndDeploymentTest\n[PASS] testConstructorAcceptsCoinWithNoCodeAndSkipsReceiverCallbacks() (gas: 119615)\n[PASS] testConstructorRejectsZeroAddressesAndTimestampOverflow() (gas: 4689)\n[PASS] testDeploymentHelperRejectsOtherChains() (gas: 3542867)\n[PASS] testExactSepoliaRehearsalDeployment() (gas: 13332196)\n[PASS] testLabelLengthsAndInvalidPadding() (gas: 50754)\n[PASS] testMockCoinInitialSupplyAndPermissionlessMint() (gas: 142562)\n[PASS] testMockCoinTransferAndAllowance() (gas: 207102)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 57.65ms (48.58ms CPU time)\n\nRan 6 tests for test/MetadataAndERC721.t.sol:MetadataAndERC721Test\n[PASS] testAllURIsBeforeAndAfterIndependentCaveFreezes() (gas: 114006383)\n[PASS] testBadTransferRecipientsAndWrongOwnerRollback() (gas: 422685)\n[PASS] testEndpointAndSampleURIs() (gas: 666122)\n[PASS] testFreezeAuthorizationInputAndFutureTokens() (gas: 423514)\n[PASS] testTransfersApprovalsAndApprovalClearing() (gas: 596574)\n[PASS] testUnmintedMetadataAndOwnerQueriesRevert() (gas: 57735)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 153.15ms (154.12ms CPU time)\n\nRan 8 tests for test/Adversarial.t.sol:AdversarialTest\n[PASS] testClaimRejectionRollbackAndReentrancy() (gas: 1020760)\n[PASS] testCoinCannotReenterBuy() (gas: 1178686)\n[PASS] testFalseOrRevertingCoinRestoresSaleAndBalances() (gas: 1197418)\n[PASS] testMissingCoinReturnIsRejected() (gas: 220202)\n[PASS] testReceiverCannotReenterBuyOrRelease() (gas: 1141427)\n[PASS] testReceiverRejectRestoresPaymentAllowanceAndSale() (gas: 1081895)\n[PASS] testReleasedSeatPaymentFailureDoesNotSkipItsId() (gas: 3263938)\n[PASS] testReserveRecipientRejectsWithoutConsumingReserve() (gas: 808282)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 1.01s (16.56ms CPU time)\n\nRan 11 tests for test/BoundaryProperties.t.sol:BoundaryPropertiesTest\n[PASS] testFuzzBuyDebitsExactPriceAndEmitsPaymentMintAndPurchase(uint256,uint256) (runs: 512, μ: 292083, ~: 291822)\nLogs:\n  Bound result 7\n  Bound result 3\n\n[PASS] testFuzzInvalidCavesFailBeforeArithmetic(uint256,bool) (runs: 256, μ: 138680, ~: 136835)\nLogs:\n  Bound result 791579930581987860060763759766065831813789839259\n\n[PASS] testFuzzInvalidIdsRoundsAndSlots(uint256,uint256,uint256,bool) (runs: 256, μ: 83406, ~: 83585)\nLogs:\n  Bound result 2889695548034689055505947\n\n[PASS] testFuzzPartialSeatClaimsAndReleaseReachExactly737(uint256,uint256) (runs: 64, μ: 94173880, ~: 93723353)\nLogs:\n  Bound result 10\n  Bound result 147\n\n[PASS] testMaximumAcceptedStartHasSafeOpeningPriceAndReleaseArithmetic() (gas: 499518)\n[PASS] testPartialReleaseAcrossCaveFiveSeatBoundary() (gas: 304256216)\n[PASS] testPartialReleaseAcrossCaveFourSeatBoundary() (gas: 301143367)\n[PASS] testPartialReleaseAcrossCaveOneSeatBoundary() (gas: 275230430)\n[PASS] testPartialReleaseAcrossCaveThreeSeatBoundary() (gas: 295265139)\n[PASS] testPartialReleaseAcrossCaveTwoSeatBoundary() (gas: 286625765)\n[PASS] testPartialReleaseAtEmptyAndFullSeatBoundaries() (gas: 292751917)\nSuite result: ok. 11 passed; 0 failed; 0 skipped; finished in 6.45s (15.83s CPU time)\n\nRan 21 tests for test/Ochre.t.sol:OchreTest\n[PASS] testAll737UniquePiecesAndNoFurtherMinting() (gas: 85091566)\n[PASS] testAllPieceArithmeticAndAllocationCounts() (gas: 22942789)\n[PASS] testBuyMissingAllowanceRollsBack() (gas: 393372)\n[PASS] testBuyMissingBalanceRollsBack() (gas: 345874)\n[PASS] testBuyPaymentAndEventNoWalletLimit() (gas: 375439)\n[PASS] testCannotSendEth() (gas: 65703)\n[PASS] testClaimOpeningProofReplayAndEvent() (gas: 386760)\n[PASS] testEveryCaveRejectsBeforeOpenAndAcceptsAtOpen() (gas: 1208140)\n[PASS] testExactSaleSequenceAndExhaustionAllCaves() (gas: 44147275)\n[PASS] testFuzzPriceLine(uint8,uint32) (runs: 256, μ: 12955, ~: 13137)\n[PASS] testInitialStateAndInterfaces() (gas: 141466)\n[PASS] testInvalidCaveAndPieceInputs() (gas: 117813)\n[PASS] testPriceBoundariesEveryCave() (gas: 579849)\n[PASS] testProofIsBoundToCallerAndSiblingOrdering() (gas: 840677)\n[PASS] testReleaseBoundaryEventAndRepeat() (gas: 155136)\n[PASS] testReleaseIsExplicitAndSkipsClaimedEvenAfterTransfer() (gas: 2651126)\n[PASS] testReleaseNeverSellsCaveSevenReserve() (gas: 9953387)\n[PASS] testReleasedSeatsFollowRemainingSales() (gas: 2796543)\n[PASS] testReserveAuthorizationEventCapAndNoOpeningRestriction() (gas: 1516315)\n[PASS] testReserveZeroRecipientRollsBack() (gas: 178731)\n[PASS] testSortedMerkleTreeAll315SeatsAndCap() (gas: 91363088)\nSuite result: ok. 21 passed; 0 failed; 0 skipped; finished in 6.45s (745.09ms CPU time)\n\nRan 3 tests for test/MockCoinInvariant.t.sol:MockCoinInvariantTest\n[PASS] invariant_supplyBalancesAndAllowancesMatchIndependentLedger() (runs: 256, calls: 32768, reverts: 0)\n\n╭------------------------+------------------+-------+---------+----------╮\n| Contract               | Selector         | Calls | Reverts | Discards |\n+========================================================================+\n| PigmentSequenceHandler | approve          | 5435  | 0       | 0        |\n|------------------------+------------------+-------+---------+----------|\n| PigmentSequenceHandler | invalidOperation | 5420  | 0       | 0        |\n|------------------------+------------------+-------+---------+----------|\n| PigmentSequenceHandler | mint             | 5587  | 0       | 0        |\n|------------------------+------------------+-------+---------+----------|\n| PigmentSequenceHandler | spend            | 5345  | 0       | 0        |\n|------------------------+------------------+-------+---------+----------|\n| PigmentSequenceHandler | spendExisting    | 5430  | 0       | 0        |\n|------------------------+------------------+-------+---------+----------|\n| PigmentSequenceHandler | transfer         | 5551  | 0       | 0        |\n╰------------------------+------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 168\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 2\n  Bound result 242\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 3\n  Bound result 1\n  Bound result 4\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 3\n  Bound result 28600000\n  Bound result 0\n  Bound result 3\n  Bound result 3\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 47430\n  Bound result 0\n  Bound result 3\n  Bound result 1\n  Bound result 854405928272041173304653986\n  Bound result 1\n  Bound result 0\n  Bound result 3\n  Bound result 1\n  Bound result 0\n  Bound result 2\n  Bound result 3391\n  Bound result 1\n  Bound result 4\n  Bound result 12967\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 91834\n  Bound result 3\n  Bound result 1\n  Bound result 745395216437679723143660941\n  Bound result 1\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 8\n  Bound result 2\n  Bound result 1\n  Bound result 3\n  Bound result 221\n  Bound result 0\n  Bound result 3\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 84\n  Bound result 4\n  Bound result 16000000\n  Bound result 1\n  Bound result 3\n  Bound result 4\n  Bound result 3\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 2\n  Bound result 4\n  Bound result 2\n  Bound result 2\n  Bound result 63\n  Bound result 0\n  Bound result 1\n  Bound result 2\n  Bound result 25485740\n  Bound result 1\n  Bound result 0\n  Bound result 2\n  Bound result 8925643787713003080627\n  Bound result 2\n  Bound result 0\n  Bound result 3\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 1000000000000000000\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 3\n  Bound result 638212886\n  Bound result 0\n  Bound result 3\n  Bound result 6500\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 129\n  Bound result 2\n  Bound result 3\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 3\n  Bound result 3\n  Bound result 109\n  Bound result 3\n  Bound result 3\n  Bound result 0\n  Bound result 231\n  Bound result 4\n  Bound result 710221914\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 3\n  Bound result 22\n  Bound result 3\n  Bound result 0\n  Bound result 101\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 2172\n  Bound result 1\n  Bound result 4\n  Bound result 3\n  Bound result 630\n  Bound result 3\n  Bound result 0\n  Bound result 1\n  Bound result 2169230016894315561434066\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 657\n  Bound result 2\n  Bound result 2\n  Bound result 3\n  Bound result 15\n  Bound result 3\n  Bound result 1\n  Bound result 2\n  Bound result 20\n  Bound result 1\n  Bound result 0\n  Bound result 65536\n  Bound result 0\n  Bound result 4\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 192308068610951695609544466072\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1000000000000000000000000000000\n  Bound result 1\n  Bound result 2\n  Bound result 2\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 17\n  Bound result 1\n  Bound result 3\n  Bound result 0\n  Bound result 69632\n  Bound result 0\n  Bound result 3\n  Bound result 1\n  Bound result 3\n  Bound result 83\n  Bound result 3\n  Bound result 4\n  Bound result 2\n  Bound result 9255\n  Bound result 0\n  Bound result 448048746273798068563799450933\n  Bound result 1\n  Bound result 0\n  Bound result 3\n  Bound result 3\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 6217\n  Bound result 1\n  Bound result 0\n  Bound result 2\n  Bound result 3\n  Bound result 10\n  Bound result 1\n  Bound result 4\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 4\n  Bound result 1\n  Bound result 690004940724479345111858597\n  Bound result 0\n  Bound result 4\n  Bound result 1611234720602037826129802884869\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 3\n  Bound result 2\n  Bound result 293\n  Bound result 2\n  Bound result 3\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 1\n  Bound result 167\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 3\n  Bound result 0\n  Bound result 2\n  Bound result 3\n  Bound result 3\n  Bound result 0\n  Bound result 0\n  Bound result 3\n  Bound result 3\n  Bound result 3\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1804\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 3\n  Bound result 0\n  Bound result 3\n  Bound result 0\n  Bound result 2\n  Bound result 3888\n  Bound result 2\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 3\n  Bound result 2\n  Bound result 3\n  Bound result 0\n  Bound result 3\n  Bound result 3\n  Bound result 576\n  Bound result 0\n  Bound result 1\n  Bound result 3\n  Bound result 0\n  Bound result 0\n  Bound result 7987\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 3\n  Bound result 0\n  Bound result 1\n  Bound result 22693953596380536125479499047\n  Bound result 2\n  Bound result 1\n  Bound result 2\n  Bound result 110644337799021\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 2062177004198107197624417456\n  Bound result 0\n  Bound result 4\n  Bound result 0\n  Bound result 854405928272041173304653985\n  Bound result 1\n  Bound result 2\n  Bound result 2\n  Bound result 0\n  Bound result 0\n  Bound result 5417\n  Bound result 1\n  Bound result 3\n  Bound result 0\n  Bound result 4\n  Bound result 604800\n  Bound result 2\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 85\n  Bound result 2\n  Bound result 0\n  Bound result 3\n  Bound result 277\n  Bound result 1\n  Bound result 4\n  Bound result 3\n  Bound result 1000000002000000000000000000\n  Bound result 2\n  Bound result 3\n  Bound result 6237\n  Bound result 0\n  Bound result 3\n  Bound result 3\n  Bound result 4\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 263\n  Bound result 0\n  Bound result 3\n  Bound result 2\n  Bound result 139266\n  Bound result 2\n  Bound result 2538\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 2367439\n  Bound result 0\n  Bound result 4\n  Bound result 6034712837323365280829813767\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 459\n  Bound result 0\n  Bound result 3\n  Bound result 4\n  Bound result 3\n  Bound result 3\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 315\n  Bound result 1\n  Bound result 9365\n  Bound result 1\n\n[PASS] testHandlerReachesFiniteInfiniteSelfAndDeadTransfers() (gas: 965021)\nLogs:\n  Bound result 1\n  Bound result 100\n  Bound result 3\n  Bound result 1\n  Bound result 1\n  Bound result 100\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 3\n  Bound result 2\n  Bound result 40\n  Bound result 1\n  Bound result 4\n  Bound result 2\n  Bound result 30\n  Bound result 1\n  Bound result 3\n  Bound result 2\n  Bound result 30\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 4\n\n[PASS] testMaximumSupplyAndMintOverflowAreAtomic() (gas: 242170)\nSuite result: ok. 3 passed; 0 failed; 0 skipped; finished in 11.88s (11.87s CPU time)\n\nRan 2 tests for test/OchreInvariant.t.sol:OchreOpeningInvariantTest\n[PASS] invariant_allocationOwnershipAndPaymentConservation() (runs: 128, calls: 16384, reverts: 0)\n\n╭----------------------+---------------+-------+---------+----------╮\n| Contract             | Selector      | Calls | Reverts | Discards |\n+===================================================================+\n| OchreSequenceHandler | advanceTime   | 2019  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| OchreSequenceHandler | buyBatch      | 1998  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| OchreSequenceHandler | claim         | 1970  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| OchreSequenceHandler | freeze        | 2057  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| OchreSequenceHandler | release       | 2068  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| OchreSequenceHandler | reserve       | 2076  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| OchreSequenceHandler | shortPayment  | 2116  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| OchreSequenceHandler | transferPiece | 2080  | 0       | 0        |\n╰----------------------+---------------+-------+---------+----------╯\n\nLogs:\n  Bound result 0\n  Bound result 2\n  Bound result 3\n  Bound result 0\n  Bound result 3\n  Bound result 2\n  Bound result 314\n  Bound result 6\n  Bound result 7\n  Bound result 1\n  Bound result 2\n  Bound result 0\n  Bound result 1\n  Bound result 4\n  Bound result 672\n  Bound result 3\n  Bound result 6\n  Bound result 0\n  Bound result 4\n  Bound result 5\n  Bound result 52797\n  Bound result 3\n  Bound result 3\n  Bound result 2\n  Bound result 5\n  Bound result 8\n  Bound result 2\n  Bound result 6\n  Bound result 2\n  Bound result 5\n  Bound result 0\n  Bound result 3\n  Bound result 1\n  Bound result 52997\n  Bound result 6\n  Bound result 2\n  Bound result 6\n  Bound result 6\n  Bound result 7\n  Bound result 2\n  Bound result 2\n  Bound result 0\n  Bound result 3\n  Bound result 0\n  Bound result 2\n  Bound result 6\n  Bound result 4\n  Bound result 0\n  Bound result 3\n  Bound result 7\n  Bound result 3\n  Bound result 5\n  Bound result 7\n  Bound result 2\n  Bound result 5\n  Bound result 2\n  Bound result 8\n  Bound result 7\n  Bound result 5\n  Bound result 7\n  Bound result 7\n  Bound result 4\n  Bound result 4\n  Bound result 3\n  Bound result 1\n  Bound result 0\n  Bound result 7\n  Bound result 7\n  Bound result 4\n  Bound result 0\n  Bound result 7\n  Bound result 0\n  Bound result 7\n  Bound result 1\n  Bound result 5\n  Bound result 86393\n  Bound result 1\n  Bound result 7\n  Bound result 5\n  Bound result 3\n  Bound result 2\n  Bound result 8\n  Bound result 4\n  Bound result 1\n  Bound result 8\n  Bound result 2\n  Bound result 6\n  Bound result 6\n  Bound result 7\n  Bound result 6\n  Bound result 1\n  Bound result 36\n  Bound result 2\n  Bound result 2\n  Bound result 6\n  Bound result 1\n  Bound result 0\n  Bound result 5\n  Bound result 2\n  Bound result 7\n  Bound result 3\n  Bound result 3\n  Bound result 1\n  Bound result 2\n  Bound result 4\n  Bound result 1\n  Bound result 3\n  Bound result 7\n  Bound result 5\n  Bound result 2\n  Bound result 4\n  Bound result 2\n  Bound result 6\n  Bound result 3\n  Bound result 214\n  Bound result 4\n  Bound result 6\n  Bound result 7\n  Bound result 3\n  Bound result 4\n  Bound result 2\n  Bound result 16\n  Bound result 6\n  Bound result 1\n  Bound result 95\n  Bound result 1\n  Bound result 2\n  Bound result 3\n  Bound result 4240\n  Bound result 6\n  Bound result 5\n  Bound result 7\n  Bound result 453\n  Bound result 6\n  Bound result 6\n  Bound result 1\n  Bound result 7\n  Bound result 62\n  Bound result 5\n  Bound result 3\n  Bound result 5\n  Bound result 4\n  Bound result 1\n  Bound result 3\n  Bound result 0\n  Bound result 253\n  Bound result 0\n  Bound result 6\n  Bound result 3\n  Bound result 0\n  Bound result 7\n  Bound result 53\n  Bound result 1\n  Bound result 3\n  Bound result 511\n  Bound result 7\n  Bound result 4\n  Bound result 4\n  Bound result 7\n  Bound result 4\n  Bound result 7\n  Bound result 7\n  Bound result 2\n  Bound result 8\n  Bound result 1\n  Bound result 2\n  Bound result 7\n  Bound result 5\n  Bound result 6\n  Bound result 3\n  Bound result 16\n  Bound result 0\n  Bound result 2\n  Bound result 2\n  Bound result 10\n  Bound result 5\n  Bound result 0\n  Bound result 45\n  Bound result 2\n  Bound result 0\n  Bound result 7\n  Bound result 7\n  Bound result 7\n  Bound result 4\n  Bound result 3\n  Bound result 0\n  Bound result 7\n  Bound result 4\n  Bound result 55\n  Bound result 6\n  Bound result 1\n  Bound result 324\n  Bound result 6\n  Bound result 6\n  Bound result 1\n  Bound result 2\n  Bound result 2\n  Bound result 20\n  Bound result 0\n  Bound result 2\n  Bound result 2\n  Bound result 4\n  Bound result 2\n  Bound result 4\n  Bound result 19965\n  Bound result 0\n  Bound result 10\n  Bound result 2\n  Bound result 0\n  Bound result 3\n  Bound result 1\n  Bound result 5\n  Bound result 2\n  Bound result 4\n  Bound result 7\n  Bound result 5\n  Bound result 8\n  Bound result 4\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 4\n  Bound result 7\n  Bound result 7\n  Bound result 2\n  Bound result 7\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 13996\n  Bound result 4\n  Bound result 34465\n  Bound result 66\n  Bound result 5\n  Bound result 3\n  Bound result 3\n  Bound result 4\n  Bound result 7\n\n[PASS] testHandlerTransitionsReachClaimsSalesReleaseAndExhaustion() (gas: 100523608)\nLogs:\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 2\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 7\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 8\n  Bound result 1\n  Bound result 1\n  Bound result 8\n  Bound result 2\n  Bound result 1\n  Bound result 8\n  Bound result 3\n  Bound result 1\n  Bound result 8\n  Bound result 4\n  Bound result 1\n  Bound result 8\n  Bound result 5\n  Bound result 1\n  Bound result 8\n  Bound result 6\n  Bound result 1\n  Bound result 8\n  Bound result 7\n  Bound result 1\n  Bound result 8\n  Bound result 0\n  Bound result 1\n  Bound result 8\n  Bound result 1\n  Bound result 1\n  Bound result 8\n  Bound result 2\n  Bound result 1\n  Bound result 8\n  Bound result 3\n  Bound result 1\n  Bound result 8\n  Bound result 4\n  Bound result 1\n  Bound result 8\n  Bound result 5\n  Bound result 1\n  Bound result 8\n  Bound result 0\n  Bound result 2\n  Bound result 8\n  Bound result 1\n  Bound result 2\n  Bound result 8\n  Bound result 2\n  Bound result 2\n  Bound result 8\n  Bound result 3\n  Bound result 2\n  Bound result 8\n  Bound result 4\n  Bound result 2\n  Bound result 8\n  Bound result 5\n  Bound result 2\n  Bound result 8\n  Bound result 6\n  Bound result 2\n  Bound result 8\n  Bound result 7\n  Bound result 2\n  Bound result 8\n  Bound result 0\n  Bound result 2\n  Bound result 8\n  Bound result 1\n  Bound result 2\n  Bound result 8\n  Bound result 2\n  Bound result 2\n  Bound result 8\n  Bound result 3\n  Bound result 2\n  Bound result 8\n  Bound result 4\n  Bound result 2\n  Bound result 8\n  Bound result 5\n  Bound result 2\n  Bound result 8\n  Bound result 0\n  Bound result 3\n  Bound result 8\n  Bound result 1\n  Bound result 3\n  Bound result 8\n  Bound result 2\n  Bound result 3\n  Bound result 8\n  Bound result 3\n  Bound result 3\n  Bound result 8\n  Bound result 4\n  Bound result 3\n  Bound result 8\n  Bound result 5\n  Bound result 3\n  Bound result 8\n  Bound result 6\n  Bound result 3\n  Bound result 8\n  Bound result 7\n  Bound result 3\n  Bound result 8\n  Bound result 0\n  Bound result 3\n  Bound result 8\n  Bound result 1\n  Bound result 3\n  Bound result 8\n  Bound result 2\n  Bound result 3\n  Bound result 8\n  Bound result 3\n  Bound result 3\n  Bound result 8\n  Bound result 4\n  Bound result 3\n  Bound result 8\n  Bound result 5\n  Bound result 3\n  Bound result 8\n  Bound result 0\n  Bound result 4\n  Bound result 8\n  Bound result 1\n  Bound result 4\n  Bound result 8\n  Bound result 2\n  Bound result 4\n  Bound result 8\n  Bound result 3\n  Bound result 4\n  Bound result 8\n  Bound result 4\n  Bound result 4\n  Bound result 8\n  Bound result 5\n  Bound result 4\n  Bound result 8\n  Bound result 6\n  Bound result 4\n  Bound result 8\n  Bound result 7\n  Bound result 4\n  Bound result 8\n  Bound result 0\n  Bound result 4\n  Bound result 8\n  Bound result 1\n  Bound result 4\n  Bound result 8\n  Bound result 2\n  Bound result 4\n  Bound result 8\n  Bound result 3\n  Bound result 4\n  Bound result 8\n  Bound result 4\n  Bound result 4\n  Bound result 8\n  Bound result 5\n  Bound result 4\n  Bound result 8\n  Bound result 0\n  Bound result 5\n  Bound result 8\n  Bound result 1\n  Bound result 5\n  Bound result 8\n  Bound result 2\n  Bound result 5\n  Bound result 8\n  Bound result 3\n  Bound result 5\n  Bound result 8\n  Bound result 4\n  Bound result 5\n  Bound result 8\n  Bound result 5\n  Bound result 5\n  Bound result 8\n  Bound result 6\n  Bound result 5\n  Bound result 8\n  Bound result 7\n  Bound result 5\n  Bound result 8\n  Bound result 0\n  Bound result 5\n  Bound result 8\n  Bound result 1\n  Bound result 5\n  Bound result 8\n  Bound result 2\n  Bound result 5\n  Bound result 8\n  Bound result 3\n  Bound result 5\n  Bound result 8\n  Bound result 4\n  Bound result 5\n  Bound result 8\n  Bound result 5\n  Bound result 5\n  Bound result 8\n  Bound result 0\n  Bound result 6\n  Bound result 8\n  Bound result 1\n  Bound result 6\n  Bound result 8\n  Bound result 2\n  Bound result 6\n  Bound result 8\n  Bound result 3\n  Bound result 6\n  Bound result 8\n  Bound result 4\n  Bound result 6\n  Bound result 8\n  Bound result 5\n  Bound result 6\n  Bound result 8\n  Bound result 6\n  Bound result 6\n  Bound result 8\n  Bound result 7\n  Bound result 6\n  Bound result 8\n  Bound result 0\n  Bound result 6\n  Bound result 8\n  Bound result 1\n  Bound result 6\n  Bound result 8\n  Bound result 2\n  Bound result 6\n  Bound result 8\n  Bound result 3\n  Bound result 6\n  Bound result 8\n  Bound result 4\n  Bound result 6\n  Bound result 8\n  Bound result 5\n  Bound result 6\n  Bound result 8\n  Bound result 0\n  Bound result 7\n  Bound result 8\n  Bound result 1\n  Bound result 7\n  Bound result 8\n  Bound result 2\n  Bound result 7\n  Bound result 8\n  Bound result 3\n  Bound result 7\n  Bound result 8\n  Bound result 4\n  Bound result 7\n  Bound result 8\n  Bound result 5\n  Bound result 7\n  Bound result 8\n  Bound result 6\n  Bound result 7\n  Bound result 8\n  Bound result 7\n  Bound result 7\n  Bound result 8\n  Bound result 0\n  Bound result 7\n  Bound result 8\n  Bound result 1\n  Bound result 7\n  Bound result 8\n  Bound result 2\n  Bound result 7\n  Bound result 8\n  Bound result 3\n  Bound result 7\n  Bound result 8\n  Bound result 4\n  Bound result 7\n  Bound result 8\n  Bound result 5\n  Bound result 7\n  Bound result 8\n  Bound result 0\n  Bound result 4\n  Bound result 1\n  Bound result 4\n  Bound result 2\n  Bound result 4\n  Bound result 3\n  Bound result 4\n  Bound result 4\n  Bound result 4\n  Bound result 5\n  Bound result 4\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 4\n  Bound result 2\n  Bound result 1\n  Bound result 4\n  Bound result 3\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 12.08s (12.17s CPU time)\n\nRan 1 test for test/OchreInvariant.t.sol:OchreReleasedInvariantTest\n[PASS] invariant_releasedSeatsStayDisjointAndPaymentsConserved() (runs: 128, calls: 16384, reverts: 0)\n\n╭----------------------+---------------+-------+---------+----------╮\n| Contract             | Selector      | Calls | Reverts | Discards |\n+===================================================================+\n| OchreSequenceHandler | advanceTime   | 2019  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| OchreSequenceHandler | buyBatch      | 1998  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| OchreSequenceHandler | claim         | 1970  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| OchreSequenceHandler | freeze        | 2057  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| OchreSequenceHandler | release       | 2068  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| OchreSequenceHandler | reserve       | 2076  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| OchreSequenceHandler | shortPayment  | 2116  | 0       | 0        |\n|----------------------+---------------+-------+---------+----------|\n| OchreSequenceHandler | transferPiece | 2080  | 0       | 0        |\n╰----------------------+---------------+-------+---------+----------╯\n\nLogs:\n  Bound result 0\n  Bound result 1\n  Bound result 2\n  Bound result 7\n  Bound result 0\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 1\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 1\n  Bound result 5\n  Bound result 1\n  Bound result 1\n  Bound result 6\n  Bound result 1\n  Bound result 1\n  Bound result 7\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 1\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 1\n  Bound result 5\n  Bound result 1\n  Bound result 1\n  Bound result 6\n  Bound result 1\n  Bound result 1\n  Bound result 7\n  Bound result 1\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 1\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 1\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 2\n  Bound result 2\n  Bound result 1\n  Bound result 3\n  Bound result 2\n  Bound result 1\n  Bound result 4\n  Bound result 2\n  Bound result 1\n  Bound result 5\n  Bound result 2\n  Bound result 1\n  Bound result 6\n  Bound result 2\n  Bound result 1\n  Bound result 7\n  Bound result 2\n  Bound result 1\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 2\n  Bound result 2\n  Bound result 1\n  Bound result 3\n  Bound result 2\n  Bound result 1\n  Bound result 4\n  Bound result 2\n  Bound result 1\n  Bound result 5\n  Bound result 2\n  Bound result 1\n  Bound result 6\n  Bound result 2\n  Bound result 1\n  Bound result 7\n  Bound result 2\n  Bound result 1\n  Bound result 0\n  Bound result 2\n  Bound result 1\n  Bound result 1\n  Bound result 2\n  Bound result 1\n  Bound result 2\n  Bound result 2\n  Bound result 1\n  Bound result 3\n  Bound result 2\n  Bound result 1\n  Bound result 4\n  Bound result 2\n  Bound result 1\n  Bound result 0\n  Bound result 3\n  Bound result 1\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 2\n  Bound result 3\n  Bound result 1\n  Bound result 3\n  Bound result 3\n  Bound result 1\n  Bound result 4\n  Bound result 3\n  Bound result 1\n  Bound result 5\n  Bound result 3\n  Bound result 1\n  Bound result 6\n  Bound result 3\n  Bound result 1\n  Bound result 7\n  Bound result 3\n  Bound result 1\n  Bound result 0\n  Bound result 3\n  Bound result 1\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 2\n  Bound result 3\n  Bound result 1\n  Bound result 3\n  Bound result 3\n  Bound result 1\n  Bound result 4\n  Bound result 3\n  Bound result 1\n  Bound result 5\n  Bound result 3\n  Bound result 1\n  Bound result 6\n  Bound result 3\n  Bound result 1\n  Bound result 7\n  Bound result 3\n  Bound result 1\n  Bound result 0\n  Bound result 3\n  Bound result 1\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 2\n  Bound result 3\n  Bound result 1\n  Bound result 3\n  Bound result 3\n  Bound result 1\n  Bound result 4\n  Bound result 3\n  Bound result 1\n  Bound result 5\n  Bound result 3\n  Bound result 1\n  Bound result 6\n  Bound result 3\n  Bound result 1\n  Bound result 7\n  Bound result 3\n  Bound result 1\n  Bound result 0\n  Bound result 3\n  Bound result 1\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 2\n  Bound result 3\n  Bound result 1\n  Bound result 3\n  Bound result 3\n  Bound result 1\n  Bound result 4\n  Bound result 3\n  Bound result 1\n  Bound result 5\n  Bound result 3\n  Bound result 1\n  Bound result 6\n  Bound result 3\n  Bound result 1\n  Bound result 7\n  Bound result 3\n  Bound result 1\n  Bound result 0\n  Bound result 3\n  Bound result 1\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 2\n  Bound result 3\n  Bound result 1\n  Bound result 3\n  Bound result 3\n  Bound result 1\n  Bound result 4\n  Bound result 3\n  Bound result 1\n  Bound result 5\n  Bound result 3\n  Bound result 1\n  Bound result 6\n  Bound result 3\n  Bound result 1\n  Bound result 7\n  Bound result 3\n  Bound result 1\n  Bound result 0\n  Bound result 3\n  Bound result 1\n  Bound result 1\n  Bound result 3\n  Bound result 1\n  Bound result 0\n  Bound result 4\n  Bound result 1\n  Bound result 1\n  Bound result 4\n  Bound result 1\n  Bound result 2\n  Bound result 4\n  Bound result 1\n  Bound result 3\n  Bound result 4\n  Bound result 1\n  Bound result 4\n  Bound result 4\n  Bound result 1\n  Bound result 5\n  Bound result 4\n  Bound result 1\n  Bound result 6\n  Bound result 4\n  Bound result 1\n  Bound result 7\n  Bound result 4\n  Bound result 1\n  Bound result 0\n  Bound result 4\n  Bound result 1\n  Bound result 1\n  Bound result 4\n  Bound result 1\n  Bound result 2\n  Bound result 4\n  Bound result 1\n  Bound result 3\n  Bound result 4\n  Bound result 1\n  Bound result 4\n  Bound result 4\n  Bound result 1\n  Bound result 5\n  Bound result 4\n  Bound result 1\n  Bound result 6\n  Bound result 4\n  Bound result 1\n  Bound result 7\n  Bound result 4\n  Bound result 1\n  Bound result 0\n  Bound result 4\n  Bound result 1\n  Bound result 1\n  Bound result 4\n  Bound result 1\n  Bound result 2\n  Bound result 4\n  Bound result 1\n  Bound result 3\n  Bound result 4\n  Bound result 1\n  Bound result 4\n  Bound result 4\n  Bound result 1\n  Bound result 5\n  Bound result 4\n  Bound result 1\n  Bound result 6\n  Bound result 4\n  Bound result 1\n  Bound result 7\n  Bound result 4\n  Bound result 1\n  Bound result 0\n  Bound result 4\n  Bound result 1\n  Bound result 1\n  Bound result 4\n  Bound result 1\n  Bound result 2\n  Bound result 4\n  Bound result 1\n  Bound result 3\n  Bound result 4\n  Bound result 1\n  Bound result 4\n  Bound result 4\n  Bound result 1\n  Bound result 5\n  Bound result 4\n  Bound result 1\n  Bound result 6\n  Bound result 4\n  Bound result 1\n  Bound result 7\n  Bound result 4\n  Bound result 1\n  Bound result 0\n  Bound result 4\n  Bound result 1\n  Bound result 1\n  Bound result 4\n  Bound result 1\n  Bound result 2\n  Bound result 4\n  Bound result 1\n  Bound result 3\n  Bound result 4\n  Bound result 1\n  Bound result 4\n  Bound result 4\n  Bound result 1\n  Bound result 5\n  Bound result 4\n  Bound result 1\n  Bound result 6\n  Bound result 4\n  Bound result 1\n  Bound result 7\n  Bound result 4\n  Bound result 1\n  Bound result 0\n  Bound result 4\n  Bound result 1\n  Bound result 1\n  Bound result 4\n  Bound result 1\n  Bound result 2\n  Bound result 4\n  Bound result 1\n  Bound result 3\n  Bound result 4\n  Bound result 1\n  Bound result 4\n  Bound result 4\n  Bound result 1\n  Bound result 5\n  Bound result 4\n  Bound result 1\n  Bound result 6\n  Bound result 4\n  Bound result 1\n  Bound result 7\n  Bound result 4\n  Bound result 1\n  Bound result 0\n  Bound result 4\n  Bound result 1\n  Bound result 1\n  Bound result 4\n  Bound result 1\n  Bound result 2\n  Bound result 4\n  Bound result 1\n  Bound result 3\n  Bound result 4\n  Bound result 1\n  Bound result 4\n  Bound result 4\n  Bound result 1\n  Bound result 5\n  Bound result 4\n  Bound result 1\n  Bound result 6\n  Bound result 4\n  Bound result 1\n  Bound result 7\n  Bound result 4\n  Bound result 1\n  Bound result 0\n  Bound result 4\n  Bound result 1\n  Bound result 1\n  Bound result 4\n  Bound result 1\n  Bound result 2\n  Bound result 4\n  Bound result 1\n  Bound result 3\n  Bound result 4\n  Bound result 1\n  Bound result 4\n  Bound result 4\n  Bound result 1\n  Bound result 5\n  Bound result 4\n  Bound result 1\n  Bound result 6\n  Bound result 4\n  Bound result 1\n  Bound result 0\n  Bound result 5\n  Bound result 1\n  Bound result 1\n  Bound result 5\n  Bound result 1\n  Bound result 2\n  Bound result 5\n  Bound result 1\n  Bound result 3\n  Bound result 5\n  Bound result 1\n  Bound result 4\n  Bound result 5\n  Bound result 1\n  Bound result 5\n  Bound result 5\n  Bound result 1\n  Bound result 6\n  Bound result 5\n  Bound result 1\n  Bound result 7\n  Bound result 5\n  Bound result 1\n  Bound result 0\n  Bound result 5\n  Bound result 1\n  Bound result 1\n  Bound result 5\n  Bound result 1\n  Bound result 2\n  Bound result 5\n  Bound result 1\n  Bound result 3\n  Bound result 5\n  Bound result 1\n  Bound result 4\n  Bound result 5\n  Bound result 1\n  Bound result 5\n  Bound result 5\n  Bound result 1\n  Bound result 6\n  Bound result 5\n  Bound result 1\n  Bound result 7\n  Bound result 5\n  Bound result 1\n  Bound result 0\n  Bound result 5\n  Bound result 1\n  Bound result 1\n  Bound result 5\n  Bound result 1\n  Bound result 2\n  Bound result 5\n  Bound result 1\n  Bound result 3\n  Bound result 5\n  Bound result 1\n  Bound result 4\n  Bound result 5\n  Bound result 1\n  Bound result 5\n  Bound result 5\n  Bound result 1\n  Bound result 6\n  Bound result 5\n  Bound result 1\n  Bound result 7\n  Bound result 5\n  Bound result 1\n  Bound result 0\n  Bound result 5\n  Bound result 1\n  Bound result 1\n  Bound result 5\n  Bound result 1\n  Bound result 2\n  Bound result 5\n  Bound result 1\n  Bound result 3\n  Bound result 5\n  Bound result 1\n  Bound result 4\n  Bound result 5\n  Bound result 1\n  Bound result 5\n  Bound result 5\n  Bound result 1\n  Bound result 6\n  Bound result 5\n  Bound result 1\n  Bound result 7\n  Bound result 5\n  Bound result 1\n  Bound result 0\n  Bound result 5\n  Bound result 1\n  Bound result 1\n  Bound result 5\n  Bound result 1\n  Bound result 2\n  Bound result 5\n  Bound result 1\n  Bound result 3\n  Bound result 5\n  Bound result 1\n  Bound result 4\n  Bound result 5\n  Bound result 1\n  Bound result 5\n  Bound result 5\n  Bound result 1\n  Bound result 6\n  Bound result 5\n  Bound result 1\n  Bound result 7\n  Bound result 5\n  Bound result 1\n  Bound result 0\n  Bound result 5\n  Bound result 1\n  Bound result 1\n  Bound result 5\n  Bound result 1\n  Bound result 2\n  Bound result 5\n  Bound result 1\n  Bound result 3\n  Bound result 5\n  Bound result 1\n  Bound result 4\n  Bound result 5\n  Bound result 1\n  Bound result 5\n  Bound result 5\n  Bound result 1\n  Bound result 6\n  Bound result 5\n  Bound result 1\n  Bound result 7\n  Bound result 5\n  Bound result 1\n  Bound result 0\n  Bound result 5\n  Bound result 1\n  Bound result 1\n  Bound result 5\n  Bound result 1\n  Bound result 2\n  Bound result 5\n  Bound result 1\n  Bound result 3\n  Bound result 5\n  Bound result 1\n  Bound result 4\n  Bound result 5\n  Bound result 1\n  Bound result 5\n  Bound result 5\n  Bound result 1\n  Bound result 6\n  Bound result 5\n  Bound result 1\n  Bound result 7\n  Bound result 5\n  Bound result 1\n  Bound result 0\n  Bound result 5\n  Bound result 1\n  Bound result 1\n  Bound result 5\n  Bound result 1\n  Bound result 2\n  Bound result 5\n  Bound result 1\n  Bound result 3\n  Bound result 5\n  Bound result 1\n  Bound result 4\n  Bound result 5\n  Bound result 1\n  Bound result 5\n  Bound result 5\n  Bound result 1\n  Bound result 6\n  Bound result 5\n  Bound result 1\n  Bound result 7\n  Bound result 5\n  Bound result 1\n  Bound result 0\n  Bound result 5\n  Bound result 1\n  Bound result 1\n  Bound result 5\n  Bound result 1\n  Bound result 2\n  Bound result 5\n  Bound result 1\n  Bound result 3\n  Bound result 5\n  Bound result 1\n  Bound result 4\n  Bound result 5\n  Bound result 1\n  Bound result 5\n  Bound result 5\n  Bound result 1\n  Bound result 6\n  Bound result 5\n  Bound result 1\n  Bound result 7\n  Bound result 5\n  Bound result 1\n  Bound result 0\n  Bound result 5\n  Bound result 1\n  Bound result 1\n  Bound result 5\n  Bound result 1\n  Bound result 2\n  Bound result 5\n  Bound result 1\n  Bound result 3\n  Bound result 5\n  Bound result 1\n  Bound result 4\n  Bound result 5\n  Bound result 1\n  Bound result 5\n  Bound result 5\n  Bound result 1\n  Bound result 6\n  Bound result 5\n  Bound result 1\n  Bound result 7\n  Bound result 5\n  Bound result 1\n  Bound result 0\n  Bound result 5\n  Bound result 1\n  Bound result 1\n  Bound result 5\n  Bound result 1\n  Bound result 2\n  Bound result 5\n  Bound result 1\n  Bound result 3\n  Bound result 5\n  Bound result 1\n  Bound result 0\n  Bound result 6\n  Bound result 1\n  Bound result 1\n  Bound result 6\n  Bound result 1\n  Bound result 2\n  Bound result 6\n  Bound result 1\n  Bound result 3\n  Bound result 6\n  Bound result 1\n  Bound result 4\n  Bound result 6\n  Bound result 1\n  Bound result 5\n  Bound result 6\n  Bound result 1\n  Bound result 6\n  Bound result 6\n  Bound result 1\n  Bound result 7\n  Bound result 6\n  Bound result 1\n  Bound result 0\n  Bound result 6\n  Bound result 1\n  Bound result 1\n  Bound result 6\n  Bound result 1\n  Bound result 2\n  Bound result 6\n  Bound result 1\n  Bound result 3\n  Bound result 6\n  Bound result 1\n  Bound result 4\n  Bound result 6\n  Bound result 1\n  Bound result 5\n  Bound result 6\n  Bound result 1\n  Bound result 6\n  Bound result 6\n  Bound result 1\n  Bound result 7\n  Bound result 6\n  Bound result 1\n  Bound result 0\n  Bound result 6\n  Bound result 1\n  Bound result 1\n  Bound result 6\n  Bound result 1\n  Bound result 2\n  Bound result 6\n  Bound result 1\n  Bound result 3\n  Bound result 6\n  Bound result 1\n  Bound result 4\n  Bound result 6\n  Bound result 1\n  Bound result 5\n  Bound result 6\n  Bound result 1\n  Bound result 6\n  Bound result 6\n  Bound result 1\n  Bound result 7\n  Bound result 6\n  Bound result 1\n  Bound result 0\n  Bound result 6\n  Bound result 1\n  Bound result 1\n  Bound result 6\n  Bound result 1\n  Bound result 2\n  Bound result 6\n  Bound result 1\n  Bound result 3\n  Bound result 6\n  Bound result 1\n  Bound result 4\n  Bound result 6\n  Bound result 1\n  Bound result 5\n  Bound result 6\n  Bound result 1\n  Bound result 6\n  Bound result 6\n  Bound result 1\n  Bound result 7\n  Bound result 6\n  Bound result 1\n  Bound result 0\n  Bound result 6\n  Bound result 1\n  Bound result 1\n  Bound result 6\n  Bound result 1\n  Bound result 2\n  Bound result 6\n  Bound result 1\n  Bound result 3\n  Bound result 6\n  Bound result 1\n  Bound result 4\n  Bound result 6\n  Bound result 1\n  Bound result 5\n  Bound result 6\n  Bound result 1\n  Bound result 6\n  Bound result 6\n  Bound result 1\n  Bound result 7\n  Bound result 6\n  Bound result 1\n  Bound result 0\n  Bound result 6\n  Bound result 1\n  Bound result 1\n  Bound result 6\n  Bound result 1\n  Bound result 2\n  Bound result 6\n  Bound result 1\n  Bound result 3\n  Bound result 6\n  Bound result 1\n  Bound result 4\n  Bound result 6\n  Bound result 1\n  Bound result 5\n  Bound result 6\n  Bound result 1\n  Bound result 6\n  Bound result 6\n  Bound result 1\n  Bound result 7\n  Bound result 6\n  Bound result 1\n  Bound result 0\n  Bound result 6\n  Bound result 1\n  Bound result 1\n  Bound result 6\n  Bound result 1\n  Bound result 2\n  Bound result 6\n  Bound result 1\n  Bound result 3\n  Bound result 6\n  Bound result 1\n  Bound result 4\n  Bound result 6\n  Bound result 1\n  Bound result 5\n  Bound result 6\n  Bound result 1\n  Bound result 6\n  Bound result 6\n  Bound result 1\n  Bound result 7\n  Bound result 6\n  Bound result 1\n  Bound result 0\n  Bound result 6\n  Bound result 1\n  Bound result 1\n  Bound result 6\n  Bound result 1\n  Bound result 2\n  Bound result 6\n  Bound result 1\n  Bound result 3\n  Bound result 6\n  Bound result 1\n  Bound result 4\n  Bound result 6\n  Bound result 1\n  Bound result 5\n  Bound result 6\n  Bound result 1\n  Bound result 6\n  Bound result 6\n  Bound result 1\n  Bound result 7\n  Bound result 6\n  Bound result 1\n  Bound result 0\n  Bound result 6\n  Bound result 1\n  Bound result 1\n  Bound result 6\n  Bound result 1\n  Bound result 2\n  Bound result 6\n  Bound result 1\n  Bound result 3\n  Bound result 6\n  Bound result 1\n  Bound result 4\n  Bound result 6\n  Bound result 1\n  Bound result 5\n  Bound result 6\n  Bound result 1\n  Bound result 6\n  Bound result 6\n  Bound result 1\n  Bound result 7\n  Bound result 6\n  Bound result 1\n  Bound result 0\n  Bound result 6\n  Bound result 1\n  Bound result 1\n  Bound result 6\n  Bound result 1\n  Bound result 2\n  Bound result 6\n  Bound result 1\n  Bound result 3\n  Bound result 6\n  Bound result 1\n  Bound result 4\n  Bound result 6\n  Bound result 1\n  Bound result 5\n  Bound result 6\n  Bound result 1\n  Bound result 6\n  Bound result 6\n  Bound result 1\n  Bound result 7\n  Bound result 6\n  Bound result 1\n  Bound result 0\n  Bound result 6\n  Bound result 1\n  Bound result 1\n  Bound result 6\n  Bound result 1\n  Bound result 2\n  Bound result 6\n  Bound result 1\n  Bound result 3\n  Bound result 6\n  Bound result 1\n  Bound result 0\n  Bound result 7\n  Bound result 1\n  Bound result 1\n  Bound result 7\n  Bound result 1\n  Bound result 2\n  Bound result 7\n  Bound result 1\n  Bound result 3\n  Bound result 7\n  Bound result 1\n  Bound result 4\n  Bound result 7\n  Bound result 1\n  Bound result 5\n  Bound result 7\n  Bound result 1\n  Bound result 6\n  Bound result 7\n  Bound result 1\n  Bound result 7\n  Bound result 7\n  Bound result 1\n  Bound result 0\n  Bound result 7\n  Bound result 1\n  Bound result 1\n  Bound result 7\n  Bound result 1\n  Bound result 2\n  Bound result 7\n  Bound result 1\n  Bound result 3\n  Bound result 7\n  Bound result 1\n  Bound result 4\n  Bound result 7\n  Bound result 1\n  Bound result 5\n  Bound result 7\n  Bound result 1\n  Bound result 6\n  Bound result 7\n  Bound result 1\n  Bound result 7\n  Bound result 7\n  Bound result 1\n  Bound result 0\n  Bound result 7\n  Bound result 1\n  Bound result 1\n  Bound result 7\n  Bound result 1\n  Bound result 2\n  Bound result 7\n  Bound result 1\n  Bound result 3\n  Bound result 7\n  Bound result 1\n  Bound result 4\n  Bound result 7\n  Bound result 1\n  Bound result 5\n  Bound result 7\n  Bound result 1\n  Bound result 6\n  Bound result 7\n  Bound result 1\n  Bound result 7\n  Bound result 7\n  Bound result 1\n  Bound result 0\n  Bound result 7\n  Bound result 1\n  Bound result 1\n  Bound result 7\n  Bound result 1\n  Bound result 2\n  Bound result 7\n  Bound result 1\n  Bound result 3\n  Bound result 7\n  Bound result 1\n  Bound result 4\n  Bound result 7\n  Bound result 1\n  Bound result 5\n  Bound result 7\n  Bound result 1\n  Bound result 6\n  Bound result 7\n  Bound result 1\n  Bound result 7\n  Bound result 7\n  Bound result 1\n  Bound result 0\n  Bound result 7\n  Bound result 1\n  Bound result 1\n  Bound result 7\n  Bound result 1\n  Bound result 2\n  Bound result 7\n  Bound result 1\n  Bound result 3\n  Bound result 7\n  Bound result 1\n  Bound result 4\n  Bound result 7\n  Bound result 1\n  Bound result 5\n  Bound result 7\n  Bound result 1\n  Bound result 6\n  Bound result 7\n  Bound result 1\n  Bound result 7\n  Bound result 7\n  Bound result 1\n  Bound result 0\n  Bound result 7\n  Bound result 1\n  Bound result 1\n  Bound result 7\n  Bound result 1\n  Bound result 2\n  Bound result 7\n  Bound result 1\n  Bound result 3\n  Bound result 7\n  Bound result 1\n  Bound result 4\n  Bound result 7\n  Bound result 1\n  Bound result 5\n  Bound result 7\n  Bound result 1\n  Bound result 6\n  Bound result 7\n  Bound result 1\n  Bound result 7\n  Bound result 7\n  Bound result 1\n  Bound result 0\n  Bound result 7\n  Bound result 1\n  Bound result 1\n  Bound result 7\n  Bound result 1\n  Bound result 2\n  Bound result 7\n  Bound result 1\n  Bound result 3\n  Bound result 7\n  Bound result 1\n  Bound result 4\n  Bound result 7\n  Bound result 1\n  Bound result 5\n  Bound result 7\n  Bound result 1\n  Bound result 6\n  Bound result 7\n  Bound result 1\n  Bound result 7\n  Bound result 7\n  Bound result 1\n  Bound result 0\n  Bound result 7\n  Bound result 1\n  Bound result 1\n  Bound result 7\n  Bound result 1\n  Bound result 2\n  Bound result 7\n  Bound result 1\n  Bound result 3\n  Bound result 7\n  Bound result 1\n  Bound result 4\n  Bound result 7\n  Bound result 1\n  Bound result 5\n  Bound result 7\n  Bound result 1\n  Bound result 6\n  Bound result 7\n  Bound result 1\n  Bound result 7\n  Bound result 7\n  Bound result 1\n  Bound result 0\n  Bound result 7\n  Bound result 1\n  Bound result 1\n  Bound result 7\n  Bound result 1\n  Bound result 2\n  Bound result 7\n  Bound result 1\n  Bound result 3\n  Bound result 7\n  Bound result 1\n  Bound result 4\n  Bound result 7\n  Bound result 1\n  Bound result 5\n  Bound result 7\n  Bound result 1\n  Bound result 6\n  Bound result 7\n  Bound result 1\n  Bound result 7\n  Bound result 7\n  Bound result 1\n  Bound result 0\n  Bound result 7\n  Bound result 1\n  Bound result 1\n  Bound result 7\n  Bound result 1\n  Bound result 2\n  Bound result 7\n  Bound result 1\n  Bound result 3\n  Bound result 7\n  Bound result 1\n  Bound result 4\n  Bound result 7\n  Bound result 1\n  Bound result 5\n  Bound result 7\n  Bound result 1\n  Bound result 6\n  Bound result 7\n  Bound result 1\n  Bound result 7\n  Bound result 7\n  Bound result 1\n  Bound result 0\n  Bound result 7\n  Bound result 1\n  Bound result 1\n  Bound result 7\n  Bound result 1\n  Bound result 2\n  Bound result 7\n  Bound result 1\n  Bound result 3\n  Bound result 7\n  Bound result 1\n  Bound result 4\n  Bound result 7\n  Bound result 1\n  Bound result 0\n  Bound result 0\n  Bound result 2\n  Bound result 0\n  Bound result 48\n  Bound result 3\n  Bound result 2\n  Bound result 314\n  Bound result 0\n  Bound result 1\n  Bound result 307\n  Bound result 2\n  Bound result 0\n  Bound result 1\n  Bound result 4\n  Bound result 148\n  Bound result 0\n  Bound result 6\n  Bound result 0\n  Bound result 4\n  Bound result 5\n  Bound result 52797\n  Bound result 2\n  Bound result 3\n  Bound result 2\n  Bound result 5\n  Bound result 8\n  Bound result 143\n  Bound result 6\n  Bound result 2\n  Bound result 5\n  Bound result 382\n  Bound result 2\n  Bound result 1\n  Bound result 18046\n  Bound result 3\n  Bound result 2\n  Bound result 3\n  Bound result 4\n  Bound result 2\n  Bound result 2\n  Bound result 2\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 2\n  Bound result 6\n  Bound result 4\n  Bound result 0\n  Bound result 3\n  Bound result 2\n  Bound result 3\n  Bound result 6\n  Bound result 7\n  Bound result 4\n  Bound result 5\n  Bound result 2\n  Bound result 8\n  Bound result 7\n  Bound result 5\n  Bound result 3\n  Bound result 7\n  Bound result 1\n  Bound result 4\n  Bound result 3\n  Bound result 2\n  Bound result 0\n  Bound result 7\n  Bound result 6\n  Bound result 4\n  Bound result 0\n  Bound result 6\n  Bound result 0\n  Bound result 7\n  Bound result 1\n  Bound result 5\n  Bound result 86393\n  Bound result 1\n  Bound result 7\n  Bound result 5\n  Bound result 3\n  Bound result 2\n  Bound result 8\n  Bound result 0\n  Bound result 1\n  Bound result 8\n  Bound result 4\n  Bound result 4\n  Bound result 6\n  Bound result 7\n  Bound result 6\n  Bound result 1\n  Bound result 196\n  Bound result 2\n  Bound result 0\n  Bound result 6\n  Bound result 1\n  Bound result 0\n  Bound result 5\n  Bound result 2\n  Bound result 7\n  Bound result 6\n  Bound result 2\n  Bound result 1\n  Bound result 2\n  Bound result 4\n  Bound result 1\n  Bound result 3\n  Bound result 7\n  Bound result 5\n  Bound result 2\n  Bound result 0\n  Bound result 2\n  Bound result 6\n  Bound result 4\n  Bound result 214\n  Bound result 4\n  Bound result 0\n  Bound result 2\n  Bound result 3\n  Bound result 2\n  Bound result 6\n  Bound result 286\n  Bound result 6\n  Bound result 1\n  Bound result 95\n  Bound result 1\n  Bound result 2\n  Bound result 3\n  Bound result 5404\n  Bound result 6\n  Bound result 5\n  Bound result 7\n  Bound result 716\n  Bound result 4\n  Bound result 6\n  Bound result 1\n  Bound result 7\n  Bound result 412\n  Bound result 5\n  Bound result 3\n  Bound result 0\n  Bound result 4\n  Bound result 1\n  Bound result 3\n  Bound result 5\n  Bound result 22806\n  Bound result 14\n  Bound result 4\n  Bound result 3\n  Bound result 0\n  Bound result 7\n  Bound result 309\n  Bound result 1\n  Bound result 3\n  Bound result 511\n  Bound result 7\n  Bound result 4\n  Bound result 4\n  Bound result 7\n  Bound result 4\n  Bound result 7\n  Bound result 7\n  Bound result 6\n  Bound result 8\n  Bound result 4\n  Bound result 2\n  Bound result 2\n  Bound result 5\n  Bound result 6\n  Bound result 0\n  Bound result 220\n  Bound result 0\n  Bound result 2\n  Bound result 2\n  Bound result 390\n  Bound result 5\n  Bound result 0\n  Bound result 369\n  Bound result 5\n  Bound result 0\n  Bound result 1\n  Bound result 7\n  Bound result 7\n  Bound result 6\n  Bound result 3\n  Bound result 0\n  Bound result 7\n  Bound result 4\n  Bound result 135\n  Bound result 6\n  Bound result 1\n  Bound result 20086\n  Bound result 6\n  Bound result 3\n  Bound result 6\n  Bound result 2\n  Bound result 5\n  Bound result 90\n  Bound result 0\n  Bound result 2\n  Bound result 6\n  Bound result 7\n  Bound result 4\n  Bound result 4\n  Bound result 19965\n  Bound result 0\n  Bound result 10\n  Bound result 2\n  Bound result 0\n  Bound result 3\n  Bound result 6\n  Bound result 1\n  Bound result 1\n  Bound result 4\n  Bound result 1\n  Bound result 6\n  Bound result 483\n  Bound result 4\n  Bound result 0\n  Bound result 1\n  Bound result 0\n  Bound result 1\n  Bound result 6\n  Bound result 7\n  Bound result 7\n  Bound result 2\n  Bound result 7\n  Bound result 5\n  Bound result 2\n  Bound result 1\n  Bound result 16439\n  Bound result 4\n  Bound result 935\n  Bound result 233\n  Bound result 5\n  Bound result 2\n  Bound result 3\n  Bound result 4\n  Bound result 7\n\nSuite result: ok. 1 passed; 0 failed; 0 skipped; finished in 14.08s (13.90s CPU time)\n\nRan 8 test suites in 14.09s (52.16s CPU time): 59 tests passed, 0 failed, 0 skipped (59 total tests)\n","passed":true},{"durationMs":78,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"MockCoin.approve(address,uint256)\",\"MockCoin.mint(address,uint256)\",\"MockCoin.transfer(address,uint256)\",\"MockCoin.transferFrom(address,address,uint256)\",\"Ochre.approve(address,uint256)\",\"Ochre.buy(uint256)\",\"Ochre.claimSeat(bytes32[])\",\"Ochre.freeze(uint256,string)\",\"Ochre.mintReserve(address)\",\"Ochre.releaseUnclaimed()\",\"Ochre.safeTransferFrom(address,address,uint256)\",\"Ochre.safeTransferFrom(address,address,uint256,bytes)\",\"Ochre.setApprovalForAll(address,bool)\",\"Ochre.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":3,\"README.md\":122,\"SECURITY.md\":22,\"foundry.toml\":17,\"launch.json\":29,\"remappings.txt\":2,\"script/Deploy.s.sol\":32,\"src/MockCoin.sol\":15,\"src/Ochre.sol\":270,\"test/Adversarial.t.sol\":205,\"test/BoundaryProperties.t.sol\":230,\"test/Fixtures.sol\":120,\"test/MetadataAndERC721.t.sol\":153,\"test/MockCoinAndDeployment.t.sol\":147,\"test/MockCoinInvariant.t.sol\":186,\"test/Ochre.t.sol\":379,\"test/OchreInvariant.t.sol\":432,\"test/README.md\":66},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"10da5ddfdd507cb4e1ad101a765aa4ca2a70237d05af7acebfac934458bac2cd","verifiedTreeHash":"c41e4a24f3329faec860738198c9611ea590ca67","verifierVersion":"0.1.0+7471272e"},{"checks":[{"durationMs":3867,"exitCode":0,"name":"build","output":"Compiling 43 files with Solc 0.8.26\nSolc 0.8.26 finished in 3.49s\nCompiler run successful!\nwarning[unsafe-oz-erc721-mint]: `ERC721._mint` does not check that the recipient can receive the token; use `_safeMint`\n   ╭▸ src/Ochre.sol:91:9\n   │\n91 │         _mint(adam_, 0);\n   │         ━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-oz-erc721-mint\n\nwarning[unsafe-oz-erc721-mint]: `ERC721._mint` does not check that the recipient can receive the token; use `_safeMint`\n   ╭▸ src/Ochre.sol:92:9\n   │\n92 │         _mint(admin_, 736);\n   │         ━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-oz-erc721-mint\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Ochre.sol:252:34\n    │\n252 │         if (label == bytes32(0)) revert InvalidConfiguration();\n    │                                  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Ochre.sol:257:50\n    │\n257 │             else if (ended || uint8(char) > 127) revert InvalidConfiguration();\n    │                                                  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Ochre.sol:114:13\n    │\n114 │         if (block.timestamp <= opens) return START_PRICE;\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Ochre.sol:116:13\n    │\n116 │         if (elapsed >= PRICE_DURATION) return floorPrice;\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_owners` is updated\n    ╭▸ src/Ochre.sol:178:14\n    │\n178 │         if (!coin.transferFrom(msg.sender, dead, price)) revert PaymentFailed();\n    │              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Ochre.sol:156:13\n    │\n156 │         if (block.timestamp < caveOpen(cave)) revert NotOpen();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Ochre.sol:180:9\n    │\n180 │         emit Bought(id, msg.sender, price);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Ochre.sol:122:31\n    │\n122 │         if (id >= MAX_SUPPLY) revert InvalidPiece();\n    │                               ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Ochre.sol:248:36\n    │\n248 │         if (cave == 0 || cave > 7) revert InvalidCave();\n    │                                    ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Ochre.sol:137:39\n    │\n137 │         if (round == 0 || round > 21) revert InvalidPiece();\n    │                                       ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Ochre.sol:184:13\n    │\n184 │         if (block.timestamp < startTime) revert NotOpen();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Ochre.sol:197:9\n    │\n197 │         emit Claimed(id, msg.sender);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/Ochre.sol:201:57\n    │\n201 │     function mintReserve(address to) external onlyAdmin nonReentrant returns (uint256 id) {\n    │                                                         ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Ochre.sol:206:9\n    │\n206 │         emit ReserveMinted(id, to);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Ochre.sol:211:13\n    │\n211 │         if (block.timestamp < startTime + 8 days) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/Ochre.sol:222:55\n    │\n222 │         if (raw.length == 0 || raw[raw.length - 1] != bytes1(\"/\")) revert InvalidBase();\n    │                                                       ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'bytes1' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Ochre.sol:257:22\n    │\n257 │             else if (ended || uint8(char) > 127) revert InvalidConfiguration();\n    │                      ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Ochre.sol:263:16\n    │\n263 │         while (length < 32 && label[length] != 0) ++length;\n    │                ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\n","passed":true},{"durationMs":346,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 8 tests for test/Adversarial.t.sol:AdversarialTest\n[PASS] testClaimRejectionRollbackAndReentrancy() (gas: 1020760)\n[PASS] testCoinCannotReenterBuy() (gas: 1178686)\n[PASS] testFalseOrRevertingCoinRestoresSaleAndBalances() (gas: 1197418)\n[PASS] testMissingCoinReturnIsRejected() (gas: 220202)\n[PASS] testReceiverCannotReenterBuyOrRelease() (gas: 1141427)\n[PASS] testReceiverRejectRestoresPaymentAllowanceAndSale() (gas: 1081895)\n[PASS] testReleasedSeatPaymentFailureDoesNotSkipItsId() (gas: 3263938)\n[PASS] testReserveRecipientRejectsWithoutConsumingReserve() (gas: 808282)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 113.74ms (34.94ms CPU time)\n\nRan 7 tests for test/MockCoinAndDeployment.t.sol:MockCoinAndDeploymentTest\n[PASS] testConstructorAcceptsCoinWithNoCodeAndSkipsReceiverCallbacks() (gas: 119615)\n[PASS] testConstructorRejectsZeroAddressesAndTimestampOverflow() (gas: 4689)\n[PASS] testDeploymentHelperRejectsOtherChains() (gas: 3542867)\n[PASS] testExactSepoliaRehearsalDeployment() (gas: 13332196)\n[PASS] testLabelLengthsAndInvalidPadding() (gas: 50754)\n[PASS] testMockCoinInitialSupplyAndPermissionlessMint() (gas: 142562)\n[PASS] testMockCoinTransferAndAllowance() (gas: 207102)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 113.84ms (46.11ms CPU time)\n\nRan 21 tests for test/Ochre.t.sol:OchreTest\n[PASS] testAll737UniquePiecesAndNoFurtherMinting() (gas: 85091566)\n[PASS] testAllPieceArithmeticAndAllocationCounts() (gas: 22942789)\n[PASS] testBuyMissingAllowanceRollsBack() (gas: 393372)\n[PASS] testBuyMissingBalanceRollsBack() (gas: 345874)\n[PASS] testBuyPaymentAndEventNoWalletLimit() (gas: 375439)\n[PASS] testCannotSendEth() (gas: 65703)\n[PASS] testClaimOpeningProofReplayAndEvent() (gas: 386760)\n[PASS] testEveryCaveRejectsBeforeOpenAndAcceptsAtOpen() (gas: 1208140)\n[PASS] testExactSaleSequenceAndExhaustionAllCaves() (gas: 44147275)\n[PASS] testFuzzPriceLine(uint8,uint32) (runs: 256, μ: 12951, ~: 13137)\n[PASS] testInitialStateAndInterfaces() (gas: 141466)\n[PASS] testInvalidCaveAndPieceInputs() (gas: 117813)\n[PASS] testPriceBoundariesEveryCave() (gas: 579849)\n[PASS] testProofIsBoundToCallerAndSiblingOrdering() (gas: 840677)\n[PASS] testReleaseBoundaryEventAndRepeat() (gas: 155136)\n[PASS] testReleaseIsExplicitAndSkipsClaimedEvenAfterTransfer() (gas: 2651126)\n[PASS] testReleaseNeverSellsCaveSevenReserve() (gas: 9953387)\n[PASS] testReleasedSeatsFollowRemainingSales() (gas: 2796543)\n[PASS] testReserveAuthorizationEventCapAndNoOpeningRestriction() (gas: 1516315)\n[PASS] testReserveZeroRecipientRollsBack() (gas: 178731)\n[PASS] testSortedMerkleTreeAll315SeatsAndCap() (gas: 91363088)\nSuite result: ok. 21 passed; 0 failed; 0 skipped; finished in 113.87ms (283.63ms CPU time)\n\nRan 6 tests for test/MetadataAndERC721.t.sol:MetadataAndERC721Test\n[PASS] testAllURIsBeforeAndAfterIndependentCaveFreezes() (gas: 114006383)\n[PASS] testBadTransferRecipientsAndWrongOwnerRollback() (gas: 422685)\n[PASS] testEndpointAndSampleURIs() (gas: 666122)\n[PASS] testFreezeAuthorizationInputAndFutureTokens() (gas: 423514)\n[PASS] testTransfersApprovalsAndApprovalClearing() (gas: 596574)\n[PASS] testUnmintedMetadataAndOwnerQueriesRevert() (gas: 57735)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 177.14ms (169.04ms CPU time)\n\nRan 4 test suites in 181.01ms (518.60ms CPU time): 42 tests passed, 0 failed, 0 skipped (42 total tests)\n","passed":true},{"durationMs":103,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"MockCoin.approve(address,uint256)\",\"MockCoin.mint(address,uint256)\",\"MockCoin.transfer(address,uint256)\",\"MockCoin.transferFrom(address,address,uint256)\",\"Ochre.approve(address,uint256)\",\"Ochre.buy(uint256)\",\"Ochre.claimSeat(bytes32[])\",\"Ochre.freeze(uint256,string)\",\"Ochre.mintReserve(address)\",\"Ochre.releaseUnclaimed()\",\"Ochre.safeTransferFrom(address,address,uint256)\",\"Ochre.safeTransferFrom(address,address,uint256,bytes)\",\"Ochre.setApprovalForAll(address,bool)\",\"Ochre.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":3,\"README.md\":122,\"SECURITY.md\":22,\"foundry.toml\":17,\"launch.json\":29,\"remappings.txt\":2,\"script/Deploy.s.sol\":32,\"src/MockCoin.sol\":15,\"src/Ochre.sol\":270,\"test/Adversarial.t.sol\":205,\"test/Fixtures.sol\":120,\"test/MetadataAndERC721.t.sol\":153,\"test/MockCoinAndDeployment.t.sol\":147,\"test/Ochre.t.sol\":379},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"37d88024dfe4a61aa92a7a125ef71b18d5f0ffec70065d5e37009da07847361a","verifiedTreeHash":"17e4ddcf23713f614d64201d2ee21d88d5aae302","verifierVersion":"0.1.0+7471272e"},{"checks":[{"durationMs":2185,"exitCode":0,"name":"build","output":"Compiling 43 files with Solc 0.8.26\nSolc 0.8.26 finished in 2.02s\nCompiler run successful!\nwarning[unsafe-oz-erc721-mint]: `ERC721._mint` does not check that the recipient can receive the token; use `_safeMint`\n   ╭▸ src/Ochre.sol:91:9\n   │\n91 │         _mint(adam_, 0);\n   │         ━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-oz-erc721-mint\n\nwarning[unsafe-oz-erc721-mint]: `ERC721._mint` does not check that the recipient can receive the token; use `_safeMint`\n   ╭▸ src/Ochre.sol:92:9\n   │\n92 │         _mint(admin_, 736);\n   │         ━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-oz-erc721-mint\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Ochre.sol:252:34\n    │\n252 │         if (label == bytes32(0)) revert InvalidConfiguration();\n    │                                  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Ochre.sol:257:50\n    │\n257 │             else if (ended || uint8(char) > 127) revert InvalidConfiguration();\n    │                                                  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Ochre.sol:114:13\n    │\n114 │         if (block.timestamp <= opens) return START_PRICE;\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Ochre.sol:116:13\n    │\n116 │         if (elapsed >= PRICE_DURATION) return floorPrice;\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-no-eth]: external call can be reentered before `_owners` is updated\n    ╭▸ src/Ochre.sol:178:14\n    │\n178 │         if (!coin.transferFrom(msg.sender, dead, price)) revert PaymentFailed();\n    │              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-no-eth\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Ochre.sol:156:13\n    │\n156 │         if (block.timestamp < caveOpen(cave)) revert NotOpen();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Ochre.sol:180:9\n    │\n180 │         emit Bought(id, msg.sender, price);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Ochre.sol:122:31\n    │\n122 │         if (id >= MAX_SUPPLY) revert InvalidPiece();\n    │                               ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Ochre.sol:248:36\n    │\n248 │         if (cave == 0 || cave > 7) revert InvalidCave();\n    │                                    ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n    ╭▸ src/Ochre.sol:137:39\n    │\n137 │         if (round == 0 || round > 21) revert InvalidPiece();\n    │                                       ━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Ochre.sol:184:13\n    │\n184 │         if (block.timestamp < startTime) revert NotOpen();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Ochre.sol:197:9\n    │\n197 │         emit Claimed(id, msg.sender);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[non-reentrant-not-first]: `nonReentrant` is not the first modifier\n    ╭▸ src/Ochre.sol:201:57\n    │\n201 │     function mintReserve(address to) external onlyAdmin nonReentrant returns (uint256 id) {\n    │                                                         ━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/non-reentrant-not-first\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/Ochre.sol:206:9\n    │\n206 │         emit ReserveMinted(id, to);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[block-timestamp]: usage of `block.timestamp` in a comparison may be manipulated by validators\n    ╭▸ src/Ochre.sol:211:13\n    │\n211 │         if (block.timestamp < startTime + 8 days) revert TooEarly();\n    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/block-timestamp\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/Ochre.sol:222:55\n    │\n222 │         if (raw.length == 0 || raw[raw.length - 1] != bytes1(\"/\")) revert InvalidBase();\n    │                                                       ━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'bytes1' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Ochre.sol:257:22\n    │\n257 │             else if (ended || uint8(char) > 127) revert InvalidConfiguration();\n    │                      ━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\nwarning[uninitialized-local]: local variable is read before being initialized\n    ╭▸ src/Ochre.sol:263:16\n    │\n263 │         while (length < 32 && label[length] != 0) ++length;\n    │                ━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/uninitialized-local\n\n","passed":true},{"durationMs":193,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 8 tests for test/Adversarial.t.sol:AdversarialTest\n[PASS] testClaimRejectionRollbackAndReentrancy() (gas: 1020760)\n[PASS] testCoinCannotReenterBuy() (gas: 1178686)\n[PASS] testFalseOrRevertingCoinRestoresSaleAndBalances() (gas: 1197418)\n[PASS] testMissingCoinReturnIsRejected() (gas: 220202)\n[PASS] testReceiverCannotReenterBuyOrRelease() (gas: 1141427)\n[PASS] testReceiverRejectRestoresPaymentAllowanceAndSale() (gas: 1081895)\n[PASS] testReleasedSeatPaymentFailureDoesNotSkipItsId() (gas: 3263938)\n[PASS] testReserveRecipientRejectsWithoutConsumingReserve() (gas: 808282)\nSuite result: ok. 8 passed; 0 failed; 0 skipped; finished in 3.47ms (6.06ms CPU time)\n\nRan 7 tests for test/MockCoinAndDeployment.t.sol:MockCoinAndDeploymentTest\n[PASS] testConstructorAcceptsCoinWithNoCodeAndSkipsReceiverCallbacks() (gas: 119615)\n[PASS] testConstructorRejectsZeroAddressesAndTimestampOverflow() (gas: 4689)\n[PASS] testDeploymentHelperRejectsOtherChains() (gas: 3542867)\n[PASS] testExactSepoliaRehearsalDeployment() (gas: 13332196)\n[PASS] testLabelLengthsAndInvalidPadding() (gas: 50754)\n[PASS] testMockCoinInitialSupplyAndPermissionlessMint() (gas: 142562)\n[PASS] testMockCoinTransferAndAllowance() (gas: 207102)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 13.12ms (15.05ms CPU time)\n\nRan 21 tests for test/Ochre.t.sol:OchreTest\n[PASS] testAll737UniquePiecesAndNoFurtherMinting() (gas: 85091566)\n[PASS] testAllPieceArithmeticAndAllocationCounts() (gas: 22942789)\n[PASS] testBuyMissingAllowanceRollsBack() (gas: 393372)\n[PASS] testBuyMissingBalanceRollsBack() (gas: 345874)\n[PASS] testBuyPaymentAndEventNoWalletLimit() (gas: 375439)\n[PASS] testCannotSendEth() (gas: 65703)\n[PASS] testClaimOpeningProofReplayAndEvent() (gas: 386760)\n[PASS] testEveryCaveRejectsBeforeOpenAndAcceptsAtOpen() (gas: 1208140)\n[PASS] testExactSaleSequenceAndExhaustionAllCaves() (gas: 44147275)\n[PASS] testFuzzPriceLine(uint8,uint32) (runs: 256, μ: 12953, ~: 13137)\n[PASS] testInitialStateAndInterfaces() (gas: 141466)\n[PASS] testInvalidCaveAndPieceInputs() (gas: 117813)\n[PASS] testPriceBoundariesEveryCave() (gas: 579849)\n[PASS] testProofIsBoundToCallerAndSiblingOrdering() (gas: 840677)\n[PASS] testReleaseBoundaryEventAndRepeat() (gas: 155136)\n[PASS] testReleaseIsExplicitAndSkipsClaimedEvenAfterTransfer() (gas: 2651126)\n[PASS] testReleaseNeverSellsCaveSevenReserve() (gas: 9953387)\n[PASS] testReleasedSeatsFollowRemainingSales() (gas: 2796543)\n[PASS] testReserveAuthorizationEventCapAndNoOpeningRestriction() (gas: 1516315)\n[PASS] testReserveZeroRecipientRollsBack() (gas: 178731)\n[PASS] testSortedMerkleTreeAll315SeatsAndCap() (gas: 91363088)\nSuite result: ok. 21 passed; 0 failed; 0 skipped; finished in 80.06ms (212.30ms CPU time)\n\nRan 6 tests for test/MetadataAndERC721.t.sol:MetadataAndERC721Test\n[PASS] testAllURIsBeforeAndAfterIndependentCaveFreezes() (gas: 114006383)\n[PASS] testBadTransferRecipientsAndWrongOwnerRollback() (gas: 422685)\n[PASS] testEndpointAndSampleURIs() (gas: 666122)\n[PASS] testFreezeAuthorizationInputAndFutureTokens() (gas: 423514)\n[PASS] testTransfersApprovalsAndApprovalClearing() (gas: 596574)\n[PASS] testUnmintedMetadataAndOwnerQueriesRevert() (gas: 57735)\nSuite result: ok. 6 passed; 0 failed; 0 skipped; finished in 88.31ms (89.44ms CPU time)\n\nRan 4 test suites in 88.99ms (184.96ms CPU time): 42 tests passed, 0 failed, 0 skipped (42 total tests)\n","passed":true},{"durationMs":63,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"MockCoin.approve(address,uint256)\",\"MockCoin.mint(address,uint256)\",\"MockCoin.transfer(address,uint256)\",\"MockCoin.transferFrom(address,address,uint256)\",\"Ochre.approve(address,uint256)\",\"Ochre.buy(uint256)\",\"Ochre.claimSeat(bytes32[])\",\"Ochre.freeze(uint256,string)\",\"Ochre.mintReserve(address)\",\"Ochre.releaseUnclaimed()\",\"Ochre.safeTransferFrom(address,address,uint256)\",\"Ochre.safeTransferFrom(address,address,uint256,bytes)\",\"Ochre.setApprovalForAll(address,bool)\",\"Ochre.transferFrom(address,address,uint256)\"],\"files\":{\".gitignore\":3,\"README.md\":122,\"SECURITY.md\":22,\"foundry.toml\":17,\"launch.json\":29,\"remappings.txt\":2,\"script/Deploy.s.sol\":32,\"src/MockCoin.sol\":15,\"src/Ochre.sol\":270,\"test/Adversarial.t.sol\":205,\"test/Fixtures.sol\":120,\"test/MetadataAndERC721.t.sol\":153,\"test/MockCoinAndDeployment.t.sol\":147,\"test/Ochre.t.sol\":379},\"excluded\":[\"lib/\",\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":1607,"exitCode":0,"name":"slither","output":"[medium/medium] uninitialized-local at src/Ochre.sol:253: Ochre._validateLabel(bytes32).ended (src/Ochre.sol#253) is a local variable never initialized\n[low/medium] timestamp at src/Ochre.sol:210: Ochre.releaseUnclaimed() (src/Ochre.sol#210-215) uses timestamp for comparisons\n[low/medium] timestamp at src/Ochre.sol:155: Ochre.buy(uint256) (src/Ochre.sol#155-181) uses timestamp for comparisons\n[low/medium] timestamp at src/Ochre.sol:112: Ochre.priceNow(uint256) (src/Ochre.sol#112-118) uses timestamp for comparisons\n[low/medium] timestamp at src/Ochre.sol:183: Ochre.claimSeat(bytes32[]) (src/Ochre.sol#183-198) uses timestamp for comparisons","passed":true},{"durationMs":460,"exitCode":0,"name":"aderyn","output":"[low] large-numeric-literal at src/MockCoin.sol:9: Large Numeric Literal (3 places)\n[low] literal-instead-of-constant at src/Ochre.sol:79: Literal Instead of Constant (42 places)\n[low] non-reentrant-not-first at src/Ochre.sol:201: `nonReentrant` is Not the First Modifier\n[low] require-revert-in-loop at src/Ochre.sol:160: Loop Contains `require`/`revert` (3 places)\n[low] unchecked-return at src/Ochre.sol:229: Unchecked Return\n[low] uninitialized-local-variable at src/Ochre.sol:254: Uninitialized Local Variable (2 places)\n[low] unsafe-erc20-operation at src/Ochre.sol:178: Unsafe ERC20 Operation\n[low] unsafe-oz-erc721-mint at src/Ochre.sol:91: Unsafe `ERC721::_mint()` (2 places)\n[low] unused-public-function at src/Ochre.sol:106: Public Function Not Used Internally (3 places)","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"fccce36f8081670db506e506ac08b9dff5936e661ae699813eca9e7b03874ffa","verifiedTreeHash":"112630f6713b2ea8a2bba40a1602b2f35e3d16f6","verifierVersion":"0.1.0+7471272e"}]}