What a fund would do
The proposal would let the owner of an AI agent give a small, fixed share of what the agent spends to a humanitarian fund, at a rate and monthly cap the owner sets in advance. Each share would become one line in a public log, kept by whoever handled the payment, and each month the log would publish a signed statement over its lines. On x402, the payment protocol the draft extension is written for, shares are paid in stablecoins and the log is kept by the facilitator, the service that settles the payment. On card and bank rails and custodial agent wallets, it is kept by the processor, the party that holds the owner's payment credential or funds. This page is for finance and programme staff at a pooled fund or an innovation office. It sets out the fund's side: what would arrive, what the fund would need and publish, what it would check before signing off each month, what it must not do, what it could refuse, and what it would never have to do. Each point links to the section of the draft specification it comes from. Where this page and the specification differ, the specification is right.
- A proposal, not a program. It is a draft specification for discussion. No fund exists for it.
- No money moves. Not on this site, and not anywhere else under this proposal.
- Every fund address in the specification is a placeholder, such as the account ending in
f00dorfund.example. - Not affiliated with the UN. Nothing here is affiliated with, endorsed by or run by the United Nations or any of its funds or offices, the x402 project, or any company.
What would reach the fund
Money, with a reference for each payment that the fund can check. On x402 the specification forbids sending a fund any record of who bought what; on every rail, published lines carry no owner, seller or item.
One payout a month from each processor's log
The processor would collect owners' shares in aggregate and pay each fund once a month. Each payout is listed with a reference, written payout:<reference>, that no other log paying the fund uses (for example, one that starts with the log's domain name) and that the fund can match in its own records.
How a processor collects and pays, in aggregate and once a month, comes from processor mode, which the specification marks as informative: suggestions, not rules. The payout reference, and everything the processor's log publishes, follow the normative attestation document, like any other log.
Source: processor-mode.md, “Processor mode” and “The processor's log” (informative); attestation.md, “Settlement references”Transfers and claims, each with its own reference
An exact share is a single on-chain transfer to the fund's address, one per share, and its transaction is its reference. A log may also use batch-settlement: the owner sets aside a deposit on chain in a payment channel whose receiver is the fund, and the log gathers many small shares into a few claims on it. Each claim's transaction and channel are its reference.
A claim counts as having reached the fund when it is made on chain. The claimed money is moved into the fund's account later by a sweep, which can carry claims from many logs at once and which anyone may make, the fund included.
Source: solidarity.md, “Share kinds”; attestation.md, “Optional share kind: batch-settlement”A statement and a settlements file
Each log would publish a statement for each month with its totals, one row per fund and asset (a currency or a token), and a settlements file listing every payment behind those totals with its reference and amount. The amounts listed for a fund add up to its row.
Source: attestation.md, “Statements” and “Settlement references”The full amount of every share
A log must not deduct its costs from shares, so totals are gross. The informative processor-mode document adds that on stablecoin rails the log operator pays the network fees for transfers, claims and sweeps. Whether a log may instead disclose and deduct a fee is one of the open questions.
Source: attestation.md, “Statements”; processor-mode.md, “Fees” (informative)What the published records leave out: who bought what. On x402, a log must not send a fund anything about purchases: the fund learns only what the log publishes. The informative processor-mode document has no matching rule for processor mode. On every rail, published lines carry no owner, no seller and no item. Two honest limits: a line's amount still shows how large the purchase was (amount divided by rate), and for stablecoin shares the public chain can link a line to the payer's address. Only a processor's log keeps owners unlinkable in what it publishes.
Source: solidarity.md, “Facilitator behaviour”, item 7; attestation.md, “Lines” and “Security considerations”
What the fund would need and publish
Four things. The first two are what a fund would need: an account to be paid into and a key to cosign with. The specification does not say how a fund publishes either, and it does not yet define how a fund's cosigning key is published or checked. The last two are what a fund that wants to be trusted with shares would publish; the informative processor-mode document suggests them and leaves allocation to each fund.
Where to pay it
On a blockchain, a receiving account on each chain it accepts, written as a CAIP-10 account: the chain and the address together. Off chain, for processor-mode payouts (card and bank rails and custodial wallets), a web address (a URI) that names the fund in the processor's log. The owner's policy names the fund, and each log lists the funds it pays in its descriptor, a public file the log publishes.
On x402, a share is paid to the fund named in the owner's own policy, never to an address chosen by a seller or a log, so neither can redirect it. In processor mode, the processor holds the money it collects until it pays the fund, so owners rely on the fund's cosignature, which says each payout listed for it arrived.
Source: attestation.md, “Lines” and “Publication”; solidarity.md, “Owner policy” and “Security and privacy”; processor-mode.md, “Processor mode” (informative)A key for cosigning
A signing key of its own. Each month the fund could cosign a log's statement: a signature with this key over the same statement the log signed, published next to it. The specification defines how a log's key is authorized, but not yet how a fund's key is published, so a verifier has no specified way to know that a key belongs to the fund.
Source: attestation.md, “Witnesses and the fund”, “Signatures and keys” and “Publication”Its allocation rule, inputs and results
The rule it uses to split the money, its exact inputs, each identified by a checksum (pinned by hash), and its results, so anyone can recompute them. The simulator runs one such rule on real crisis data (its source code is allocate.js).
Source: processor-mode.md, “Fund policy” (informative)What it raises, next to official aid
What it raises, reported alongside official aid levels, so the new money cannot quietly replace them.
Source: processor-mode.md, “Fund policy” (informative)What a fund must not do
Two things. One rule the specification sets for a fund directly, about payment channels, below; and one its cosignature carries, never to cosign two different statements for the same log and month (step 8 under Each month).
Claim or refund a share's payment channel
On x402, a batch-settlement payment channel names the fund's own address as its receiver, and the channel's rules let the receiver claim from it or refund it directly. The specification forbids this: a fund must not claim or refund solidarity channels. The log does the claiming.
Any amount claimed on such a channel that the log did not claim itself counts in no line, total or settlement reference, and the shares it covers are counted as uncollected.
Source: attestation.md, “Optional share kind: batch-settlement”, “Claims” and “Refunds”Each month: check the statement and the money, then cosign
This is what the fund's monthly work would be. No log pays any fund today, and no money moves. A log's statement for a month should appear within 15 days after the month ends.
- Fetch the month from each log that would pay the fund. Every log would publish the same five things at fixed addresses under its own URL: its descriptor (a public file listing the log's signing keys, the funds it pays and the witnesses it expects), each month's statement with its cosignatures, the month's lines, the month's settlements file, and a lookup that reports, for any share id, whether its line is in a statement and, if so, the proof. Source: attestation.md, “Statements” and “Publication”
- Check the log's signature. Verify the log's signature on the statement, and check that the key it used is the log's: authorized for the log's web address (by a
did:webdocument or a DNS record on its host) and listed in its descriptor for that month. Source: attestation.md, “Signatures and keys” - Check that the month follows the last one. The statement's
previousfield must be the fingerprint (SHA-256 hash) of the exact signed payload bytes of the log's statement for the month before, not of the published file that wraps it with its cosignatures, and that chain must lead back, one month at a time, to the last statement the fund cosigned for this log. A log's first statement haspreviousempty (null) and must be for the first month of the earliest key in the log's descriptor. - Read the settlements file. It has one entry per payment, written
<fund>|<asset>|<ref>|<amount>, where the reference is a transfer (exact:), a claim (claim:) or a payout (payout:). Source: attestation.md, “Settlement references” - Check each of the fund's references. Each must exist and be credited to the fund. A transfer must go to the fund's address. A claim must be on a payment channel whose receiver is the fund's address and whose
receiverAuthorizer(the address allowed to make claims for the receiver) is this log's; it counts when the claim is made on chain, before any sweep moves the money into the fund's account. Transfers and claims are public on the chain, so they are checked against the chain, and a program can do that. A payout must be one the fund received from this log, and only the fund can check that, in its own records. Source: attestation.md, “Optional share kind: batch-settlement”, “Channel” and “Claims” - Check that no payment is counted twice. For each reference, add this statement's amounts to those in every statement the fund has already cosigned, from any log, this log's earlier months included. The sum must not exceed what that reference credited to the fund.
- Check the sum. The amounts listed for the fund must add up to its row in the statement's totals. verify.py does this arithmetic.
- Only then cosign, and only once for each log and month. Sign the statement with the fund's own key. If anything does not match, do not cosign. Never cosign a second, different statement for the same log and month. Source for steps 2, 3 and 5 to 8: attestation.md, “Witnesses and the fund”, “Signatures and keys” and “Consistency between months”
What the fund's cosignature says
The specification has a witness (another party that checks and cosigns statements) make the checks in steps 2 and 3, and keep the rule in step 8 against cosigning two versions of one month, before it cosigns. A fund's cosignature carries the same checks. The specification accepts it, like a witness's, as evidence that a log's key was current when the statement was issued, and consistency between months rests on the witnesses' rule against signing two versions of one month, which a verifier that requires only the fund's cosignature relies on the fund to keep.
A fund that cosigns a log's statement for a month also attests, for every totals row that names it:
- that each settlement reference listed for it exists and is credited to it;
- that across every statement it has cosigned, from any log and including this log's earlier months, the amounts listed for any one reference never add up to more than that reference credited to it;
- and that the amounts add up to the row.
The specification calls this the “money arrived” attestation. Anyone checking a receipt chooses which cosignatures to require, and the specification recommends the fund plus one independent witness.
On x402, a log cannot redirect a share, but it could misreport. In processor mode, the processor holds what it collects until it pays the fund. Either way, owners rely on their proofs and on cosigned statements, and the fund's cosignature is the part only the fund can give.
Source: attestation.md, “Witnesses and the fund”, “Signatures and keys”, “Receipts” and “Consistency between months”; solidarity.md, “Security and privacy”; processor-mode.md, “Processor mode” (informative)What a fund could refuse
The specification binds a fund to very little: what its cosignature attests, including never cosigning two versions of one month, and the rule above about payment channels. The rest is the fund's choice.
Cosigning any log
Each log keeps its own allow-list of the funds it pays, and settles only to those. That list is the log's: the specification gives a fund no way to take itself off it, or to stop transfers and claims paid to its address on chain. What a fund can always withhold is its cosignature. Being on a log's list does not make a fund cosign that log's statements.
Source: attestation.md, “Publication”; solidarity.md, “Share kinds”; processor-mode.md, “Fund policy” (informative)Any month
If the money a statement lists did not arrive, or any other check fails, the fund would not cosign it. Anyone who requires the fund's cosignature then cannot verify a receipt from that statement.
Source: attestation.md, “Witnesses and the fund” and “Receipts”Any allocation rule it did not choose
The proposal leaves allocation to each fund. The specification suggests, for discussion only, a window of a UN pooled fund such as the Central Emergency Response Fund, allocated by a published rule like allocate.js. It is not a requirement, and nothing here is affiliated with or endorsed by the UN.
Source: processor-mode.md, “Fund policy” (informative)What a fund would never have to do
Submit transfers or run the claiming
The fund sits outside the payment protocol. Logs submit the transfers and make the claims; a fund must not make claims on solidarity channels (see What a fund must not do). Moving claimed money from a payment channel into the fund's account is a separate step, a sweep, which anyone may make, the fund included. The informative processor-mode document says the log operator pays the network fees for transfers, claims and sweeps, but no normative rule yet requires a log to sweep.
Source: solidarity.md, “Summary” and “Facilitator behaviour”; attestation.md, “Optional share kind: batch-settlement”; processor-mode.md, “Fees” (informative)See purchases
What every log publishes is monthly totals, payment references, and lines with no owner, seller or item. On x402 the specification goes further: a log must not send a fund anything about purchases. The informative processor-mode document has no matching rule.
Source: solidarity.md, “Facilitator behaviour”; attestation.md, “Lines”Handle refunds
Shares are final. A refund, cancellation, chargeback or dispute of a purchase does not reverse or reduce a share, and no one may ask a fund to return any part of a total it has received. For processor mode, the informative processor-mode document adds: where a processor offers owners a refund credit, it only lowers that owner's later shares and never moves money back from a fund; and if the processor's own collection from an owner is reversed, the loss is the processor's, and it must not ask the fund for anything.
Source: solidarity.md, “Refunds”; processor-mode.md, “Refunds” (informative)Questions a fund is best placed to answer
The specification leaves these open. Each is taken from its open questions.
- Regulation. Collecting owners' money and passing it to a third-party fund can be money transmission or remittance, and can need charitable-solicitation registration in many US states; a monthly charge falls under card-network rules for recurring merchant-initiated charges. Who can run processor mode, and where? Source: processor-mode.md, “Open questions”, 3 (informative)
- Allow-lists. Who curates a shared fund allow-list beyond each log's own? Source: processor-mode.md, “Open questions”, 4 (informative)
- Tax receipts. Who issues tax receipts, and in which countries can a share be deductible? Source: processor-mode.md, “Open questions”, 4 (informative)
- Fees. Should a log be allowed to disclose and deduct a fee instead of bearing all costs? Source: solidarity.md, “Open questions”, 5
- Witnesses. What default should verifiers require (the fund plus one independent witness is proposed), and who runs independent witnesses? Source: attestation.md, “Open questions”, 2
- Deadline. Is 15 days after the month the right deadline for a statement? Source: attestation.md, “Open questions”, 3
Recompute a month's numbers
For the fund's technical staff. The numbers in a log's statement can be recomputed from the files the log publishes. Two checkers, written separately in two languages so that they have to agree, are published with the specification, and the hash manifest (a JSON file of checksums) pins the SHA-256 of each one. They check arithmetic, inclusion and, in some cases, the log's signature. Neither checks cosignatures, and neither can do the fund's own matching.
The step no program can do
No checker can see the fund's accounts. Transfers and claims are public on the chain, so a program can check them there. A processor-mode payout can only be matched in the fund's own records: that step is the fund's alone, and it is part of what the fund's cosignature says it did. Neither checker below reads the chain either: checking transfers and claims needs a tool that reads the chain, such as a block explorer or a node.
verify.py
A checker in Python, standard library only, plus the cryptography package if the log's signature is to be checked. Given a month's files saved from a log (<log>/lines/<period>, <log>/statements/<period> and <log>/settlements/<period>), run:
python3 verify.py --selftest
python3 verify.py --lines lines.txt --statement statement.json --settlements settlements.txt
python3 verify.py --chain first.json second.json
python3 verify.py receipt.json --key <the log's public key in hex>
The first reproduces the specification's test vectors. It needs solidarity-vectors.json in a spec folder beside verify.py, or its path after --selftest; without it, it checks only the Certificate Transparency vectors and skips the draft 2 ones.
The second rebuilds the month's root (a fingerprint of all its lines), size and totals from its lines and compares them with the statement, then checks the settlements file's hash and that its amounts add up to the totals. The third checks that each statement names the one before it, with no month skipped. Both are arithmetic only: they check no signature.
The last checks that one line is in a statement for the line's month. It checks the log's signature only when given --key, only for an Ed25519 key, and only when the cryptography package is installed; a signature it does not check is reported as not checked, not as a failure. It counts cosignatures but does not check them.
The descriptor gives the log's key as a JWK. For an Ed25519 key (kty OKP), the JWK's x value is the key itself in base64url. To turn it into hex:
python3 -c "import base64,sys; x=sys.argv[1]; print(base64.urlsafe_b64decode(x+'='*(-len(x)%4)).hex())" <x>
Source: attestation.md, “Test vectors” and “Signatures and keys”
merkle.js
The same tree, line, settlement and receipt checks in JavaScript, for a web browser or Node.js 20 or later. It has no check that statements chain. Its receipt check verifies the log's signature (Ed25519 or ES256) when given the log's key, and does not check cosignatures. The ledger demo uses it.
The ledger demo
To see the idea work before reading any code: a simulated month in your browser. Rebuild each batch's fingerprint, then change one line of a receipt by one cent and watch its proof fail. It is simulated, and it still uses the draft 1 line format, with a payment id and an owner id in each line; in draft 2, lines carry no owner, no seller and no item.