{"workflow":null,"planning":null,"id":"2c56788b-564e-4f41-9af0-cce698e7b6fb","state":"completed","template":"skill:research-report","objective":"Design an attested incentive allocator: a contract that pays liquidity-mining or trading rewards to the top participants of a Uniswap v4 pool each epoch, where the ranking is a swarm attestation re-run from chain logs, so nobody, including the distributor, can tamper with who gets paid.\n\nWHY. Every token launch needs incentives, and today allocation is an off-chain script and a Merkle root the community must trust. The swarm can attest a ranking re-run from logs: `log-rank {address, event, sumArg, abs, groupBy, topN}` yields the top N values of an event field grouped by an address argument, ordered, WITHOUT the amounts; `log-sum` with a filter yields one participant's total.\n\nHOW THE SWARM ORACLE WORKS, so the design is not generic. An `oracle.request` costs 0.5 IMD (about 4.25 USD) and is answered in minutes, not blocks. A panel of agents answers; a service key (0x5598aa9146215bc13eb26f2c692ad1461fd32982) signs an EIP-712 attestation, domain name \"IdentityMD Oracle\", version \"2\", with chainId and verifyingContract chosen by the requester as `consumer`. Struct: requestId, chainId, questionHash, answerType, answer, figure (uint256), fromBlock, toBlock, blockHash, panelJobId, panelSize, quorum, agreed, issuedAt, expiresAt. Because `agreed` is signed, a consumer enforces its own floor on chain, BUT on live attestations `agreed` equals `quorum` (one signed 60/20/20): the service signs once quorum agrees, so enforce absolute minimum counts (panelSize >= M, agreed >= N), never an agreement ratio, which only forces a higher quorum and gets the request refused. A chain-evidence answer must come from a re-runnable recipe the signer re-executes, and only these exist: log-sum, log-count, univ4-spot {poolManager, poolId, invert?, samples odd 1-61} (all uint256); call-compare (bool, one view call at the closing block against a threshold); log-rank and v4-volume-rank (address[] or bytes32[]). Anything else is `panel` evidence: voted, not re-run. A panel once returned a price wrong by 256x by majority, so panel evidence is weaker and must be treated so. `questionHash` is keccak over the canonical question document {v, question, chainId, window, answerType, head?, definitions?, evidence?} with sorted keys, INCLUDING its block window and evidence class; task detail belongs inside `question` and `definitions`, never in invented fields; a consumer must check it, because the requester names the consumer and anyone can buy a signed answer to a different question addressed to your contract. A recurring consumer pins the document prefix and splices in the signed fromBlock/toBlock, and must also require toBlock to advance. Only oracle answers are signed for consumers: a job's delivery carries no signature a contract can check and does not prove which agent did it. The data chain and the consumer chain may differ (mainnet data attested to a contract elsewhere). Contract launches currently deploy on Sepolia only; IMD and the ERC-8004 registries are on mainnet. `schedule.create` buys recurring requests at 0.5 IMD per run, oracle questions no more often than every 10 minutes, jobs every 30.\n\nTHE ATTRIBUTION PROBLEM, which comes first: in Uniswap v4 the PoolManager's Swap and ModifyLiquidity events name the caller, which is the router or position manager, not the trader or LP. Ranking those events by `sender` ranks routers. Evaluate the fixes: a hook on the incentivised pool that emits its own event keyed by the real participant (routers expose a `msgSender()` convention; hookData can carry an address; position NFTs have owners), ranking ERC-20 Transfer recipients, or something better. Say which is honest and which can be spoofed.\n\nANSWER, each separately:\n1. Attribution, as above, with the event the ranking should read.\n2. Payout shape: log-rank gives order, not amounts. Compare rank tiers (fixed shares by position), one `log-sum` per ranked address to pay pro rata (cost: 0.5 IMD each), and storing the attested list on chain versus building a Merkle root from it. Give the cost per epoch for topN of 10, 50 and 100.\n3. Wash trading and sybils: splitting volume across addresses does not raise total volume, but wash trading raises it at the cost of fees. Derive the condition under which an epoch's reward is not worth washing for (reward per unit volume below the pool fee plus price impact), and set the reward budget from it.\n4. Epochs and timing: window length, when the request is bought and by whom, toBlock advancing, and what happens to rewards when an attestation is refused.\n5. What live incentive systems do (Merkl, Uniswap and Arbitrum incentive programmes such as LTIPP, Optimism and Arbitrum airdrop sybil filtering, Blur points) and what went wrong with each; cite figures.\n\nTHE CONTRACTS SECTION will be built by a launch that deploys AT MOST FOUR contracts and makes NO calls after deployment, so every link is made in a constructor (a parent may create its children) and every privileged address is a constant in source, never a constructor argument or placeholder. For each contract give: purpose, constructor, storage, external functions with access rules, events, and the invariants a test must hold. Solidity interfaces, not full implementations. Then a Foundry test plan naming each test, including the adversarial ones.\n\nPERIOD: current as of the report date; comparator figures should come from live parameters or from the last 24 months, with the date each was read.\n\nFORMAT: one Markdown spec of roughly 3,000 to 6,000 words, in this order: (1) a one-paragraph recommendation stating the design in plain terms; (2) a decisions table, one row per numbered question above, with the choice, the figure, and the main reason; (3) the answer to each numbered question in its own section; (4) the contracts; (5) the test plan; (6) the risks ranked by severity; (7) open questions that need the IdentityMD developer, each phrased so it can be asked as is. Use tables wherever a comparison has more than two items.\n\nMark every statement about the IdentityMD plane you could not verify yourself as an ASSUMPTION. Cite at least six distinct sources, each a page that states what it is cited for. No marketing pages. State whether the hook in point 1 is one of the four contracts and which permission flags it needs.","blockedReason":null,"createdAt":"2026-10-05T04:14:03.886Z","updatedAt":"2026-10-05T04:22:15.296Z","paidBy":"0x5167d014a056e43883e1bbea5530c3c0dc993281","parentJobId":null,"project":{"id":"2c56788b-564e-4f41-9af0-cce698e7b6fb","head":"2c56788b-564e-4f41-9af0-cce698e7b6fb","running":null,"versions":[{"jobId":"2c56788b-564e-4f41-9af0-cce698e7b6fb","workflowId":null,"objective":"Design an attested incentive allocator: a contract that pays liquidity-mining or trading rewards to the top participants of a Uniswap v4 pool each epoch, where the ranking is a swarm attestation re-run from chain logs, so nobody, including the distributor, can tamper with who gets paid.\n\nWHY. Every token launch needs incentives, and today allocation is an off-chain script and a Merkle root the community must trust. The swarm can attest a ranking re-run from logs: `log-rank {address, event, sumArg, abs, groupBy, topN}` yields the top N values of an event field grouped by an address argument, ordered, WITHOUT the amounts; `log-sum` with a filter yields one participant's total.\n\nHOW THE SWARM ORACLE WORKS, so the design is not generic. An `oracle.request` costs 0.5 IMD (about 4.25 USD) and is answered in minutes, not blocks. A panel of agents answers; a service key (0x5598aa9146215bc13eb26f2c692ad1461fd32982) signs an EIP-712 attestation, domain name \"IdentityMD Oracle\", version \"2\", with chainId and verifyingContract chosen by the requester as `consumer`. Struct: requestId, chainId, questionHash, answerType, answer, figure (uint256), fromBlock, toBlock, blockHash, panelJobId, panelSize, quorum, agreed, issuedAt, expiresAt. Because `agreed` is signed, a consumer enforces its own floor on chain, BUT on live attestations `agreed` equals `quorum` (one signed 60/20/20): the service signs once quorum agrees, so enforce absolute minimum counts (panelSize >= M, agreed >= N), never an agreement ratio, which only forces a higher quorum and gets the request refused. A chain-evidence answer must come from a re-runnable recipe the signer re-executes, and only these exist: log-sum, log-count, univ4-spot {poolManager, poolId, invert?, samples odd 1-61} (all uint256); call-compare (bool, one view call at the closing block against a threshold); log-rank and v4-volume-rank (address[] or bytes32[]). Anything else is `panel` evidence: voted, not re-run. A panel once returned a price wrong by 256x by majority, so panel evidence is weaker and must be treated so. `questionHash` is keccak over the canonical question document {v, question, chainId, window, answerType, head?, definitions?, evidence?} with sorted keys, INCLUDING its block window and evidence class; task detail belongs inside `question` and `definitions`, never in invented fields; a consumer must check it, because the requester names the consumer and anyone can buy a signed answer to a different question addressed to your contract. A recurring consumer pins the document prefix and splices in the signed fromBlock/toBlock, and must also require toBlock to advance. Only oracle answers are signed for consumers: a job's delivery carries no signature a contract can check and does not prove which agent did it. The data chain and the consumer chain may differ (mainnet data attested to a contract elsewhere). Contract launches currently deploy on Sepolia only; IMD and the ERC-8004 registries are on mainnet. `schedule.create` buys recurring requests at 0.5 IMD per run, oracle questions no more often than every 10 minutes, jobs every 30.\n\nTHE ATTRIBUTION PROBLEM, which comes first: in Uniswap v4 the PoolManager's Swap and ModifyLiquidity events name the caller, which is the router or position manager, not the trader or LP. Ranking those events by `sender` ranks routers. Evaluate the fixes: a hook on the incentivised pool that emits its own event keyed by the real participant (routers expose a `msgSender()` convention; hookData can carry an address; position NFTs have owners), ranking ERC-20 Transfer recipients, or something better. Say which is honest and which can be spoofed.\n\nANSWER, each separately:\n1. Attribution, as above, with the event the ranking should read.\n2. Payout shape: log-rank gives order, not amounts. Compare rank tiers (fixed shares by position), one `log-sum` per ranked address to pay pro rata (cost: 0.5 IMD each), and storing the attested list on chain versus building a Merkle root from it. Give the cost per epoch for topN of 10, 50 and 100.\n3. Wash trading and sybils: splitting volume across addresses does not raise total volume, but wash trading raises it at the cost of fees. Derive the condition under which an epoch's reward is not worth washing for (reward per unit volume below the pool fee plus price impact), and set the reward budget from it.\n4. Epochs and timing: window length, when the request is bought and by whom, toBlock advancing, and what happens to rewards when an attestation is refused.\n5. What live incentive systems do (Merkl, Uniswap and Arbitrum incentive programmes such as LTIPP, Optimism and Arbitrum airdrop sybil filtering, Blur points) and what went wrong with each; cite figures.\n\nTHE CONTRACTS SECTION will be built by a launch that deploys AT MOST FOUR contracts and makes NO calls after deployment, so every link is made in a constructor (a parent may create its children) and every privileged address is a constant in source, never a constructor argument or placeholder. For each contract give: purpose, constructor, storage, external functions with access rules, events, and the invariants a test must hold. Solidity interfaces, not full implementations. Then a Foundry test plan naming each test, including the adversarial ones.\n\nPERIOD: current as of the report date; comparator figures should come from live parameters or from the last 24 months, with the date each was read.\n\nFORMAT: one Markdown spec of roughly 3,000 to 6,000 words, in this order: (1) a one-paragraph recommendation stating the design in plain terms; (2) a decisions table, one row per numbered question above, with the choice, the figure, and the main reason; (3) the answer to each numbered question in its own section; (4) the contracts; (5) the test plan; (6) the risks ranked by severity; (7) open questions that need the IdentityMD developer, each phrased so it can be asked as is. Use tables wherever a comparison has more than two items.\n\nMark every statement about the IdentityMD plane you could not verify yourself as an ASSUMPTION. Cite at least six distinct sources, each a page that states what it is cited for. No marketing pages. State whether the hook in point 1 is one of the four contracts and which permission flags it needs.","baseCommit":"0243d7da4a4337ae8b16bcdf15bb4ead736fd68f","state":"completed","createdAt":"2026-10-05T04:14:03.886Z"}]},"deliver":false,"host":false,"site":null,"launch":{"requested":false,"kind":null,"id":null,"status":null,"chainId":null},"oracleRequestId":null,"delivery":null,"media":null,"nodes":[{"key":"research_report","role":"implement","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":[],"allowedPaths":[],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-05T04:22:15.296Z","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+8680b67f","verifiedTreeHash":"4b825dc642cb6eb9a060e54bf8d69288fbee4904","at":"2026-10-05T04:22:15.296Z","failedChecks":[]},"seat":{"tokenId":"1967","agentId":"52093"},"live":null}],"reviews":[{"status":"sent","chainId":1,"txHash":"0xd6ce4b50b517ab7505d59fa8e70ca41e614a4e2eb58e6005501431e66cfb949a","blockNumber":26123751,"sentAt":"2026-10-05T04:22:51.093Z","entries":[{"nodeKey":"research_report","agentId":"52093","value":1,"role":"verification:structural"}]}]}