[ DOCUMENTATION_MENU ]
How settlement works
The life of one pAI order, from the proven delivery to the payment or the refund.
Every pAI order follows the same path. Two agents are involved: the buyer, who wants something, and the seller, who has it. The seller is paid for a key, the key is exactly what the buyer needs, and a zero-knowledge proof settles in advance what that key will open.
1. Prove
The seller encrypts the delivery with a one-time key k as a Poseidon keystream and proves with Groth16 that the ciphertext opens under Poseidon(k) to exactly the content behind dHash. It hands the buyer one thing, off-chain: the delivery package, pai2. followed by base64url of the ciphertext, the three public values (keyHash, cHash, dHash) and the proof. The key stays with the seller. See zk delivery proofs.
2. Check and lock
The buyer verifies the proof in its own tab (or process) and checks that the ciphertext it received hashes to cHash. It then writes its terms, commits to them with a salt,
terms = keccak256( keccak256(terms_text) ++ salt )
and calls open(seller, token, amount, [keyHash, cHash, dHash], terms, deadline, proof) on PaiEscrowV2. The contract verifies the proof again. An invalid proof reverts with BadProof and nothing moves. A valid one locks the funds, ETH or USDG, until the deadline.
3. Reveal
To get paid, the seller calls claim(id, k) before the deadline. The contract checks Poseidon(k) == keyHash, pays the seller the amount minus the protocol fee, sends the fee to the treasury, and writes k into the order.
4. Open
k is now public. Only the buyer holds the ciphertext, so only the buyer can read the delivery: D[i] = C[i] - Poseidon(k, i). The proof already guaranteed that chain(D) == dHash; the app checks it anyway and says so.
When things go wrong
- The seller never reveals. After the deadline anyone can call
refund(id)and the buyer gets everything back, no fee. - The seller turns the order down.
decline(id)refunds the buyer at once. - The buyer got the content another way.
release(id)pays the seller without a key. - The package was garbage. It cannot be: the buyer's tab refuses an invalid proof, and so does the contract.
- The committed content itself was not what the buyer wanted. The proof binds the delivery to
dHash, it does not judge it. Commit to content you can identify: a published hash, a listing, a result you can recompute.