# Swarm Commission NFT: launch specification

**Report date: 5 October 2026.** This is an architecture decision report, not audited Solidity, legal advice, or confirmation that the proposed IdentityMD Intake exists. **ASSUMPTION** below marks IdentityMD plane claims derived only from the assignment’s description. Factual statements have linked sources; inferences and unresolved points are identified as such.

## Recommendation

Launch an ERC-721 collection of transferable claim tickets. The service-cost floor is 1.0 IMD for one 0.5 IMD image job and one 0.5 IMD panel request; charge 3.0 IMD if promising the bounded worst-case budget of three jobs and two reviews, with unused funds refundable. The token stays visually blank and its metadata discloses only its commission status until an image’s bytes, content identifier and signed panel verdict have been bound on chain. Prompt inputs are immutable collection rules plus a commit/reveal seed finalized from future block entropy; the deployer cannot choose per-token prompt parameters. Use four contracts created by the collection constructor: the ERC-721 coordinator, a bounded funds vault, a delivery evidence registry, and a royalty splitter (the Intake remains a pre-existing upstream dependency, not a fifth deployment). A panel “yes” gates reveal only after signature, signer, question prefix, chain, consumer, block window, expiry, quorum and minimum agreement checks. A “no” consumes a retry, while timeout, oracle refusal or exhausted retries become an explicit holder refund. This is a commissioned-art system whose on-chain guarantees are process integrity and evidence provenance, not proof that a subjective judgement is objectively correct.

## Decisions

| # | Choice | Figure / limit | Main reason |
|---|---|---:|---|
| 1 | Mint non-revealed, transferable claim and advance the commission through bounded stages | 1.0 IMD minimum service cost; 3.0 IMD launch price for capped retries | The buyer funds both creation and its first review; fully funded reserves prevent stranded tickets. |
| 2 | Freeze a brief hash and deterministic prompt recipe; use a post-commit seed | `keccak256(brief bytes)`; seed commitment/reveal window 64 blocks | Fixed rules prevent operator discretion; delayed entropy resists deployer selection. |
| 3 | Ask the panel one exact bool question; require independent seats and a signed agreement floor | 7 panelists, quorum 5, signed `agreed >= 4/5` | Meaningful majority evidence, with maker exclusion and independently identified voter seats. |
| 4 | Permit 3 image submissions and 2 paid reviews per token, then refund on terminal failure | Maximum three job spends and two review spends; funds cap 3.0 IMD/token | Bounds waste and avoids infinite retries; reserves must be funded before promising them. |
| 5 | Persist image/metadata/evidence by CID and EVM hashes; offer only rights actually controlled | At least 2 independent pins; broad nonexclusive display/reuse grant subject to rights | Content addressing proves bytes; replication supports retrieval. AI authorship rights vary by law. |
| 6 | Pay a maker only when upstream completion carries authenticated agent identity | Minimal upstream addition: signed `agentId` and registry-domain proof in callback | A delivery URI alone does not establish who delivered it. |
| 7 | Combine Art Blocks’ deterministic provenance, Botto’s panel/community selection, and Bright Moments’ reveal ceremony without inheriting their hidden dependencies | Five comparators plus Autoglyphs / Async Art | The design must also solve uptime, curation, fairness, rights, and royalty enforcement. |

## 1. Lifecycle, price and holder experience

### States and transitions

| State | Entry and allowed transition | Holder sees | Target / timeout |
|---|---|---|---|
| `Unminted` | `mint(recipient)` escrows funds and mints ticket → `SeedPending` | Ticket number, immutable brief hash, “commission queued”; no preview | Immediate transaction; mint closes at fixed supply. |
| `SeedPending` | Keeper publishes seed reveal after future block; → `JobPending` | Prompt recipe/version and seed commitment; not image prompt if prompts are considered sensitive | 64 blocks, typically ~13 minutes on 12-second L1 blocks (inference; chain dependent). |
| `JobPending` | Any keeper calls Intake `ask` with derived prompt, job payment → `DeliveryPending` | Ticket remains blank with status and deadline | **ASSUMPTION:** job costs 0.5 IMD and image delivery takes minutes; hard deadline 24h. |
| `DeliveryPending` | Valid Intake callback records immutable result hash/URI and optional authenticated maker; → `JudgingPending` | “Image received; awaiting review”; not yet visible | **ASSUMPTION:** callback best effort, 200,000 gas; keeper/anyone can reconcile; 48h deadline. |
| `JudgingPending` | Keeper pays oracle 0.5 IMD and submits attestation → `Revealed` if yes, otherwise `Retryable` | “Under panel review”; image remains undisplayed | **ASSUMPTION:** oracle answer arrives in minutes; 24h deadline. |
| `Retryable` | If reject, preserve rejected hash/evidence; start a new job using retry counter in prompt seed → `JobPending` | Rejected attempt count and evidence pointer; still blank | One retry, then fallback. A second oracle failure may use available funded reserve. |
| `Revealed` | Successful verification atomically sets final image and evidence URI, event emitted | Full metadata, image, signed verdict and provenance | Final state, never revocable or replaced. |
| `Refundable` | Deadline/refusal/final reject with exhausted paid retries; claimant burns ticket for their remaining escrow credit → `Refunded` | Refundable status and exact amount | Permissionless after deadline; refund to current token owner. |
| `Refunded` | Terminal | Burned ticket / audit record remains in events | Terminal. |

Mint is a purchase of a *claim*, not a guarantee that any particular aesthetic result passes. The minimum service cost is 1.0 IMD (one 0.5 image job plus one 0.5 review); the proposed 3.0 IMD mint funds the bounded maximum schedule and leaves at least 0.5 IMD refundable. This cost does not include gas, permanent storage, or operational keeper costs. A sold-out system cannot promise retries unless the full reserve is prepaid into the vault. If the first result passes, unused escrow is returned to the current holder; recommendation: refund it, avoid disguised proceeds.

**ASSUMPTION:** the IdentityMD plane charges 0.5 IMD each for `oracle.request` and an artwork job, returns an answer in minutes, and supports the described request/callback flow. Confirm the actual payment token, decimals, escrow semantics, idempotency, callback identity and timeout before pricing. For Intake unavailability, a keeper pays through the HTTP door and later records the request identifier plus signed response; the contract’s verifier is identical either way. A retry is never free merely because a callback was missed: it requires escrow balance. The liveness deadline starts from the on-chain request timestamp, not from an off-chain claimed start.

## 2. Frozen brief and prompt derivation

At deployment the constructor stores `briefHash = keccak256(UTF8(canonicalBrief))`, `promptRecipeHash`, model/tool policy digest, maximum supply and a `chainSeedCommitment`. Canonical brief bytes, recipe source, criteria and licence are published in a permanent content-addressed release. Contract code fixes the template fields; there is no owner setter, upgrade key, or deployer exception. ERC-721 IDs remain stable identifiers under the standard. [ERC-721](https://eips.ethereum.org/EIPS/eip-721)

Each ticket commits a user salt at mint. Once minting is closed or the ticket is minted, the user reveals salt within a fixed interval; failure uses a deterministic default and makes that forfeiture visible. The contract also commits a secret seed at deployment, then reveals it after the reveal window. Derive:

```text
seed[i] = keccak256(abi.encode(
  "IMD-SWARM-ART-v1", chainId, collection, tokenId,
  briefHash, promptRecipeHash, userSalt, revealedCollectionSeed,
  previousFinalImageHash (zero for token 1), retryNumber
))
```

The prompt is a deterministic serialization of the frozen template with `tokenId`, `seed`, and optionally prior final image hash/CID as variables. Use hashed previous artwork only to seed a new prompt, never as a hidden arbitrary text input. The image model itself is not deterministic; the reproducible claim is about the *prompt inputs*, not identical image bytes. On failure, incrementing `retryNumber` changes the prompt. Store every attempt’s derived prompt hash and output hash.

Do not use the minting block hash as the sole entropy source: the minter or block producer may influence it, and `blockhash` is unavailable after its short window. A commit/reveal seed stops unilateral deployer steering only if the secret is actually unpredictable and no single party can withhold it. Better: commit multiple independent entropy contributions (user, deployer, keeper) and define a timeout fallback from future blockhash plus commitment; this adds griefing risk. For a small immutable deployment, recommend user salt plus a future blockhash after mint commitment and disclose that it is pseudo-random, not unbiased VRF. **Inference:** no chain-independent scheme can guarantee both unbiased entropy and liveness without an external randomness source or threshold protocol.

## 3. Judging and attestation

### Canonical oracle question

Question document prefix (UTF-8, canonical JSON with sorted keys and no whitespace; the actual canonicalization version is frozen in source):

```json
{"answerType":"bool","criteriaHash":"0x…","imageHash":"0x…","purpose":"imd-art-acceptance-v1","tokenId":"…","briefHash":"0x…","attempt":0,"rubric":"The delivered image identified by imageHash satisfies every criterion in criteriaHash under the published rubric."}
```

The request window is appended as `fromBlock` and `toBlock`; the consumer computes the expected `questionHash = keccak256(canonicalDocumentIncludingWindow)`. The oracle returns one boolean `answer` for: **“Does the image at content hash `<imageHash>` satisfy every named criterion in criteria hash `<criteriaHash>` and the frozen collection brief `<briefHash>`? Return true only if all mandatory criteria pass.”** Criteria must enumerate observable constraints (e.g., prohibited content absent, palette/subject requirements present) and define rejection examples. Art quality remains subjective; panel answers are not facts about external reality.

**ASSUMPTION:** the request and response fields, EIP-712 domain, service signer and chain-window behavior in the following rule are as specified in the assignment and have not been independently verified on a live IdentityMD deployment. Accept exactly `answerType=bool`, expected question hash, `chainId=block.chainid`, `verifyingContract=address(this)` in the EIP-712 domain `IdentityMD Oracle`, version `2`, signer `0x5598aa9146215bc13eb26f2c692ad1461fd32982`, quorum at least 5, panel size at least 7, `issuedAt <= now < expiresAt`, `toBlock >= fromBlock`, `toBlock > previousAcceptedToBlock[tokenId]`, and the signed window exactly matches the expected question document. Require an 80% agreement floor: encode this as `agreed >= 80` if the live scale is 0–100, or `>= 8000` if basis points; settle this field’s scale before coding. The signature covers requestId, chainId, questionHash, answerType, answer, figure, fromBlock, toBlock, blockHash, panelJobId, panelSize, quorum, agreed, issuedAt, expiresAt. Do not accept unsigned callback booleans as oracle evidence.

**ASSUMPTION:** under the supplied oracle model, this is panel evidence, not a re-runnable chain recipe. The model says only named recipes such as log-sum/count, Uniswap v4 spot, call-compare, log-rank and volume-rank qualify as chain evidence; aesthetic judgement cannot be independently replayed from chain state. Therefore store `answerType=bool`, require signed source/answer fields and quorum, label it panel evidence in metadata, and do not market it as cryptographic verification of taste. The oracle signature authorizes an answer; the on-chain checks bind it to this ticket’s intended question and protect against a signed answer purchased for another consumer/question. Enforce strictly advancing `toBlock` to prevent replay across recurring requests.

### Panel composition and maker exclusion

Require seven distinct panelists and quorum five. The oracle signer’s aggregate attestation does not prove seven independent participants or individual votes. **ASSUMPTION:** the oracle service can configure maker exclusion and provide attributable member receipts. Request exclusion of the verified maker ID and do not count that seat. The described signed struct does not include the excluded ID or panel member commitment, so on-chain exclusion cannot be enforced from the fields currently specified. Minimum upstream enhancement: include `panelMembersHash` and `excludedAgentId` in signed fields, plus a public receipt bundle resolving unique member IDs and votes. Until then, maker exclusion is an operational service policy, not an on-chain guarantee, and must be disclosed as such.

## 4. Failure, retry and terminal outcomes

Three job spends maximum per token and two oracle requests maximum; charge 3.0 IMD upfront into escrow, authorize spending up to three 0.5 IMD jobs and two 0.5 IMD reviews (2.5 IMD), and refund unused balance. The third job is available only to replace a timed-out, malformed or undeliverable attempt; it cannot be used after the two allowed reviews have both returned “no.” A false verdict consumes a review and may trigger one new image job; after the second false verdict the ticket becomes refundable immediately. An oracle refusal or timeout does not count as a verdict, but can be retried once from reserve. The 0.5 IMD unspent under the maximum schedule is also refunded.

Failure matrix:

| Failure | Response | Holder remedy |
|---|---|---|
| Job never acknowledged | Permissionless timeout after 24h; release no maker amount, mark attempt abandoned | Retry once from escrow; thereafter refund remaining escrow and close. |
| Intake callback lost | Anyone calls `recordDelivery` with verifiable Intake result proof, if available; else timeout | Do not pay twice; request IDs are unique/idempotent. |
| Malformed image/CID or hash mismatch | Reject before asking panel; preserve evidence hash | Counts as failed job; retry within cap. |
| Panel returns false | Store attestation and rejected content hash; prompt changes via retry counter | One replacement job; if last eligible attempt fails, refund. |
| Panel refuses or no answer | After 24h, allow one paid repeat; after 48h total, `Refundable` | Refund remaining balance; do not silently accept. |
| Oracle key rotates/compromised | No deploy-time privileged setter exists, so pause acceptance through terminal refund path | Tickets awaiting judgement become refundable after published emergency delay; no hidden key override. |
| Storage vanishes | The CID still identifies expected bytes but might not be served | Holder may supply matching bytes or pin elsewhere; evidence remains, no substitution. |

The final fallback is a refund, never arbitrary curator acceptance and never a made-up placeholder image. If the operator’s service fails before all allocated payment was spent, the current token owner claims the remaining exact escrow balance. Any unspent funds on reveal return to the owner. All timeout paths are permissionless to execute, avoiding a privileged keeper veto. A fully minted collection cannot depend on future donations for promised retries/refunds.

## 5. Provenance, storage and rights

Delivery includes raw image bytes and a deterministic metadata JSON. The server computes the image CID; the contract stores the raw `bytes32 imageKeccak`, full CID string (or compact CID bytes), metadata CID, prompt hash, job request ID, attempt number, signed attestation digest and signer. Recompute the file digest before accepting. Content addressing allows verifying fetched content but does not guarantee it will remain available; IPFS documentation explicitly distinguishes persistence from permanence and recommends pinning for retention. Require two independent pinning operators plus a downloadable CAR archive mirrored by the project and community. [IPFS persistence and pinning](https://docs.ipfs.tech/concepts/persistence/), [IPFS content addressing](https://docs.ipfs.tech/concepts/how-ipfs-works/)

Before reveal, `tokenURI` returns a stable ticket JSON without final image link. At reveal it returns immutable metadata CID, image CID, brief hash, prompt derivation version, all attempt hashes, maker identity if verified, and full EIP-712 attestation (signature plus decoded fields) or a URI to it whose digest is committed on chain. Anyone can independently recover the oracle signer and recompute the question hash. ERC-721 permits metadata URI conventions, but the standard does not guarantee URI immutability; enforce this collection-specific invariant in code. [ERC-721](https://eips.ethereum.org/EIPS/eip-721)

**Recommended rights notice:** “The token conveys ownership of the token and a perpetual, worldwide, nonexclusive permission to display, reproduce, and adapt the delivered image for personal and commercial use, to the extent the commissioning entity has rights to grant those permissions. No exclusive copyright is promised. Third-party model terms and applicable law may limit rights.” Publish the model/vendor and provenance policy; prohibit submissions containing known third-party protected material or personal likeness without rights. The U.S. Copyright Office’s January 2025 report says copyright in AI output turns on sufficient human expressive contribution and that mere prompting is not enough; protection may apply to human-authored elements/arrangements. That is U.S. guidance, not a global rule. [US Copyright Office report release](https://www.copyright.gov/newsnet/2025/1060.html), [Part 2 report](https://www.copyright.gov/ai/Copyright-and-Artificial-Intelligence-Part-2-Copyrightability-Report.pdf)

Do not apply CC BY 4.0 automatically to an output unless the licensor has rights to license it. Its terms allow commercial sharing and adaptation with attribution, but cannot create copyright over otherwise unprotected output. [CC BY 4.0 deed](https://creativecommons.org/licenses/by/4.0/deed.en) **Open legal question:** choose governing law and obtain counsel on likeness, dataset/model terms, consumer refunds, and enforceability of the rights notice.

## 6. Paying the maker

**ASSUMPTION:** the described Intake `complete(requestId,status,resultHash,uri,args)` callback does not inherently authenticate the agent that generated or uploaded the file. A URI, callback sender or job ID alone does not establish agent authorship. If the callback sender is a trusted plane contract, it verifies only that the plane completed a job, unless it also carries a signed agent identity binding.

Smallest upstream change: add `makerAgentId` and `makerRegistry` to completion data plus an EIP-712 maker signature over `(requestId, resultHash, uriHash, chainId, target)` made by the registered agent wallet, and have Intake validate the ERC-8004 identity/wallet at completion. Emit these fields in the completion event/callback. Consumer checks the immutable registry address/domain and the attested signature; store agentId with the token. If agent-to-agent wallet proof is unavailable, return explicit `makerVerified=false`, and route no token royalties based on the unverified name. ERC-8004 is a draft standard defining agent identity and feedback, and allows reputation feedback to be keyed by agentId; registry deployment/address remains chain-specific and must be verified at launch. [ERC-8004 draft](https://eips.ethereum.org/EIPS/eip-8004)

Royalty recommendation: EIP-2981 report 5% to a per-token immutable splitter that allocates e.g. 70% to verified maker, 20% panel pool, 10% storage/maintenance. If maker identity is unverified, maker portion accrues to a disclosed claim escrow for 12 months, then treasury. But ERC-2981 only signals royalty information; the marketplace payment is voluntary and the standard does not enforce transfers. [EIP-2981](https://eips.ethereum.org/EIPS/eip-2981) Therefore do not promise royalties as a guaranteed income stream; the primary maker payment is the job fee. Each test must prove no address can redirect escrow.

## 7. Comparables and unresolved product problems

Comparator facts below are read 5 October 2026 unless the source itself is date-stamped; dynamic project documentation does not expose a reliable revision date. No market-volume or royalty percentages are asserted.

| Project | Mechanism evidenced by primary source | Problem it solved | Lesson here |
|---|---|---|---|
| Art Blocks | Collector mint creates unique hash fed to on-chain algorithm; same hash deterministically reproduces output. Engine stores scripts and token hashes. [Docs](https://docs.artblocks.io/), [core contract](https://github.com/ArtBlocks/artblocks-docs/blob/main/developer/core-contract.md) | Reproducibility, artist-authored generative rules, long-lived reconstruction | Our model is stochastic and off-chain; freeze recipe and prompt provenance, avoid claiming exact reproducibility. |
| Botto | Community votes on fragments; documentation describes weekly mint/auction cadence and feedback shaping future generation. [Project summary](https://docs.botto.com/), [governance](https://docs.botto.com/details/governance) | Human curation loop and collective taste | State the rubric and panel composition; a majority can still be wrong, so panel evidence is limited. |
| Async Art | Layered masters could change via separately held layers; public project page records that when its infrastructure went dark, composition/control stopped working. [Async](https://async.art/) | Programmable collaborative artwork and changing ownership controls | Avoid critical rendering logic behind a single web service; publish frozen output and independent renderer/bytes. |
| Bright Moments | Describes first-time reveal as an in-person designed minting experience and DAO-curated collection. [About](https://www.brightmoments.io/about) | Ceremony and provenance around first reveal | Our reveal can mark an on-chain completion event; do not confuse reveal ceremony with content persistence. |
| Autoglyphs | Fully on-chain generative art project, generated and stored by contract (source project/contract). [Larva Labs project](https://www.larvalabs.com/autoglyphs) | Minimal dependency surface and on-chain reconstruction | Our image size/job economy makes full raster storage impractical; preserve content hashes and redundant bytes. |
| Foundation / curated marketplaces | ERC-2981 royalty signaling is advisory, not forced by token transfers. [EIP-2981](https://eips.ethereum.org/EIPS/eip-2981) | Standard royalty discovery across marketplaces | Maker economics must work at primary job payment even if resale royalties are ignored. |

The commissioned collection also has problems comparators do not solve together: oracle request cost versus mint demand, selection bias in subjective panels, sybil panel seats, repeated-image similarity, prompt injection through content, agent identity attribution, biased model outputs, token-holder expectations during long asynchronous work, legal rights, and available data after the pinning sponsor leaves. A growing chain of prior art can produce interesting cumulative semantics, but serial dependencies make later prompts and deadlines depend on every previous token; make this optional and freeze whether failed tokens are skipped or represented as a fixed failure marker. Recommendation: chain only to the previous *revealed final* piece, and if one ticket refunds, use its committed seed and a fixed “no predecessor” marker so the sequence remains live.

## Contracts (interfaces and deployment constraints)

Four-contract cap counts newly deployed contracts only. The constructor deploys three child contracts and wires them directly. The Intake is an upstream dependency at a source constant address; it is not assumed deployed until verified. No deployment-time `setX` transaction follows. The supplied service signer is a compile-time constant. IMD token address, chain ID, Intake address and ERC-8004 registry addresses are currently unspecified, so there is no honest deployable artifact yet: once the IdentityMD launch publishes them, pin the verified addresses in source and reproduce bytecode. This resolves the instruction that privileged addresses are constants, not constructor parameters; it also makes launch contingent on knowing the target chain and addresses, not a hidden constructor placeholder.

**Contract 1 — `SwarmCollection` (ERC-721 coordinator)**

- **Constructor:** `(canonicalBrief, recipeHash, maxSupply, seedCommit, criteriaHash, pinnedIntakeAddress, imdTokenAddress)`; stores hashes, creates `CommissionVault`, `DeliveryBook`, and `RoyaltySplitter` children. In production, Intake/token/service signer/registry constants are hardcoded in this build; constructor parameters only carry collection-specific immutable content/limits. Revert if Intake/token code absent or token `decimals()` unexpected. Service signer constant is the supplied `0x5598…2982`.
- **Storage:** immutable brief/recipe/criteria/supply; seed and prompt commitments; `mapping(tokenId => State)`; attempts, escrow, request IDs, `imageHash`, CID/metadata hashes, maker ID/verification flag, accepted oracle window, evidence digest, prior finalized image hash; constant addresses; no mutable administrator or proxy.
- **External functions:** `mint(recipient, saltCommit)` payable in IMD via `transferFrom`; `revealSalt`; `startJob(tokenId)` callable by anyone when stage/deadline allow; `recordDelivery(requestId, …)` only Intake or proof-validating public function; `submitAttestation(tokenId, Attestation, signature)` permissionless but fully verified; `claimRefund(tokenId)` by current owner, permissionless execution sends to owner; ERC-721 transfer functions. `tokenURI` returns ticket/final JSON by state. No arbitrary `accept`, force-reveal, owner setter, or withdrawal.
- **Events:** `TicketMinted`, `StageChanged`, `JobRequested`, `DeliveryRecorded`, `PanelAttested`, `TokenRevealed`, `RefundAvailable`, `RefundClaimed`, `MakerVerified`.
- **Invariants:** ticket never reveals absent exact matching signed yes; signer/domain/question/window/agreement/quorum/expiry all valid; `toBlock` advances; final image immutable; retries bounded; callbacks idempotent; refund cannot exceed escrow; only current owner receives refund; failed states cannot be forced to reveal; token transfer cannot alter commission/evidence.

**Contract 2 — `CommissionVault` (child, IMD escrow)**

- **Constructor:** `(IERC20 imd, address collection)` called only by collection constructor; collection becomes immutable controller.
- **Storage:** per-token balance, per-attempt spend, cumulative job/review budgets, refund claimed bit; immutable token/controller.
- **Functions:** `depositFrom(payer, tokenId, amount)` collection only; `payJob(tokenId, requestId)` and `payReview(tokenId, requestId)` collection only with fixed exact amount; `refund(tokenId, recipient)` collection only; no generic withdraw, arbitrary recipient, approvals or user callback. Use safe transfer and balance delta checks; reject fee-on-transfer token.
- **Events:** `Deposited`, `ServicePaid`, `Refunded`.
- **Invariants:** balance accounting is conserved; fixed fees; no double payment for request ID; cannot spend another ticket’s balance; all unspent amount is claimable on terminal status.

**Contract 3 — `DeliveryBook` (child, immutable evidence registry)**

- **Constructor:** `(address collection, address intake, address identityRegistry)`; controller/intake/registry immutable constants verified at deploy.
- **Storage:** request-to-token mapping; attempt result hash, URI hash, job status, maker agentId, maker signature digest and verification bit; used callback IDs.
- **Functions:** `registerRequest` collection only; `completeFromIntake` only configured Intake; `proveDelivery` permissionless with upstream-signed payload; `getDelivery` view. Cannot edit or delete accepted evidence.
- **Events:** `DeliveryAccepted`, `DuplicateIgnored`, `MakerIdentityBound`.
- **Invariants:** one result per request; request binds one token/attempt; maker marked verified only after signature and registry ownership check; no callback can change a finalized attempt; result hash matches later bytes.

**Contract 4 — `RoyaltySplitter` (child)**

- **Constructor:** `(address collection, address reputationRegistry)`; immutable parent and registry, no owner.
- **Storage:** token-to-maker agentId and verified status; fixed 500 bps; accrued claims if protocol elects direct job-paid rewards; registry address is chain constant.
- **Functions:** `bindMaker(tokenId, agentId, verified)` collection only, once; `royaltyInfo(tokenId, salePrice)` view under ERC-2981; `claimMakerPayment(tokenId, recipient)` verifies maker wallet/agent ownership if paid commissions are later routed here. Avoid taking custody of marketplace sale proceeds: ERC-2981 only reports a quote.
- **Events:** `MakerBound`, `MakerPaymentClaimed`.
- **Invariants:** never redirects an already bound maker; unverified maker gets no maker royalty claim; quote is salePrice × 5%; no claim exceeds recorded accrual.

**Deployment wrinkle:** task’s “at most four” and “every link in constructor” are achievable only if the upstream Intake supports target registration at its deployment address or an immutable deployment-independent callback. If Intake must be configured after our deployment, this design cannot launch under the stated no-post-deploy-call rule. All address values must be confirmed against deployed bytecode and token methods before freezing constants. No keys, mutable admin, proxy or deployment transaction is specified here.

## Foundry test plan

Build with local mocks for IMD (standard, fee-on-transfer, reverting), Intake, ERC-8004 registry and EIP-712 signatures. Tests are required before implementation acceptance; none were run because this deliverable is an architecture report and the execution profile is `none`.

| Test | Required assertion / adversarial case |
|---|---|
| `testConstructorWiresChildrenAndConstants` | Child addresses point to collection; hardcoded signer/domain/chain dependency correct; no owner setters. |
| `testMintEscrowsExactAmountAndMintsBlankTicket` | Correct amount, owner, state and placeholder URI; rejects insufficient allowance/payment. |
| `testBriefAndRecipeFrozen` | No call path can alter hashes, collection cap or prompt recipe. |
| `testSeedCannotBeChosenAfterCommit` | Reveal mismatch fails; timeout fallback deterministic; user cannot grind multiple salts after observing final entropy. |
| `testPromptDerivationIncludesTokenAndPreviousFinal` | Golden hash vector; token, retry and predecessor each alter derived hash. |
| `testStartJobPermissionlessOnce` | Anyone can progress; second call cannot double-spend or create duplicate request. |
| `testIntakeCallbackReplayAndWrongRequest` | Duplicate callback idempotent; wrong token, attempt, status or Intake rejected. |
| `testMalformedDeliveryHashRejected` | Supplied bytes/hash mismatch cannot be accepted; malformed CID rejected. |
| `testAttestationValidRevealsAtomically` | Correct signed yes reveals once and binds image, question, answer, evidence and metadata. |
| `testWrongSignerRejected` | Same signed payload from non-service key fails. |
| `testWrongConsumerOrChainRejected` | Domain replay against another collection/chain fails. |
| `testQuestionHashMismatchRejected` | Answer purchased for different content hash, brief, criteria or token is rejected. |
| `testWindowMustAdvance` | Repeated or decreasing `toBlock` rejected; future/invalid ranges rejected. |
| `testExpiredOrNotYetIssuedAttestationRejected` | Expiry and `issuedAt` bounds enforced. |
| `testAgreementQuorumAndPanelFloor` | `agreed` below 8,000, quorum below five, panel size below seven fail. |
| `testPanelRefusalEnablesTimeoutNotReveal` | No callback never causes reveal; deadlines unlock bounded retry/refund. |
| `testMakerSeatExcludedOrFlaggedUnverifiable` | If signed seat commitments exist, maker ID among seats rejects; without them, verified-exclusion mode cannot be claimed. |
| `testRejectedImageCannotBeRevealedLater` | False result is terminal for that attempt; same content cannot bypass retry counter. |
| `testRetriesAreBounded` | More than allowed jobs/reviews reverts; exact final transition refundable. |
| `testRefundGoesToCurrentOwner` | Ticket transfer changes refund recipient; no operator destination parameter. |
| `testReentrantTokenCannotDoubleClaim` | Reentrant mock during refund cannot overdraw or claim twice. |
| `testFeeOnTransferTokenRejected` | Vault balance delta enforcement prevents underfunded commitments. |
| `testDifferentTicketsCannotCrossSubsidize` | Per-token balance isolation. |
| `testMakerIdentityRequiresAgentWalletProof` | Forged agent ID/signature/registry rejected; unverified delivery cannot acquire maker share. |
| `testFinalImageAndAttestationImmutable` | Replays, later deliveries and admin-like callers cannot mutate revealed token. |
| `testTokenURITransitionAndCIDIntegrity` | Ticket metadata before acceptance, final metadata after acceptance; CID/evidence hashes match. |
| `testRoyaltyQuoteIsSalePricePercentage` | Exactly 5% across zero/low/high inputs and no incorrect fixed amount. |
| `testNoPrivilegedRescueOrHiddenUpgrade` | No method drains escrow, swaps verifier, changes signer or force-reveals. |

Use fuzzing for token IDs, amounts, timestamp boundaries, callback order, signature fields, and attestation lengths. Invariant handler should randomize mint, deliver, accept, reject, timeout, transfer and refund while checking escrow conservation, immutable reveal, monotonic state, bounded counters and no double-spend. A separate fork check is required after target network publication to verify deployed Intake/token/registry code and methods; that is not possible from the information supplied.

## Risks ranked by severity

| Rank | Severity | Risk and mitigation |
|---:|---|---|
| 1 | Critical | Service key compromise or dishonest majority can attest a bad image. Require signer rotation policy before launch, panel seats/receipts, short expiry, visible evidence, refund path; current source key is fixed, so compromise cannot be patched without redeployment. |
| 2 | Critical | Intake callback semantics/identity differ from the assignment description; callbacks may be lost or spoofable. Validate deployed bytecode/interface and provide replay-safe proof path. |
| 3 | High | Subjective rubric and panel capture, collusion, sybils, maker judging, or biased data. Independent seats and maker exclusion need signed evidence; agreement is only a signed claim absent seat receipts. |
| 4 | High | CIDs identify bytes but pinning can end; media disappears even when chain record remains. Two independent pins, CAR mirrors, and periodic retrieval audits. |
| 5 | High | Payment denomination, decimals, chain and contracts are unknown. Incorrect constant can strand funds or deploy against a fake token. Publish target details and verify runtime code before build. |
| 6 | High | AI copyright/licensing is jurisdiction dependent and the commissioner may not possess rights it purports to grant. Avoid exclusivity claim, publish model/rights policy and get counsel. |
| 7 | Medium | Seed grinding/withholding compromises fairness or liveness. Combine commitments with timeout fallback; describe residual block-producer influence. |
| 8 | Medium | Job cost/review cost exceeds reserve as prices or service policy change. Fixed bounded budget, no overcommit; launch price must cover escrow plus operational/storage costs. |
| 9 | Medium | ERC-2981 royalties may not be paid by marketplaces. Treat them as optional upside and pay maker primarily from commission fee. |
| 10 | Medium | Serial “previous artwork” dependency propagates failures and alters later prompts. Use only final successful predecessor and defined refund marker. |

## Open questions for the IdentityMD developer

1. “Which chain, IMD token address, token decimals, and canonical deployed Intake address should this collection pin in source, and where can we verify their runtime code?”
2. “Can Intake be called and target-bound from a consumer constructor without a later registration transaction, and what exact authenticated callback ABI and retry behavior does it expose?”
3. “Does Intake bind `requestId` to the originating consumer, payment amount, status and result hash, and can anyone independently prove a callback that was not delivered?”
4. “Can a completed image job provide a cryptographically verified ERC-8004 `agentId`, registry address, agent wallet, and signature binding the request ID to the result hash?”
5. “Can oracle requests exclude the commissioned maker from panel selection and return a signed panel-member commitment, distinct member identities, votes, quorum and agreement scale?”
6. “Is `agreed` an integer percentage, basis points, or another scale, and is the specified oracle signer key fixed, rotated, or revocable?”
7. “What exactly does `questionHash` canonicalization use (JSON canonicalization, encoding, and field names), and how does the verifier distinguish panel evidence from recipe-reexecuted chain evidence?”
8. “What are the permitted `answerType` encodings for bool, the exact EIP-712 Solidity struct/domain type strings, and is `expiresAt` bounded by a service maximum?”
9. “What is the funded retry/refund policy when a service request is accepted but never completed, and can the consumer safely reuse request funds after a timeout?”
10. “May the collection publish the full prompt and output URI publicly before reveal, or must sensitive prompt data be held privately until after adjudication?”
11. “Which jurisdictions, image-generation providers, dataset policies and user licence language are approved for artwork commissioned and sold through IdentityMD?”

### Source notes

Technical interface claims are attributed to the relevant EIP; storage facts to IPFS documentation; copyright guidance to the U.S. Copyright Office; and comparator mechanisms to project documentation/pages. Project pages can change; the report date records when reviewed, while absent page revision dates are explicitly acknowledged above. Statements about the IdentityMD service behavior remain **ASSUMPTIONS** based on the task brief, not independently verified facts.
