# ERC-8458: Agent Income Statements

> Robinhood Chain testnet (46630). Test tokens, no value. Reference contracts not audited. These are drafts under review, not standards.

A draft under review on ethereum/ERCs. Public, chained statements of what an agent's ERC-8004 agentWallet received, one leaf per transfer, rebuildable from token logs.

Status: Testnet only.

- Pull request: https://github.com/ethereum/ERCs/pull/2102
- Text pinned at the pull request's head commit 9eea7ceae2a053a2212e5a272380bc16a9324b53 (ERCS/erc-8458.md, CC0): https://github.com/priors-agents/ERCs/blob/9eea7ceae2a053a2212e5a272380bc16a9324b53/ERCS/erc-8458.md
- Discussion: https://ethereum-magicians.org/t/erc-8458-agent-income-statements/30047
- Reference implementation: https://github.com/priors-agents/erc-agent-income-statements/tree/56820aa790e0d852cf4eee3d36bef03e52d23a6e (commit 56820aa790e0d852cf4eee3d36bef03e52d23a6e)
- This page: https://lab.priors.trade/erc/8458

## Abstract

This proposal defines public income statements for agents of [ERC-8004](https://eips.ethereum.org/EIPS/eip-8004), carried on its Reputation Registry. A statement commits, with a Merkle root, to the incoming transfers of one [ERC-20](https://eips.ethereum.org/EIPS/eip-20) token to the agent's ERC-8004 `agentWallet` over a window of log positions, with each transfer as its own leaf. One writer's statements about one agent are chained by hash over back-to-back windows, and the agent's owner can name, in the agent's ERC-8004 metadata, the writer readers read first. Anyone can rebuild every leaf and total from the token's own logs and the identity registry's, and an optional verifier contract checks one transfer against a statement's root on chain.

Statements are ordinary `giveFeedback` entries, with `tag1` set to `revenues`, the tag ERC-8004 gives as its example of cumulative revenues, and `tag2` set to `x402.statement`. An entry's value is the cumulative total through the end of its window, and its file, carried in the entry itself, is the evidence. x402 payments, which settle as a token transfer to the address an agent names as its `payTo`, are the motivating case. A token log cannot show how a transfer was settled, so a statement counts every incoming transfer except mints, transfers of nothing and the agent's own, and calls the total income, not x402 revenue.

## Specification headings

1. Terms
2. Entries
3. Windows
4. Payments
5. Encoding
6. Leaves
7. Statement file
8. Writers
9. Named writer
10. Readers
11. Verifier

## At Priors

Nothing at Priors runs this draft. Its reference contracts go on the testnet only.

## Try it on testnet (46630)

Every action is prepared as an unsigned transaction { chainId: 46630, to, data, value }, signed by your own wallet or testnet key. Test tokens have no value.

Contracts:

- incomeVerifier: 0x16002AbFB325ffd814b91C985164Efb62Af4B838 (https://explorer.testnet.chain.robinhood.com/address/0x16002AbFB325ffd814b91C985164Efb62Af4B838)
- reputationRegistry: 0x8004B663056A597Dffe9eCcC1965A193B7388713 (https://explorer.testnet.chain.robinhood.com/address/0x8004B663056A597Dffe9eCcC1965A193B7388713)
- testDollar: 0x64A419191369E6a79d562A65336073ec1bfbf4BD (https://explorer.testnet.chain.robinhood.com/address/0x64A419191369E6a79d562A65336073ec1bfbf4BD)

Actions:

- `prove_payment`: Prove one payment against a statement's root. Who signs: anyone (a lender or buyer agent) Params: `root` (The statement's Merkle root, bytes32), `proof` (The proof: 0x hashes separated by commas (empty when the statement holds one payment; the payments read gives it), bytes32s, optional, default ), `payment_chain` (The payment's chain id, uint, optional, default 46630), `asset` (The token paid (empty: the lab's test dollar), address, optional, default (the lab's)), `agent_id` (The paid agent's identity, agentId), `owner` (The agent's owner when paid, address), `payer` (Who paid, address), `pay_to` (The address paid (the agentWallet), address), `amount` (The amount, in the token's base units, uint), `paid_at` (When it was paid (unix seconds), uint), `tx_hash` (The payment's transaction hash, bytes32), `log_index` (The Transfer log's index, uint).
- `post_statement`: Post an income statement (writer). Who signs: the statement's writer Params: `agent_id` (The agent, agentId), `value` (The statement's value (cumulative income, base units), uint), `value_decimals` (The value's decimals, uint, optional, default 6), `feedback_uri` (The statement file's data: URI, string), `feedback_hash` (keccak256 of the file, bytes32).

Reads:

- `verify_payment`: Check a payment against a root (no transaction). Params: `root` (The statement's Merkle root, bytes32), `proof` (The proof: 0x hashes separated by commas (empty when the statement holds one payment; the payments read gives it), bytes32s, optional, default ), `payment_chain` (The payment's chain id, uint, optional, default 46630), `asset` (The token paid (empty: the lab's test dollar), address, optional, default (the lab's)), `agent_id` (The paid agent's identity, agentId), `owner` (The agent's owner when paid, address), `payer` (Who paid, address), `pay_to` (The address paid (the agentWallet), address), `amount` (The amount, in the token's base units, uint), `paid_at` (When it was paid (unix seconds), uint), `tx_hash` (The payment's transaction hash, bytes32), `log_index` (The Transfer log's index, uint).
- `leaf_hash`: A payment's leaf hash. Params: `payment_chain` (The payment's chain id, uint, optional, default 46630), `asset` (The token paid (empty: the lab's test dollar), address, optional, default (the lab's)), `agent_id` (The paid agent's identity, agentId), `owner` (The agent's owner when paid, address), `payer` (Who paid, address), `pay_to` (The address paid (the agentWallet), address), `amount` (The amount, in the token's base units, uint), `paid_at` (When it was paid (unix seconds), uint), `tx_hash` (The payment's transaction hash, bytes32), `log_index` (The Transfer log's index, uint).
- `statements`: A writer's income statements for an agent (testnet). Params: `agent_id` (The agent, agentId), `writer` (The writer (empty: the lab writer), address, optional, default (the lab's)).
- `payments`: The payments in an agent's latest income statement from a writer, each with its proof for verify_payment and prove_payment (testnet). Params: `agent_id` (The agent, agentId), `writer` (The writer (empty: the lab writer), address, optional, default (the lab's)), `statement_tx` (The statement's transaction (empty: the writer's latest), bytes32, optional).

Deploy your own:

- `verifier`: Your own IncomeStatementVerifier. No params.

## With an agent

- MCP (Streamable HTTP): https://lab.priors.trade/mcp. Tools for this draft: `lab_erc(8458)`, `lab_setup(address)`, `lab_read(8458, read, params)`, `lab_prepare(8458, action, params)`, `lab_deploy_prepare(8458, deploy, params)`, `lab_check_contract(8458, chain, address)`, `lab_feedback_draft(8458, note, txHash?)`.
- HTTP: https://lab.priors.trade/openapi.json describes GET https://lab.priors.trade/api/lab/erc/8458, /api/lab/read/8458/{read}, /api/lab/prepare/8458/{action}, /api/lab/deploy/8458/{deploy}, /api/lab/check/8458/{chain}/{address} and /api/lab/setup/{address}.

A prompt to give your agent:

```text
Use the Priors lab on Robinhood Chain testnet (chain id 46630), where every token is a test token of no value. Its MCP server is https://lab.priors.trade/mcp and this draft's page is https://lab.priors.trade/erc/8458.md. Try ERC-8458, Agent Income Statements (a draft under review). Start with lab_setup for my testnet address to see my test ETH, test dollars and identities, then prove one payment against a statement's root, then post an income statement (writer), then your own incomestatementverifier with lab_prepare(8458, <action>, params). Each prepare returns an unsigned transaction { chainId: 46630, to, data, value }: sign and send it yourself with a testnet key, and refuse any other chain. Never ask me for a key. After each transaction, read the result back with lab_read and tell me what changed. If the draft or its reference code looks wrong, draft a report with lab_feedback_draft.
```

## Check a contract

Any address on testnet or mainnet: supportsInterface(0xcc3df75f) and the views, read only (`lab_check_contract`, or GET https://lab.priors.trade/api/lab/check/8458/{chain}/{address}).

## Feedback

The discussion of the text belongs in its thread: https://ethereum-magicians.org/t/erc-8458-agent-income-statements/30047. A bug in the reference implementation goes to its repository's issues: https://github.com/priors-agents/erc-agent-income-statements/issues (a new one: https://github.com/priors-agents/erc-agent-income-statements/issues/new). The text under review: https://github.com/ethereum/ERCs/pull/2102/files. `lab_feedback_draft` writes the report; the lab posts nothing for anyone.
