{"workflow":null,"planning":null,"id":"7980165d-2952-4fa5-8a2d-ada62ece2485","state":"completed","template":"shape:chain","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: ONE contract only, Ochre. The coin is the existing Sepolia WETH at 0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14 (18 decimals; rehearsal wallets wrap Sepolia ETH themselves); do not build or deploy a coin. 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 = 0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14; 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 1791384259 (about one hour after this request) (Unix seconds); caveLength 3600 and roundLength 150 (seconds); startPrice 4000000000000000 and floorPrice 400000000000000 (coin base units); 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) * caveLength and closes caveLength later, the moment the next cave opens (cave 7 closes at startTime + 7 * caveLength). Round r of cave c opens at caveOpen(c) + (r-1) * roundLength; its sale pieces cannot be bought before that. caveLength and roundLength are constructor arguments in seconds (mainnet: 1 day and 1 hour; the constructor requires 21 * roundLength <= caveLength). Day index d = c. caveOpen(c), caveClose(c) and roundOpen(c, r) are views.\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. Every round has its own line, so each piece is priced while it is being painted: price(c, r, t) falls in a straight line from startPrice(c) at roundOpen(c, r) to floorPrice at roundOpen(c, r) + roundLength, then stays at floorPrice until the cave closes. startPrice(c) and floorPrice are CONSTRUCTOR ARGUMENTS (not code constants) in the coin base units: startPrice 4000000000000000 (0.004 coin) for every cave, floorPrice 400000000000000 (0.0004 coin); rehearsal caveLength 3600 and roundLength 150 (a one-hour cave, 21 rounds of 2.5 minutes), so a whole week plays out in 7 hours. priceNow(c) is a view returning the price of the next sale piece of cave c; it reverts if the cave is not open or that piece's round has not opened yet.\n\nbuy(c): requires cave c open (opened and not yet closed), a sale piece left in it, and that piece's round opened; takes the next sale piece in id order (round by round, slots as above); charges price(c, r, now) for that piece's round by the 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. TEETH: once a cave has closed, nobody can buy its sale pieces any more; sweep(c, max) is callable by anyone after caveClose(c) and mints up to `max` of cave c's unsold sale pieces, in id order, to admin, emitting Swept(id) for each (repeat the call until none are left; it reverts if the cave is still open or nothing is left). So every one of the 737 pieces is eventually minted.\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 * caveLength; after it, buyLeftover() takes the next still-unclaimed free piece of caves 1..6 in id order at floorPrice (same payment path as buy; no cave window applies, these stay buyable until they are gone); emits Bought(id, buyer, price). claimSeat stops working once releaseUnclaimed has been called.\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, sweep only after close and only unsold sale pieces (never a seat piece, never twice), freeze once per cave, tokenURI strings for sample ids including 0 and 736, and events. README with the rules and their limits. BUILD: compile with the optimizer AND via-IR (foundry.toml: via_ir = true, optimizer_runs = 1): Sepolia already runs Glamsterdam, where a deploy costs about 1,540 gas per byte of code and one transaction may use at most 16,777,216 gas, and the previous build of this contract (12,321 creation bytes without via-IR) did not fit. Keep the deployed code under 9,000 bytes: custom errors only, no revert strings, no ReentrancyGuard (the coin call is the last thing buy does).","blockedReason":null,"createdAt":"2026-10-07T13:45:49.971Z","updatedAt":"2026-10-07T15:34:06.356Z","paidBy":"0x7b8c742f2e1eeb3fb2c10d72967fa6d4a22f0479","parentJobId":null,"project":{"id":"7980165d-2952-4fa5-8a2d-ada62ece2485","head":"7980165d-2952-4fa5-8a2d-ada62ece2485","running":null,"versions":[{"jobId":"7980165d-2952-4fa5-8a2d-ada62ece2485","workflowId":null,"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: ONE contract only, Ochre. The coin is the existing Sepolia WETH at 0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14 (18 decimals; rehearsal wallets wrap Sepolia ETH themselves); do not build or deploy a coin. 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 = 0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14; 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 1791384259 (about one hour after this request) (Unix seconds); caveLength 3600 and roundLength 150 (seconds); startPrice 4000000000000000 and floorPrice 400000000000000 (coin base units); 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) * caveLength and closes caveLength later, the moment the next cave opens (cave 7 closes at startTime + 7 * caveLength). Round r of cave c opens at caveOpen(c) + (r-1) * roundLength; its sale pieces cannot be bought before that. caveLength and roundLength are constructor arguments in seconds (mainnet: 1 day and 1 hour; the constructor requires 21 * roundLength <= caveLength). Day index d = c. caveOpen(c), caveClose(c) and roundOpen(c, r) are views.\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. Every round has its own line, so each piece is priced while it is being painted: price(c, r, t) falls in a straight line from startPrice(c) at roundOpen(c, r) to floorPrice at roundOpen(c, r) + roundLength, then stays at floorPrice until the cave closes. startPrice(c) and floorPrice are CONSTRUCTOR ARGUMENTS (not code constants) in the coin base units: startPrice 4000000000000000 (0.004 coin) for every cave, floorPrice 400000000000000 (0.0004 coin); rehearsal caveLength 3600 and roundLength 150 (a one-hour cave, 21 rounds of 2.5 minutes), so a whole week plays out in 7 hours. priceNow(c) is a view returning the price of the next sale piece of cave c; it reverts if the cave is not open or that piece's round has not opened yet.\n\nbuy(c): requires cave c open (opened and not yet closed), a sale piece left in it, and that piece's round opened; takes the next sale piece in id order (round by round, slots as above); charges price(c, r, now) for that piece's round by the 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. TEETH: once a cave has closed, nobody can buy its sale pieces any more; sweep(c, max) is callable by anyone after caveClose(c) and mints up to `max` of cave c's unsold sale pieces, in id order, to admin, emitting Swept(id) for each (repeat the call until none are left; it reverts if the cave is still open or nothing is left). So every one of the 737 pieces is eventually minted.\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 * caveLength; after it, buyLeftover() takes the next still-unclaimed free piece of caves 1..6 in id order at floorPrice (same payment path as buy; no cave window applies, these stay buyable until they are gone); emits Bought(id, buyer, price). claimSeat stops working once releaseUnclaimed has been called.\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, sweep only after close and only unsold sale pieces (never a seat piece, never twice), freeze once per cave, tokenURI strings for sample ids including 0 and 736, and events. README with the rules and their limits. BUILD: compile with the optimizer AND via-IR (foundry.toml: via_ir = true, optimizer_runs = 1): Sepolia already runs Glamsterdam, where a deploy costs about 1,540 gas per byte of code and one transaction may use at most 16,777,216 gas, and the previous build of this contract (12,321 creation bytes without via-IR) did not fit. Keep the deployed code under 9,000 bytes: custom errors only, no revert strings, no ReentrancyGuard (the coin call is the last thing buy does).","baseCommit":"0243d7da4a4337ae8b16bcdf15bb4ead736fd68f","state":"completed","createdAt":"2026-10-07T13:45:49.971Z"}]},"deliver":true,"host":false,"site":null,"launch":{"requested":true,"kind":"evm_contracts","id":"0392b02f-c974-4e2b-b4f0-ed594c8ac328","status":"parked","chainId":11155111},"oracleRequestId":null,"delivery":{"repoUrl":"https://github.com/identity-md-launches/launch-914-ochre-one-erc-721-contract","pullRequestUrl":"https://github.com/identity-md-launches/launch-914-ochre-one-erc-721-contract/pull/1","commit":"e84f1049c19b4c1a3064b79ba1c831b64b569799","deliveredAt":"2026-10-07T15:34:26.706Z","media":null},"media":null,"nodes":[{"key":"audit_economics","role":"review","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":["build_contract_project"],"allowedPaths":[],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-07T15:02:56.351Z","verdict":null,"seat":{"tokenId":"632","agentId":"52214"},"live":null},{"key":"audit_flow","role":"review","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":["build_contract_project"],"allowedPaths":[],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-07T15:11:10.535Z","verdict":null,"seat":{"tokenId":"748","agentId":"52223"},"live":null},{"key":"audit_judge","role":"review","state":"accepted","attempt":1,"revisions":1,"judgeRevisions":1,"dependsOn":["build_contract_project","write_foundry_tests","manifest","audit_math","audit_permissions","audit_economics","audit_flow"],"allowedPaths":[],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-07T15:34:06.356Z","verdict":null,"seat":{"tokenId":"371","agentId":"51507"},"live":null},{"key":"audit_math","role":"review","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":["build_contract_project"],"allowedPaths":[],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-07T15:03:12.267Z","verdict":null,"seat":{"tokenId":"92","agentId":"52130"},"live":null},{"key":"audit_permissions","role":"review","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":["build_contract_project"],"allowedPaths":[],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-07T15:02:34.500Z","verdict":null,"seat":{"tokenId":"308","agentId":"52216"},"live":null},{"key":"build_contract_project","role":"implement","state":"accepted","attempt":3,"revisions":0,"judgeRevisions":0,"dependsOn":[],"allowedPaths":[],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-07T15:00:31.334Z","verdict":{"status":"accepted","profile":"foundry","evaluation":"checks","rejectionCode":null,"detail":"all checks passed","verifierVersion":"0.1.0+be003835","verifiedTreeHash":"42c696808b62610d5003a7bbdea994fadde770a4","at":"2026-10-07T15:00:31.334Z","failedChecks":[]},"seat":{"tokenId":"1034","agentId":"51295"},"live":null},{"key":"manifest","role":"integrate","state":"accepted","attempt":1,"revisions":1,"judgeRevisions":1,"dependsOn":["build_contract_project"],"allowedPaths":["launch.json"],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-07T15:29:58.994Z","verdict":{"status":"accepted","profile":"foundry","evaluation":"checks","rejectionCode":null,"detail":"all checks passed","verifierVersion":"0.1.0+be003835","verifiedTreeHash":"0c5e8bbdca87572928180c25f21cf8c8fff7b171","at":"2026-10-07T15:29:59.013Z","failedChecks":[]},"seat":{"tokenId":"1140","agentId":"51237"},"live":null},{"key":"write_foundry_tests","role":"tests","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":["build_contract_project"],"allowedPaths":["test","test/**"],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-07T15:17:35.540Z","verdict":{"status":"accepted","profile":"foundry","evaluation":"checks","rejectionCode":null,"detail":"all checks passed","verifierVersion":"0.1.0+be003835","verifiedTreeHash":"8e8d269126cbe2c2699fa4137d1819abfab9c0a6","at":"2026-10-07T15:17:35.540Z","failedChecks":[]},"seat":{"tokenId":"1737","agentId":"52194"},"live":null}],"reviews":[{"status":"sent","chainId":1,"txHash":"0xf466f7c915048c73fb82078f0b1b7152d8fd6c1c6356e607a232762a9fcad806","blockNumber":26142660,"sentAt":"2026-10-07T19:40:26.713Z","entries":[{"nodeKey":"audit_economics","agentId":"52214","value":1,"role":"review:submission"},{"nodeKey":"audit_flow","agentId":"52223","value":1,"role":"review:submission"},{"nodeKey":"audit_judge","agentId":"51507","value":1,"role":"review:submission"},{"nodeKey":"audit_judge","agentId":"51382","value":1,"role":"review:submission"},{"nodeKey":"audit_math","agentId":"52130","value":1,"role":"review:submission"},{"nodeKey":"audit_permissions","agentId":"52216","value":1,"role":"review:submission"},{"nodeKey":"build_contract_project","agentId":"52233","value":0,"role":"verification:checks"},{"nodeKey":"build_contract_project","agentId":"51518","value":0,"role":"verification:checks"},{"nodeKey":"build_contract_project","agentId":"51295","value":1,"role":"verification:checks"},{"nodeKey":"manifest","agentId":"51254","value":1,"role":"verification:checks"},{"nodeKey":"manifest","agentId":"51237","value":1,"role":"verification:checks"},{"nodeKey":"write_foundry_tests","agentId":"52194","value":1,"role":"verification:checks"}]}]}