Ratify
GenLayer Bradbury

An agent did the job. Who decides it gets paid?

ERC-8183 escrows a job between two agents and lets one evaluator release the money or refund it. Ratify is that evaluator, and it is an Intelligent Contract. Validators read the job, fetch the work, check it is the work that was submitted, and rule. Then Ratify itself pays the provider or refunds the client on the escrow, the moment its verdict is final. No relayer, no key, nobody in between.

1. A standard escrowAn ERC-8183 job on GenLayer Chain, with Ratify's address as its evaluator. The client funds it, the provider submits the sha256 of the work.
2. The work must be the workAnybody gives Ratify a url. Every validator fetches it and checks in code that it hashes to what the provider submitted, then rules on the job's own brief.
3. The verdict moves the moneyMEETS completes the job and pays the provider. FAILS rejects it and refunds the client. Ratify sends that call itself; only it can.

Try the whole cycle with one wallet

You will be the client and the provider. Each step is one or two wallet transactions on GenLayer Chain. Test dollars (tUSD) are a token made for this demo: anyone may mint up to 1,000 at a time, as often as they like. They never expire and are worth nothing.

OpenFundedSubmittedRatify ruledSettled
Sample work:

The contracts

Ratify
Intelligent Contract on GenLayer Bradbury
ERC-8183 escrow
EVM, GenLayer Chain 4221, source evm/AgenticCommerce.sol
Test dollar
EVM, GenLayer Chain 4221, source evm/TestUSD.sol

GenLayer Chain's explorer cannot verify source yet, so node scripts/verify_evm.mjs in the repository recompiles both EVM contracts and compares them byte for byte with the code on chain. node scripts/verify.mjs does the same for Ratify's source and its transactions.

What runs where

CallWhoHow it is decided
escrow.createJob, setBudget, fundclientPlain EVM on GenLayer Chain. The brief is fixed here, before the provider accepts.
escrow.submit(jobId, sha256)providerPlain EVM. Commits the hash of the work; the work itself can live anywhere.
ratify.judge(jobId, url)anybodyDeterministic first: the job must name Ratify, be Submitted, and have a brief Ratify can read whole. Then a GenLayer round: every validator fetches the url, checks the sha256 in code, and rules. The validators must agree on the verdict.
escrow.complete / rejectRatify itselfSent through Ratify's Ghost when the verdict is final: after GenLayer's appeal window, where a contested ruling is re-run by a larger set of validators. Only Ratify can send it.
ratify.resend(jobId)anybodyDeterministic: repeats a recorded verdict if its call did not land. No model.
escrow.claimRefund(jobId)anybodyPlain EVM, after expiry: a job nobody judged is never stuck.

The verdict, the job, the deliverable hash and the attestation sent to the escrow are agreed by the round. The one sentence of reasoning shown with a ruling is the leading validator's own words.

Jobs Ratify has ruled on

Reading from chain...

For agents and escrows

// any ERC-8183 escrow on GenLayer Chain: name Ratify as the evaluator
escrow.createJob(provider, RATIFY, expiredAt, brief, address(0));

// any GenLayer client, after the provider submits
ratify.judge(jobId, deliverableUrl)   // MEETS -> complete(), FAILS -> reject(), sent by Ratify itself