{"workflow":null,"planning":null,"id":"677e1498-4b02-485d-8a81-1131b138112d","state":"completed","template":"skill:build-contract-project","objective":"Update the Pawn site: add an owner Setup page, add a keeper, and restyle the site to match the project's X account. Keep all existing functions.\n\nTHEME: pixel-art pawn shop at night. Deep green background (#173b32 to #0d2619), gold accents (#e0b14c, #f6d27a), cream text (#f2e8d0). Mascot: an original pixel frog pawnbroker in a green eyeshade with a gold jeweler's loupe over one eye, wearing a green jacket with a gold bow tie, and the pawnbroker's three gold balls above him. Draw him as inline SVG pixel art and use him in the header and as the favicon. Pixel-style display font for headings, clean body text. Buttons gold on green. Mobile-first.\n\nSETUP PAGE (visible to the owner wallet; each step shows done or pending from chain state)\n- Top: every deployed contract by name, address and Etherscan link.\n- Floor, one button flow: \"Request floor\" submits the oracle request from the browser through api.imd.fun with the x402 flow (Permit2 signature, 0.5 IMD from the connected wallet), using this exact question, public sources, within 5%, uint256, consumer = PawnShop on chain 1: \"What is the current floor price, in wei, of the identity.md NFT collection at 0x0000eC93127BAA929E58E97dd0095A2BFb38ec1D on Ethereum mainnet, defined as the lowest active listing on OpenSea or Blur at the time of answering? Answer as a uint256 in wei.\" The page polls until answered, verifies consumer and attester, then: if PawnShop has no questionHash for identity.md, prompts one transaction to set it from the attestation; then prompts one transaction to post the floor. Also accept a pasted request id instead of paying here, with the same checks, so a request bought elsewhere works.\n- Burn: one button sends 10,000,000 PAWN from the connected wallet to MilestoneBurn, showing the vault's balance. \"Request market cap\" runs the same request flow with consumer = MilestoneBurn and this question, public sources, within 5%, uint256: \"What is the fully diluted market cap of the PAWN token (0x4f2bacee5f2e7ce3f48dfbd635d96e9a8fcbe478, Ethereum mainnet), computed as total supply times the spot price from its Uniswap v4 ETH pool, converted to USD at the current ETH price? Answer as a uint256 in USD with 18 decimals.\" If MilestoneBurn has no questionHash, prompt one transaction to set it from the attestation. Show the latest attested market cap against the $1M target, and a Burn button that enables when an attestation qualifies. Pasted request ids accepted here too.\n- Open: Unpause button; deposit-cap field with Raise; Deposit ETH field for seeding the pool.\n- Claims: trading fees, bounty credits and protocol fees, one button each with the pending amount shown.\n- A \"Refresh floor\" button on the public Borrow page runs the same request-and-post flow for any wallet, since borrowers pay for their own refresh.\n\nKEEPER (keeper/ in the repo: Node, viem, MIT, hourly GitHub Actions workflow and cron example; config for RPC, addresses, oracle request ids; private key from env only). Hourly: fetch the latest attestations, post a floor when newer than stored, startAuction on overdue loans, call MilestoneBurn.burn() when an attestation qualifies. Skip actions whose bounty won't cover gas unless ALWAYS_RUN=true. Optional webhook or Telegram alerts: stale floor, oracle failed, auction started or stuck 3 days, queued owner change, low reserves, burn fired. README: run it in five minutes.\n\nRepublish the site under the same name.","blockedReason":null,"createdAt":"2026-10-08T14:43:55.533Z","updatedAt":"2026-10-08T15:09:28.412Z","paidBy":"0x23e5d7a7b4ea19530ec39c67cd46aa8c10d15acf","parentJobId":"8267708e-cdea-4a6b-9767-c37a4e87fbf6","project":{"id":"699b8539-76a2-4c37-b11e-ba4d269487ad","head":"c0f35007-65d3-45b3-8e39-4ea31424729e","running":null,"versions":[{"jobId":"699b8539-76a2-4c37-b11e-ba4d269487ad","workflowId":"b1df4c7c-4882-4f61-a69a-70ddecea3740","objective":"PAWN: the Pawn ($PAWN) token and five contracts on Ethereum mainnet. A pawn shop for identity.md seats: borrow ETH against a seat while it keeps working in the IMD swarm. Fixed-term loans, no liquidations: repay by the deadline or the seat is auctioned. Lenders earn loan fees behind a reserve. Locking PAWN lowers the fee. Name \"Pawn\", symbol \"PAWN\". Owner forwards claimed trading fees to LendingPool.donate(). X: @PawnIMD. No clarifying questions; sane defaults, documented. Percentages in bps.\n\nOWNER: 0x23e5d7a7b4ea19530ec39c67cd46aa8c10d15acf, Ownable2Step everywhere. Only the powers listed; lender-affecting changes wait 48h; no owner function moves pool ETH, NFTs, proceeds, reserves, locked PAWN or the burn vault.\n\nCONTRACTS (Solidity 0.8.26, Foundry, OpenZeppelin, no proxies, reentrancy guards, ETH owed is pulled via claim(), rounding favors the pool)\n\n1. CollateralVault (EIP-1167 clone per loan, initialized once by PawnShop, onERC721Received). Holds one NFT. ERC-1271 isValidSignature: only for isSeat collections, returns the magic value ONLY for an IMD WorkerAuthorization EIP-712 digest {deviceKey, wallet, tokenId, nonce, expiresAt, relayOrigin} the borrower registered via authorizeWorker(message); any other hash fails. callFor(target, data): borrower only, loan active, no value, for claiming rewards; reverts if target is the collection, PawnShop, LendingPool or the vault, or if the vault no longer owns the NFT after. Borrower can withdraw ETH/ERC-20 in the vault; the NFT leaves only via PawnShop.\n\n2. PawnShop. Terms: 0 = 30 days, 300 bps; 1 = 7 days, 100 bps; owner can queue terms (7-90 days, 50-1000 bps), live after 48h; open loans never change; min loan 0.01 ETH. Collections: per collection max loan per term (bps of floor, 0 disables), max share of pool totalAssets (bps), floor questionHash, isSeat; hard limits max loan 4000 bps, non-seat share 2500 bps; constructor registers identity.md 0x0000eC93127BAA929E58E97dd0095A2BFb38ec1D (isSeat, 4000 each term, share 10000); owner queues additions or changes (48h), can disable a collection's new loans at once; a zero questionHash is settable once. New loans start paused. pawn(collection, tokenId, termId): NFT into a new vault, lend up to the term's share of the floor in ETH; fee after discount deducted upfront; module records the PAWN committed; repay full principal; reverts if share exceeded or idle ETH short. repay/extend any time until an auction starts; extend pays the chosen term's fee after discount and pushes the due date out by the term; repay and auction settlement call release(loanId) on the module. Fees: 85% to LendingPool, 15% protocol, filling in order: bounty reserve to 0.2 ETH, pool shortfall reserve to 5% of totalAssets, then the fee recipient (owner at deploy, changeable after 48h). Discount module: LockDiscount at deploy, swappable after 48h; lower of module fee and term fee. Default: after due + 3-day grace, anyone calls startAuction for 0.002 ETH bounty; Dutch auction in ETH from the last stored floor (even stale) to 70% over 72h, then to 50% over 7 days, then holds; proceeds repay principal, surplus to borrower. Floor: anyone submits a signed IMD oracle attestation per collection (OracleAttestation v2, domain {\"IdentityMD Oracle\",\"2\",chainId 1,this contract}; pinned attester; collection questionHash; answerType uint256, wei; panelSize>=5; agreed>=4; not expired; issued within 26h; newer than stored); first valid per collection per 24h earns 0.001 ETH; no fresh floor = no new loans or extensions, repay and auctions always work. Attester: constructor arg per api.imd.fun; settable once if zero; changes 48h. Owner can only: pause/unpause new loans; queue terms, collections, parameters; set a zero questionHash or attester once; change attester, fee recipient or module after 48h; two-step transfer. Repay, withdraw, claim, unlock and auctions never pause.\n\n3. LendingPool. OpenZeppelin ERC-4626 over WETH 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, decimals offset, native ETH helpers; only PawnShop borrows and repays; withdrawals limited to idle assets. donate(): ETH from anyone, vested into the share price over 7 days. Shortfall reserve outside the share price absorbs auction gaps first. Deposit cap 10 ETH; owner can only raise it.\n\n4. LockDiscount (no owner). lock/unlock any time except PAWN committed to an open loan. Tiers by locked balance at pawn or extend: 2000 bps off at 1,000,000 PAWN, 3333 at 5,000,000, 5000 at 20,000,000. A discounted loan commits the tier amount; unlockable = locked minus the largest open commitment; release(loanId) from PawnShop drops it.\n\n5. MilestoneBurn (no owner, no withdrawal). Anyone sends PAWN in; burn(): anyone, on a signed IMD oracle attestation (same rules, own questionHash settable once) stating PAWN fully diluted market cap in USD 18 decimals >= 1,000,000e18, burns all to dEaD once.\n\nTESTS: Foundry unit, fuzz, invariant (mock ERC-721 in test/ only). DOCS: README with how it works, owner powers, risks, bounties, tiers, burn, oracle top-ups, addresses.\n\nWEBSITE (static, IPFS-ready, public RPC, Etherscan links, mobile-first, links x.com/PawnIMD). Shows: pitch, floor and age, pool vs cap, utilization, lender income, reserve, loans and auctions, terms and tiers, burn vault vs $1M, health, stats, risks, trade panel. Wallet can: buy/sell PAWN; pawn a seat (term, max, fee, due date, lock PAWN for a tier until the loan closes); repay; extend; lock/unlock; authorize a worker device (paste IMD pairing message); claim rewards, vault tokens, ETH; deposit/withdraw; buy or start auctions; post floor; trigger burn; owner: unpause, raise cap, queue changes, set hash/attester once, claim fees.","baseCommit":"0243d7da4a4337ae8b16bcdf15bb4ead736fd68f","state":"completed","createdAt":"2026-10-08T03:56:30.027Z"},{"jobId":"677e1498-4b02-485d-8a81-1131b138112d","workflowId":null,"objective":"Update the Pawn site: add an owner Setup page, add a keeper, and restyle the site to match the project's X account. Keep all existing functions.\n\nTHEME: pixel-art pawn shop at night. Deep green background (#173b32 to #0d2619), gold accents (#e0b14c, #f6d27a), cream text (#f2e8d0). Mascot: an original pixel frog pawnbroker in a green eyeshade with a gold jeweler's loupe over one eye, wearing a green jacket with a gold bow tie, and the pawnbroker's three gold balls above him. Draw him as inline SVG pixel art and use him in the header and as the favicon. Pixel-style display font for headings, clean body text. Buttons gold on green. Mobile-first.\n\nSETUP PAGE (visible to the owner wallet; each step shows done or pending from chain state)\n- Top: every deployed contract by name, address and Etherscan link.\n- Floor, one button flow: \"Request floor\" submits the oracle request from the browser through api.imd.fun with the x402 flow (Permit2 signature, 0.5 IMD from the connected wallet), using this exact question, public sources, within 5%, uint256, consumer = PawnShop on chain 1: \"What is the current floor price, in wei, of the identity.md NFT collection at 0x0000eC93127BAA929E58E97dd0095A2BFb38ec1D on Ethereum mainnet, defined as the lowest active listing on OpenSea or Blur at the time of answering? Answer as a uint256 in wei.\" The page polls until answered, verifies consumer and attester, then: if PawnShop has no questionHash for identity.md, prompts one transaction to set it from the attestation; then prompts one transaction to post the floor. Also accept a pasted request id instead of paying here, with the same checks, so a request bought elsewhere works.\n- Burn: one button sends 10,000,000 PAWN from the connected wallet to MilestoneBurn, showing the vault's balance. \"Request market cap\" runs the same request flow with consumer = MilestoneBurn and this question, public sources, within 5%, uint256: \"What is the fully diluted market cap of the PAWN token (0x4f2bacee5f2e7ce3f48dfbd635d96e9a8fcbe478, Ethereum mainnet), computed as total supply times the spot price from its Uniswap v4 ETH pool, converted to USD at the current ETH price? Answer as a uint256 in USD with 18 decimals.\" If MilestoneBurn has no questionHash, prompt one transaction to set it from the attestation. Show the latest attested market cap against the $1M target, and a Burn button that enables when an attestation qualifies. Pasted request ids accepted here too.\n- Open: Unpause button; deposit-cap field with Raise; Deposit ETH field for seeding the pool.\n- Claims: trading fees, bounty credits and protocol fees, one button each with the pending amount shown.\n- A \"Refresh floor\" button on the public Borrow page runs the same request-and-post flow for any wallet, since borrowers pay for their own refresh.\n\nKEEPER (keeper/ in the repo: Node, viem, MIT, hourly GitHub Actions workflow and cron example; config for RPC, addresses, oracle request ids; private key from env only). Hourly: fetch the latest attestations, post a floor when newer than stored, startAuction on overdue loans, call MilestoneBurn.burn() when an attestation qualifies. Skip actions whose bounty won't cover gas unless ALWAYS_RUN=true. Optional webhook or Telegram alerts: stale floor, oracle failed, auction started or stuck 3 days, queued owner change, low reserves, burn fired. README: run it in five minutes.\n\nRepublish the site under the same name.","baseCommit":"220319fe418655d9b37571024a45dd6a7f4e96c3","state":"completed","createdAt":"2026-10-08T14:43:55.533Z"},{"jobId":"c0f35007-65d3-45b3-8e39-4ea31424729e","workflowId":null,"objective":"Site update for Pawn.\n\nChange: owner controls (Setup page, Governance actions, claim buttons, unpause, cap, question hash, attester, queued changes) render only when the connected wallet is the contracts' owner. For everyone else, show the owner state read-only: paused or open, deposit cap, floor question hash set or not, and any queued changes with their countdowns. The public Refresh floor button stays available to all wallets. No other design or code changes; the Setup page, keeper and pixel theme are already merged in main (PR #2, commit 8422066).\n\nThen build web/ to dist/ and publish the site under the same name. Confirm the live site serves the new assets and the pixel frog favicon.","baseCommit":"842206640fc3725679893fba00fdc2f7a334fff8","state":"completed","createdAt":"2026-10-08T16:00:43.928Z"}]},"deliver":true,"host":false,"site":null,"launch":{"requested":false,"kind":null,"id":null,"status":null,"chainId":null},"oracleRequestId":null,"delivery":{"repoUrl":"https://github.com/identity-md-launches/launch-1031-workflow-frontend-stage-context","pullRequestUrl":"https://github.com/identity-md-launches/launch-1031-workflow-frontend-stage-context/pull/2","commit":"842206640fc3725679893fba00fdc2f7a334fff8","deliveredAt":"2026-10-08T15:09:52.963Z","media":null},"media":null,"nodes":[{"key":"build_contract_project","role":"implement","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":[],"allowedPaths":[],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-08T15:09:28.412Z","verdict":{"status":"accepted","profile":"foundry","evaluation":"checks","rejectionCode":null,"detail":"all checks passed","verifierVersion":"0.1.0+ad90ce4c","verifiedTreeHash":"c1026d0ab6a41e41c4e58c5713fd2bd7bbd72e2d","at":"2026-10-08T15:09:28.412Z","failedChecks":[]},"seat":{"tokenId":"1006","agentId":"51221"},"live":null}],"reviews":[{"status":"queued","chainId":1,"txHash":null,"blockNumber":null,"sentAt":null,"entries":[{"nodeKey":"build_contract_project","agentId":"51221","value":1,"role":"verification:checks"}]}]}