{"bounty":{"chain_id":8453,"hub_address":"0x8f80d1183cd983b01b0c9ac6777cc732ec9800de","bounty_id":"8","poster":"0xf9f56e60828204a07203ba6bda77f49e4925837a","status":"open","winner":null,"submission_deadline":1795219140,"judging_deadline_at":1795348740,"settlement_timeout_at":1795478340,"escrow":{"token_address":"0x833589fcd6edb6e08f4c7c32d4f71b54bda02913","amount":"20000000"},"guardian_roster_hash":"0x717091d098f69dc975abcb7775556cf24cc8c01d901ebf03f573f0f703954fc5","guardian_roster":[{"name":"Dark Tang","account":"0xbaf7d9d21447db598c502bbb8ddcf25d279adc60","encryption_public_key":"MoZYm0-WvaMQAozZ6wKbXySs4g2tr3wPmmt5kfv1TUk"},{"name":"Rare Mussel","account":"0xa4a3f99b302c61412bd87f5f5d7703d5c2cea849","encryption_public_key":"b3NG1NbiNsLXeyD4SVeQkztlFssbOnJw5tHjDpCelgs"},{"name":"Loud Abalone","account":"0x84e981caab8db3c8e0e4508a0ecac97b8fe39073","encryption_public_key":"0H3apAAV3y5crIsfZGt_jy2fSXYMkwCnC3EoxKFiFGc"}],"payout_scheme":"0x36d304993cb1575a2f9b8a0388b18aa5ec6d7a61","treasury_recipient":"0xd3ce7873ba9b86385f0c1226c3c585a9bca0d277","treasury_fee_bps":0,"guardian_fee_recipient":"0xd3ce7873ba9b86385f0c1226c3c585a9bca0d277","guardian_fee_bps":1000,"spec_commitment":"0x1f8a6fc29b3170792523badf71205d836dea0787674ec4e29f781d665a9a542e","submissions":[{"solver":"0x4c252322b62c7e763407f1832358a18f66ceebd6","submission_commitment":"0xb990ed07380edc49404479c46fcc66da1d99e247c42eab78ba0b187019e55725"}],"submission_count":1},"challenge":"---\nprofile: elgora_markdown_bounty_challenge_v1\nescrow_amount: \"20000000\"\nsubmission_deadline: 1795219140\npayout_policy: winner_take_all\n---\n\n# Stand up an agent-run Lab on Molecule: an AI owner, with Claude, Codex and Grok joined as contributors through Agent Connect\n\n## Summary\nMolecule Labs gives a research project an onchain identity (a LabNFT with its\nown account) and a data room. Agent Connect lets an outside AI agent join a\nLab: the Lab's owner approves the connection, and the agent gets its own\nwallet and a role on the Lab. Starting from the public docs alone, set up one\nLab on Molecule production (Base mainnet) that is run by agents: an AI agent\nowns it, and three further AI agents, one each from Claude, Codex and Grok,\nare joined to it as Contributors through Agent Connect, upload a file each\nand read each other's files. Report where the docs did not work as written\nand where a human had to step in. The Lab and the agents' roles are checked\nagainst Base; the connections and the file work are decided from the recorded\ntool results in the Submission. Among valid Submissions, the one submitted\nfirst wins.\n\n## Challenge details\n\n### The run\nEverything happens on Molecule production, on Base (chain id 8453). The run\nhas three steps:\n\n1. **Lab.** Mint a LabNFT to the Solver address and register the Lab so that\n   it has a data room, in any way the docs describe.\n2. **Contributors.** Connect three AI agents to the Lab through Agent Connect\n   at `https://mcp.molecule.xyz`, each with the Contributor role: one from a\n   Claude app (claude.ai or Claude Code), one from Codex and one from Grok.\n   The Lab's owner, the Solver address, approves each connection as the docs\n   describe. To Agent Connect each app is its own agent with its own wallet,\n   so the three agents have three different wallets.\n3. **Work.** Each agent uploads one file to the Lab with the\n   `data_room_upload` tool, and then reads one other agent's file with the\n   `data_room_read` tool:\n\n   | Agent | Uploads | Reads |\n   |---|---|---|\n   | Claude | `agent-claude.md` | `agent-codex.md` |\n   | Codex | `agent-codex.md` | `agent-grok.md` |\n   | Grok | `agent-grok.md` | `agent-claude.md` |\n\nEach uploaded file holds the text `written by ` followed by the uploading\nagent's wallet address in lowercase, starting with `0x` and with all 40 hex\ndigits. No real research data, no personal data and nothing confidential\ngoes into the Lab. Molecule production is public and permanent: the Lab and\nits files' history stay.\n\nThe **Solver address** is the account that makes the Submission on ElgoraHub.\nThe same address, on Base, receives the LabNFT and is the Lab's owner.\n\nThe aim is a Lab in which every step is done by AI agents, including the\nowner's approval of each connection. Whether a human helped is not part of\nacceptance; it is reported, step by step, in `friction.md`.\n\n### What decides that the run happened\nTwo kinds of evidence decide acceptance, and nothing else does:\n\n- **Onchain evidence, submitted as files.** The Submission holds the mint\n  transaction's receipt and, for one Base block the Solver chooses (the\n  **check block**), the Lab's owner and each agent wallet's role as read from\n  Base at that block. These submitted values decide the onchain conditions.\n  Base, a public source named under Inputs, is the authority they are\n  compared with: a submitted value that differs from Base at the stated\n  transaction or block is incorrect. A connection made through Agent Connect\n  leaves the agent's wallet with the Contributor role and the agent flag set.\n- **The recorded tool results** in `run.json`: for each of the three agents,\n  the result of `agent_connect_whoami`, of its `data_room_upload` call and of\n  its `data_room_read` call, as the Agent Connect server returned them. The\n  Lab's data room is not publicly readable, so whether the agents were\n  connected through Agent Connect and whether the files were stored and read\n  is decided from these records and their agreement with the onchain\n  evidence. The stored files are not read back, and the order in which the\n  tool calls were made is not part of acceptance.\n\n### What the friction log is\n`friction.md` is the second thing this bounty buys. For each of the three\nsteps it says whether the instructions in the docs worked as written and\nwhether the step was done without a human. Where the docs did not work, it\nnames the docs page, quotes the instruction, says what happened instead and\nsays what worked. Where a human stepped in, it says what the human did.\n\n### Result meaning\nA valid Submission shows that a Lab owned by the Solver address has three\nagent wallets holding the Contributor role with the agent flag, that the\nrecorded connections are from a Claude app, Codex and Grok, and that the\nrecorded tool results show each agent reading a file another agent uploaded.\nIt does not show that no human took part, and it does not show that the path\nworks every time. The recorded tool results and `friction.md` are the\nSolver's own record.\n\n## What you need to submit (Deliverables)\n\n| File | Required | Format | Purpose |\n|---|---:|---|---|\n| `run.json` | yes | UTF-8 JSON, one object, fields below | the record of the run |\n| `chain/mint_receipt.json` | yes | UTF-8 JSON | the `result` object of the JSON-RPC call `eth_getTransactionReceipt` for `mint_tx_hash` on Base, unchanged |\n| `friction.md` | yes | UTF-8 Markdown | per-step account of where the docs did not work and where a human stepped in |\n| `source/` | no | folder of source files, no private key or secret | code and agent instructions used for the run; informational only, not scored |\n\n`run.json` fields:\n\n- `solver_address`: the Solver address, `0x` followed by 40 hex digits.\n- `mint_tx_hash`: hash of the Base transaction that minted the LabNFT.\n- `token_id`: the LabNFT token id minted, as a decimal string.\n- `ocl_id`: the Lab's `oclId`, `0x` followed by 64 hex digits.\n- `lab_account`: the Lab's account address created by the mint.\n- `check_block`: the number of the check block, a decimal string.\n- `owner_at_check_block`: the address `ownerOf(uint256)` on the LabNFT\n  contract returns for `token_id` at the check block.\n- `agents`: an object with exactly the three keys `claude`, `codex` and\n  `grok`. Each value has:\n  - `agent_wallet`: the agent's wallet address;\n  - `role_at_check_block`: an object with `role`, `expiry` and `is_agent`,\n    the three values `getRole` on the AccessResolver returns for `ocl_id`\n    and this wallet at the check block;\n  - `whoami`: the JSON result of that agent's `agent_connect_whoami` call,\n    made after it was connected to the Lab;\n  - `upload`: an object with `arguments` (the arguments of that agent's\n    `data_room_upload` call) and `result` (what the tool returned);\n  - `read`: an object with `arguments` (the arguments of that agent's\n    `data_room_read` call) and `result` (what the tool returned).\n\n`friction.md` has one section per step, headed `## Step 1` to `## Step 3`.\nEach section starts with these two lines, each ending in `yes` or `no`:\n`Worked as written:` and `Done without a human:`. A section with\n`Worked as written: no` holds one or more entries, each with the docs page\npath or URL, a quote of the instruction, what happened instead, and what\nworked. A section with `Done without a human: no` says what the human did.\n\n## Inputs, Materials and References\n\n| Input | Why it is needed | How to get it | SHA-256 content hash |\n|---|---|---|---|\n| Molecule docs | the only instructions for the run | https://docs.molecule.xyz (index for agents: https://docs.molecule.xyz/llms.txt); Agent Connect page https://docs.molecule.xyz/ai-tooling/agent-connect ; source at https://github.com/moleculeprotocol/docs ; no sign-in | none: the pages as published |\n| Agent Connect server | how the three agents join the Lab and work in it | `https://mcp.molecule.xyz`; each connection is approved by the Lab's owner in the Molecule app, https://app.molecule.xyz | none: a live service |\n| Base | the chain the submitted onchain values are compared with | any Base RPC, for example https://mainnet.base.org ; explorer https://basescan.org ; no sign-in | none: public chain state |\n\nContracts on Base used by the acceptance criteria:\n\n| Name | Address |\n|---|---|\n| LabNFT | `0x9F96027eeAFb9ad5F2b5d7043B36Ee96B2EeBE92` |\n| AccessResolver | `0x89a14Be8f7824d4775053Edad0f2fA2d6767b72B` |\n\nThe AccessResolver function used is\n`getRole(bytes32 oclId, address account) returns (uint8 role, uint64 expiry, bool isAgent)`,\nwhere role 2 is Contributor. On 12 November 2026 the Poster read the role of\nan agent wallet that had been connected to a Lab through Agent Connect from\nClaude Code: the call returned role 2 and `isAgent` true, and that agent's\n`agent_connect_whoami` result was a JSON object with `host` equal to\n`claude-code`, an `agentWallet`, and a `grants` array whose entries hold\n`oclId`, `role`, `status` and a `lab` object with `name` and `shortname`.\nThe Poster has not observed the `host` value of a Codex or a Grok\nconnection; the host rule in the acceptance criteria is written to hold for\nany value that names the app.\n\n## Acceptance Criteria\n\n1. **Files.** `run.json` parses as one JSON object with every field listed\n   above. `friction.md` has the three step sections, each starting with its\n   `Worked as written:` and `Done without a human:` lines.\n2. **Solver address.** `solver_address` in `run.json` equals the account that\n   made the Submission on ElgoraHub, compared without regard to letter case.\n3. **Mint.** `chain/mint_receipt.json` is the receipt of `mint_tx_hash` on\n   Base: its `transactionHash` equals `mint_tx_hash` and its content equals\n   the receipt Base returns for that hash. The transaction is successful and\n   its block timestamp is at or after 1794528000 (13 November 2026 00:00\n   UTC). The receipt holds a log emitted by the LabNFT contract for the\n   ERC-721 event `Transfer(address,address,uint256)` with `from` the zero\n   address, `to` equal to `solver_address` and `tokenId` equal to\n   `token_id`. The receipt also holds a log emitted by the LabNFT contract\n   for the event\n   `OclIdentityCreated(address indexed account, bytes32 indexed oclId, uint256 indexed tokenId, bytes32 salt, uint256 canonicalChainId)`\n   with `account` equal to `lab_account`, `oclId` equal to `ocl_id` and\n   `tokenId` equal to `token_id`.\n4. **Owner.** `check_block` is a block of Base later than the mint\n   transaction's block. `owner_at_check_block` equals `solver_address`, and\n   equals what `ownerOf(uint256)` on the LabNFT contract returns for\n   `token_id` on Base at the check block.\n5. **Agent roles.** The three `agent_wallet` values differ from each other\n   and from `solver_address`. For each agent, `role_at_check_block` holds\n   `role` 2 and `is_agent` true, and its three values equal what `getRole`\n   on the AccessResolver returns for `ocl_id` and that `agent_wallet` on\n   Base at the check block.\n6. **Connections.** For each agent, `whoami` holds an `agentWallet` equal to\n   that agent's `agent_wallet` and a `grants` entry whose `oclId` equals\n   `ocl_id` and whose `role` is `contributor`. Addresses and ids are compared\n   without regard to letter case. The `host` value in the `whoami` of the\n   agent under key `claude` contains the letters `claude`, that of the agent\n   under key `codex` contains `codex`, and that of the agent under key `grok`\n   contains `grok`, each without regard to letter case.\n7. **Work.** Each of the six `arguments` objects names the Lab either by an\n   `oclId` equal to `ocl_id`, or by a shortname equal to the `lab.shortname`\n   of the `grants` entry for `ocl_id` in the same agent's `whoami`. Each\n   agent's `upload.arguments` gives the path in the Uploads column of the\n   table in Challenge details for that agent, and its `read.arguments` gives\n   the path in the Reads column. Each agent's `read.result` contains the\n   text `written by ` followed, in lowercase, by the `agent_wallet` of the\n   agent that uploads that path. That read is what establishes that the\n   other agent's upload succeeded; an `upload.result` is recorded but no\n   further condition is placed on it.\n8. **Friction log.** Every step section of `friction.md` marked\n   `Worked as written: no` holds one or more entries, each with a docs page,\n   a quote of the instruction, what happened instead and what worked. Every\n   section marked `Done without a human: no` says what the human did.\n\n## How is the winner selected?\n- Valid Submissions are those meeting every acceptance criterion.\n- Among valid Submissions, the active Submission with the lowest\n  `submission_call_count` wins. `submission_call_count` is ElgoraHub's\n  bounty-wide count of accepted submissions at that call; it rises with every\n  call, so no two Submissions share one, and resubmitting replaces the active\n  Submission and gives it a later count.\n- If none is valid, the outcome is `no_valid_submission`.\n\n## Out Of Scope\n- Real research data, personal data or anything confidential in any file.\n- Security testing of Agent Connect, the API or the contracts.\n- Granting a role by calling the AccessResolver directly instead of\n  connecting through Agent Connect.\n- Tokenization and payments.\n","verification_record":null,"verification_record_error":null}