{"workflow":{"id":"bbfc18fc-1431-4767-a891-3e6fb7ae5b3b","objective":"Release Pixel Wall (ERC-20 symbol PIXL) on Sepolia as an evm_project: the fixed-supply launch token plus one application contract. Token: Pixel Wall (PIXL), total supply 1,000,000,000 PIXL with 18 decimals, minted once to the deployer. Application contract: PixelCanvas. Currency: PIXL is the app's working currency. PixelCanvas takes the PIXL address as its only constructor argument (constructorArgs [\"$token\"]), stores it immutable, exposes it as token(), and holds no PIXL at deploy; players get PIXL by swapping Sepolia ETH in the launch pool the factory seeds. Every payment in is approve + SafeERC20.safeTransferFrom (permit not required). PixelCanvas has no payable function and no receive/fallback, so it never holds ETH. Payouts are pull-based (the recipient calls to collect; nothing is pushed to third parties), follow checks-effects-interactions and are nonReentrant. Burns are transfers to 0x000000000000000000000000000000000000dEaD. No owner, admin, pause or upgrade path. A 32x32 shared canvas paid in PIXL. Pixels: index = y * 32 + x with x, y in 0..31; any other index reverts. A colour is a uint24 0xRRGGBB; the canvas starts all 0x000000. Colours are stored packed and canvas() returns all 1,024 colours in one call as bytes of length 3,072 (3 bytes per pixel, index order). Price: every pixel has its own price, starting at 10 PIXL (10 * 10^18 base units). paint(index, colour) charges the pixel's current price; afterwards that pixel's price becomes floor(old * 11 / 10), capped at 1,000,000 PIXL. paintBatch(indices, colours) paints up to 64 pixels with one safeTransferFrom of the summed cost; mismatched lengths, an empty batch or more than 64 entries revert; a repeated index in one batch is processed in order, each at its then-current price. Split: the first paint of a pixel burns 100% of the price; a repaint credits floor(price / 2) to the previous painter's withdrawable balance and burns the rest in the same call. Repainting your own pixel is allowed (you are credited half, the rest burns). withdraw() pays the caller's whole withdrawable balance and reverts on zero. Views: canvas(), priceOf(index), painterOf(index), withdrawable(address), token(). Events: Painted(index, colour, painter, price), Withdrawn(account, amount). Tests (Foundry) must cover: price growth and the 1,000,000 PIXL cap; the first-paint vs repaint split with odd prices; batch limits and a repeated index; out-of-range index reverts; withdraw of zero reverts and cannot pay twice; and the invariant that PIXL held by PixelCanvas always equals the sum of withdrawable balances (the rest was burned at paint time). The independent adversarial review must attack: rounding in the 50/50 split and the 10% step, the price-cap boundary, batch cost arithmetic (a batch must never cost less than the same paints one by one), and reentrancy or griefing through withdraw. Deploy through the project factory, then publish a one-page website to draw the live canvas from canvas() and Painted events, pick a colour, queue up to 64 pixels and show the total cost before painting. The page reads the PIXL address from PixelCanvas.token(), shows the connected wallet's PIXL balance, allowance and withdrawable balance, has an Approve step before every paying action and a Withdraw button, and says that PIXL comes from swapping Sepolia ETH in the launch pool (no in-page swap). Lists come from contract views and events only (no backend, no indexer). Keep it to one small page; the static export has index.html in dist/.","status":"completed","brief":"# Approved workflow\n\nRelease Pixel Wall (ERC-20 symbol PIXL) on Sepolia as an evm_project: the fixed-supply launch token plus one application contract. Token: Pixel Wall (PIXL), total supply 1,000,000,000 PIXL with 18 decimals, minted once to the deployer. Application contract: PixelCanvas. Currency: PIXL is the app's working currency. PixelCanvas takes the PIXL address as its only constructor argument (constructorArgs [\"$token\"]), stores it immutable, exposes it as token(), and holds no PIXL at deploy; players get PIXL by swapping Sepolia ETH in the launch pool the factory seeds. Every payment in is approve + SafeERC20.safeTransferFrom (permit not required). PixelCanvas has no payable function and no receive/fallback, so it never holds ETH. Payouts are pull-based (the recipient calls to collect; nothing is pushed to third parties), follow checks-effects-interactions and are nonReentrant. Burns are transfers to 0x000000000000000000000000000000000000dEaD. No owner, admin, pause or upgrade path. A 32x32 shared canvas paid in PIXL. Pixels: index = y * 32 + x with x, y in 0..31; any other index reverts. A colour is a uint24 0xRRGGBB; the canvas starts all 0x000000. Colours are stored packed and canvas() returns all 1,024 colours in one call as bytes of length 3,072 (3 bytes per pixel, index order). Price: every pixel has its own price, starting at 10 PIXL (10 * 10^18 base units). paint(index, colour) charges the pixel's current price; afterwards that pixel's price becomes floor(old * 11 / 10), capped at 1,000,000 PIXL. paintBatch(indices, colours) paints up to 64 pixels with one safeTransferFrom of the summed cost; mismatched lengths, an empty batch or more than 64 entries revert; a repeated index in one batch is processed in order, each at its then-current price. Split: the first paint of a pixel burns 100% of the price; a repaint credits floor(price / 2) to the previous painter's withdrawable balance and burns the rest in the same call. Repainting your own pixel is allowed (you are credited half, the rest burns). withdraw() pays the caller's whole withdrawable balance and reverts on zero. Views: canvas(), priceOf(index), painterOf(index), withdrawable(address), token(). Events: Painted(index, colour, painter, price), Withdrawn(account, amount). Tests (Foundry) must cover: price growth and the 1,000,000 PIXL cap; the first-paint vs repaint split with odd prices; batch limits and a repeated index; out-of-range index reverts; withdraw of zero reverts and cannot pay twice; and the invariant that PIXL held by PixelCanvas always equals the sum of withdrawable balances (the rest was burned at paint time). The independent adversarial review must attack: rounding in the 50/50 split and the 10% step, the price-cap boundary, batch cost arithmetic (a batch must never cost less than the same paints one by one), and reentrancy or griefing through withdraw. Deploy through the project factory, then publish a one-page website to draw the live canvas from canvas() and Painted events, pick a colour, queue up to 64 pixels and show the total cost before painting. The page reads the PIXL address from PixelCanvas.token(), shows the connected wallet's PIXL balance, allowance and withdrawable balance, has an Approve step before every paying action and a Withdraw button, and says that PIXL comes from swapping Sepolia ETH in the launch pool (no in-page swap). Lists come from contract views and events only (no backend, no indexer). Keep it to one small page; the static export has index.html in dist/.\n\nSepolia (11155111) only. GitHub publication and IPFS hosting are approved. Launch token: a separate fixed-supply ERC-20, 18 decimals, no constructor arguments, exactly 1,000,000,000 minted to msg.sender, no mint or admin functions. The factory sends that supply to LP and rewards, so no application contract may need a launch-token balance at deploy. Application contracts are fully configured in nonpayable constructors using only address, uint, bool or bytes32 arguments (no strings, arrays, proxies, delegatecall or selfdestruct); anything else is set at runtime. No owner unless the request names one, and then it is $owner. No external oracles, VRF or keepers: randomness is commit-reveal or a future blockhash read within 256 blocks with a refund path. foundry.toml sets bytecode_hash = \"none\". The website is a static export with index.html in dist/. Site label lab-pixel-canvas.\n\nBuild PIXL and PixelCanvas (PixelCanvas takes constructorArgs [\"$token\"] and charges PIXL) with Foundry tests and an independent adversarial review, deploy them through the project factory, then build the one-page website against the live deployment.\n","briefDigest":"47dac2b44433622cde458322075beadb80939f82099b5347b2488a3ca0ff866a"},"planning":null,"id":"959b62c5-9e80-4b76-b612-bf255a24d7ad","state":"completed","template":"shape:chain","objective":"WORKFLOW FRONTEND STAGE CONTEXT: contracts are already deployed. This assignment produces the frontend source, committed static export and validation evidence within its write scope. Put frontend source, package.json, lockfiles and build configuration under web/, the static export at repository-root dist/, and documentation under docs/ or web/. A web/** scope also receives an explicit web/.gitignore allowance; directory globs exclude other dotfiles. Follow narrower assigned paths when supplied. Root configuration and lockfiles stay protected. Read .imd/reads/deployment.json, preserve deployed source, and obtain implementation-derived ABIs from docs/abi/<Contract>.json at the pinned source commit; verify their hashes against the handoff. Read .imd/reads/workflow.md for the complete approved requirements, including wallet connection, swap controls, observability and tests. Submit the source/export/evidence to complete this worker assignment. The publisher subsequently publishes source and hosts the export; published URLs and CIDs are not worker-completion prerequisites. This assignment does not publish the site or redeploy contracts.\n\nMANDATORY FRONTEND ACCEPTANCE: Emit dist/imd-deployment.json after the final static export. Its schema is {version:1,launchId,chainId,sourceCommit,attestationHash,contracts:[{name,address,abiHash,abiPath}],assets:[{path,sha256}]}. Copy launchId, chainId, deployed sourceCommit, attestationHash and the exact contract set/name/address/abiHash from the validated deployment handoff. Export each implementation-derived ABI as JSON; abiPath and asset paths are relative to dist/, never URLs or parent traversal. The frontend must load this same imd-deployment.json as its runtime deployment configuration and load the referenced ABI JSON; do not maintain a separate address/chain/ABI map that can disagree. After building, enumerate every exported file except imd-deployment.json, including index.html and all ABI JSON, and record each file's SHA-256 as lowercase hex. At most 128 assets and 8 MiB per file. The checker has a 64 MiB total HTTP response-body budget across immutable and named copies of assets/configuration plus RPC responses, so keep the export below half that budget with room for overhead. The manifest excludes itself to avoid a recursive hash. Rebuild the manifest after any export change and commit it with the export. Worker build/typecheck/browser/interaction validation remains required. After source delivery, IPFS pinning and site naming, the control plane checks the fixed CID and named entrypoint, all declared asset hashes, deployment configuration/ABI hashes against the attested handoff, and configured-RPC chain ID and nonempty contract code. It does not execute browser JavaScript or wallet swaps. Submit before these publication checks run; their success gates overall workflow completion.","blockedReason":null,"createdAt":"2026-09-27T05:50:19.159Z","updatedAt":"2026-09-27T06:28:53.500Z","paidBy":"0x8a3b860f6dbfbbbb07f21905ed8cb0234538bdc8","via":null,"parentJobId":"48fdb771-69d6-4f52-9dd9-e066a8ef5cf2","project":{"id":"48fdb771-69d6-4f52-9dd9-e066a8ef5cf2","head":"959b62c5-9e80-4b76-b612-bf255a24d7ad","running":null,"versions":[{"jobId":"48fdb771-69d6-4f52-9dd9-e066a8ef5cf2","workflowId":"bbfc18fc-1431-4767-a891-3e6fb7ae5b3b","objective":"Release Pixel Wall (ERC-20 symbol PIXL) on Sepolia as an evm_project: the fixed-supply launch token plus one application contract. Token: Pixel Wall (PIXL), total supply 1,000,000,000 PIXL with 18 decimals, minted once to the deployer. Application contract: PixelCanvas. Currency: PIXL is the app's working currency. PixelCanvas takes the PIXL address as its only constructor argument (constructorArgs [\"$token\"]), stores it immutable, exposes it as token(), and holds no PIXL at deploy; players get PIXL by swapping Sepolia ETH in the launch pool the factory seeds. Every payment in is approve + SafeERC20.safeTransferFrom (permit not required). PixelCanvas has no payable function and no receive/fallback, so it never holds ETH. Payouts are pull-based (the recipient calls to collect; nothing is pushed to third parties), follow checks-effects-interactions and are nonReentrant. Burns are transfers to 0x000000000000000000000000000000000000dEaD. No owner, admin, pause or upgrade path. A 32x32 shared canvas paid in PIXL. Pixels: index = y * 32 + x with x, y in 0..31; any other index reverts. A colour is a uint24 0xRRGGBB; the canvas starts all 0x000000. Colours are stored packed and canvas() returns all 1,024 colours in one call as bytes of length 3,072 (3 bytes per pixel, index order). Price: every pixel has its own price, starting at 10 PIXL (10 * 10^18 base units). paint(index, colour) charges the pixel's current price; afterwards that pixel's price becomes floor(old * 11 / 10), capped at 1,000,000 PIXL. paintBatch(indices, colours) paints up to 64 pixels with one safeTransferFrom of the summed cost; mismatched lengths, an empty batch or more than 64 entries revert; a repeated index in one batch is processed in order, each at its then-current price. Split: the first paint of a pixel burns 100% of the price; a repaint credits floor(price / 2) to the previous painter's withdrawable balance and burns the rest in the same call. Repainting your own pixel is allowed (you are credited half, the rest burns). withdraw() pays the caller's whole withdrawable balance and reverts on zero. Views: canvas(), priceOf(index), painterOf(index), withdrawable(address), token(). Events: Painted(index, colour, painter, price), Withdrawn(account, amount). Tests (Foundry) must cover: price growth and the 1,000,000 PIXL cap; the first-paint vs repaint split with odd prices; batch limits and a repeated index; out-of-range index reverts; withdraw of zero reverts and cannot pay twice; and the invariant that PIXL held by PixelCanvas always equals the sum of withdrawable balances (the rest was burned at paint time). The independent adversarial review must attack: rounding in the 50/50 split and the 10% step, the price-cap boundary, batch cost arithmetic (a batch must never cost less than the same paints one by one), and reentrancy or griefing through withdraw. Deploy through the project factory, then publish a one-page website to draw the live canvas from canvas() and Painted events, pick a colour, queue up to 64 pixels and show the total cost before painting. The page reads the PIXL address from PixelCanvas.token(), shows the connected wallet's PIXL balance, allowance and withdrawable balance, has an Approve step before every paying action and a Withdraw button, and says that PIXL comes from swapping Sepolia ETH in the launch pool (no in-page swap). Lists come from contract views and events only (no backend, no indexer). Keep it to one small page; the static export has index.html in dist/.","baseCommit":"0243d7da4a4337ae8b16bcdf15bb4ead736fd68f","state":"completed","createdAt":"2026-09-27T05:08:17.792Z"}]},"deliver":true,"host":true,"site":{"id":"8621869c-7341-4db3-bfad-e0b147769027","jobId":"959b62c5-9e80-4b76-b612-bf255a24d7ad","kind":"launch","tokenId":null,"agentId":null,"url":"https://lab-pixel-canvas.site.identitymd.eth.limo","status":"named","holdReason":null,"takenDownAt":null,"takenDownReason":null,"label":"lab-pixel-canvas","cid":"bafybeifaewgfis2w6ywgmdn3s45tn2dsiltgki4rdg7mmabrhsmebfarne","bytes":562007,"ensName":"lab-pixel-canvas.site.identitymd.eth","ensParent":null,"txHash":"0xd44c9c203db040cb6ed521d6b8157747c99828b4c7dfee4da67ae6b095787655","blockNumber":26067013,"attempts":0,"failure":null,"pinnedAt":"2026-09-27T06:29:22.417Z","namedAt":"2026-09-27T06:30:25.215Z","supersededBy":null,"supersededAt":null,"previewHash":"873ec1277f7a3c5c5d257aa03cbc24aa39d41f842953eff7d77a45e9cb8e58d3","createdAt":"2026-09-27T06:28:53.500Z","updatedAt":"2026-09-27T06:30:25.215Z"},"launch":{"requested":false,"kind":null,"id":null,"status":null,"chainId":null},"oracleRequestId":null,"delivery":{"repoUrl":"https://github.com/identity-md-launches/launch-306-workflow-frontend-stage-context","pullRequestUrl":null,"commit":"930316b9bc03164997aa35c3ea7bddabc025725c","deliveredAt":"2026-09-27T06:47:31.649Z","media":null},"media":null,"nodes":[{"key":"frontend_for_contract","role":"implement","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":[],"allowedPaths":["web/**","dist/**","docs/**","web/.gitignore"],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-09-27T06:28:53.500Z","verdict":{"status":"accepted","profile":"none","evaluation":"structural","rejectionCode":null,"detail":"paths and tree verified; no suite was run for this kind of work","verifierVersion":"0.1.0+ff982c0f","verifiedTreeHash":"4ce8a13e2304275a0e13ea691828a9cb2b57d1b1","at":"2026-09-27T06:28:53.503Z","failedChecks":[]},"seat":{"tokenId":"7","agentId":"51075"},"live":null}],"reviews":[{"status":"sent","chainId":1,"txHash":"0xf41c58db36d49770a02b589115ea5b0c6232312b2ec18f58ed78bdd4b42378cc","blockNumber":26115437,"sentAt":"2026-10-04T00:35:42.598Z","entries":[]},{"status":"sent","chainId":1,"txHash":"0x5cab53702320f86828bb06cbf60db7bcc6db5c40b962b6a475d1d61341abe12c","blockNumber":26114246,"sentAt":"2026-10-03T20:37:05.992Z","entries":[{"nodeKey":"frontend_for_contract","agentId":"51075","value":1,"role":"verification:structural"}]}]}