Programmable escrow for B2B stablecoin payments
What is programmable escrow?
Programmable escrow is holding a business’s stablecoin payment, such as USDC, in an escrow smart contract or a dedicated wallet until agreed conditions are met, such as work approved or goods delivered, then releasing it to the seller, or returning it if a condition fails or a deadline passes.
That makes it different from authorize and capture, where the merchant captures the money as orders ship.
Businesses paying suppliers, contractors and service providers, and the B2B payment platforms they use, depend on these conditional payments, a form of crypto escrow: the seller starts work knowing the money is there, and the buyer pays knowing it comes back if the deal falls through.
With Goldsky, you can hold the funds in an escrow contract you deploy, which only your Compose release task can pay out of, or in an escrow wallet your custody provider holds.
Who uses programmable escrow?
Businesses that pay suppliers, contractors and service providers in stablecoins, the B2B payment platforms and payment providers they use, and title and escrow companies holding deposits for real estate closings.
How programmable escrow works
The diagram follows one order from agreeing the release terms to paying the seller or refunding the buyer, and shows who does each step. Your setup may differ.
Ways to run programmable escrow
An escrow contract keeps each payment’s state onchain and lets only the release task pay out of it; a custodial escrow wallet pools payments under your custody provider’s signing policy, and only your database says which order each payment belongs to.
- Best for
- Payout rules enforced onchain, payment by payment
- Where the funds sit
- An escrow contract you deploy
- Who can pay out
- Only the task’s wallet, enforced by the contract
- What each order holds
- Recorded onchain per payment
- Best for
- Funds kept with a custody provider and its approval policy
- Where the funds sit
- A wallet your custody provider holds
- Who can pay out
- Whoever your custody policy lets sign
- What each order holds
- Recorded only in your database
| Usual setupOption 1: Escrow smart contract | Option 2: Custodial escrow wallet | |
|---|---|---|
| Best for | Payout rules enforced onchain, payment by payment | Funds kept with a custody provider and its approval policy |
| Products | ComposeTurbo | ComposeTurbo |
| Where the funds sit | An escrow contract you deploy | A wallet your custody provider holds |
| Who can pay out | Only the task’s wallet, enforced by the contract | Whoever your custody policy lets sign |
| What each order holds | Recorded onchain per payment | Recorded only in your database |
Agree the release terms
Buyer and seller need to know in advance what releases the money and what sends it back.
Set the condition that releases the payment, such as delivery confirmed, a milestone approved or an inspection passed, the deadline after which it’s released or refunded without anyone acting, and who rules on a dispute. Terms left vague turn every late delivery into an argument over who gets the money.
Deploy the escrow contract
The contract keeps the money out of reach of both sides, and of your own staff, until the terms say otherwise.
It takes each payment, records the buyer, the seller, the amount and the deadline, and pays out only through a release function and a refund function that one agent address can call. Have it audited before it holds real funds, because money a faulty payout function sends can’t be pulled back.
Take the buyer’s payment into escrow
The order is funded only once the stablecoins sit in the contract.
The buyer approves the contract to spend the stablecoins and calls it with the order’s details; the contract pulls the funds in, marks the payment pending and emits an event with its ID. Stablecoins sent straight to the contract’s address, without that call, aren’t recorded against any order.
Record each deposit in your ledger
Handled by Goldsky TurboYour platform needs its own record of what each order holds in escrow, kept in step with the chain.
Every deposit, release and refund the contract emits is written to your database against the payment ID. If a reorg (the chain replacing its newest blocks) drops a deposit, its row has to go too, or the order shows funds that aren’t there.
With Goldsky, a Turbo Pipelines pipeline decodes the escrow contract’s events from the chain’s raw logs with
Decode contract events (opens in a new tab)_gs_log_decodeand the contract’s ABI, then writes them to a table keyed on a primary key, so a reorg’s deletes and updates correct the rows in place.Mark the order funded
Seller and buyer both act on the order’s status, so it has to show the money is held.
Your order system joins the deposit row to the order by the payment ID and checks the amount. Tell the seller to ship or start work only once enough blocks sit on top of the deposit that a reorg is unlikely to undo it.
Confirm the condition
Someone has to decide that the goods arrived, the milestone was met or the dispute was settled.
Your platform records the evidence, such as a carrier’s delivery scan, the buyer’s approval or an inspector’s report, and then asks for a release or a refund. When buyer and seller disagree, the payment stays held until your dispute process or arbitrator rules.
Act on deadlines and stuck payments
Handled by Goldsky ComposeA buyer who never confirms, or an order nobody touches, shouldn’t leave money held for good.
On a schedule, every payment past its deadline is released or refunded under the terms, and any payment still pending after a failed release is reported to your team. Checking only when someone acts misses the orders where nobody does.
A Compose task on a cron trigger can read the contract for payments still pending past their deadline and start the release task for each one with
Run a task on a schedule (opens in a new tab)callTask, the way the compliance oracle guide’s scheduled task catches payments left in escrow.Release the payment or refund the buyer
Handled by Goldsky ComposeThe money moves only once the decision is made, and only to the side the terms name.
Each request names the payment and the outcome, and the payout waits until it’s safely in the chain before the decision is recorded with its reason. Keep the contract’s check that a payment is still pending, so a second request for the same payment can’t pay it twice.
Your app starts a Goldsky Compose task with an authenticated HTTP call; the task calls the contract’s release or refund function from the one wallet the contract trusts, with gas sponsored, waits for the confirmations you set and can replay the call if a reorg drops it. A retried task doesn’t send the call twice, and the decision is stored in a collection keyed on the payment ID.
Send from a task wallet (opens in a new tab)Close the order
Seller, buyer and your books should all show where the money went.
When the release or refund reaches your ledger, mark the order paid out or refunded and tell both sides. Keep the condition evidence, the decision and both transaction hashes with the order, so anyone can trace the money from deposit to payout.
What to know about an escrow smart contract
- Only the contract’s agent address can pay out, so a bug in your app can’t send escrowed funds anywhere the contract doesn’t allow.
- Each contract trusts one agent wallet; rotating its key is a contract call from the old key, followed by a redeploy of the task.
- You can let the buyer reclaim funds after a deadline without your platform, so an outage on your side doesn’t trap them.
- The contract is code you own: it needs an audit, and changing its rules means deploying a new one.
Agree the release terms
Buyer and seller need to know in advance what releases the money and what sends it back.
Set the condition that releases the payment, such as delivery confirmed, a milestone approved or an inspection passed, the deadline after which it’s released or refunded without anyone acting, and who rules on a dispute. Terms left vague turn every late delivery into an argument over who gets the money.
Set up the escrow wallet and its policy
Escrowed funds need a wallet of their own, kept apart from your operating money.
Your custody provider holds the escrow wallet’s key and signs only under a policy you set, such as payouts only to the buyer or seller on an order and only up to its amount. A wallet shared with operating funds makes it impossible to show which money is held for buyers.
Take the buyer’s payment
The order is funded once the stablecoins reach the escrow wallet.
The buyer sends the order amount from the wallet they gave at checkout. A payment from a different wallet, or for a different amount, can’t be tied to the order without someone looking at it.
Spot the deposit
Handled by Goldsky TurboYour platform has to know the money arrived before it tells the seller to go ahead.
Every transfer of the stablecoin into the escrow wallet is written to your database as it lands. If a reorg (the chain replacing its newest blocks) undoes one, its row has to be removed, or the order shows funds that aren’t there.
Goldsky’s Turbo Pipelines reads the curated ERC-20 transfers dataset, filtered at the source to the stablecoin’s contract, keeps the transfers into your escrow wallet in a SQL transform and writes them to your database, where reorg corrections update or delete the rows.
See the EVM transfer datasets (opens in a new tab)Match the deposit to the order
The wallet holds many orders’ money, so each deposit has to be assigned to one.
Your database joins each deposit to an open order by sender and amount, or by a deposit address per order, and marks the order funded. Deposits that match no order go to a review queue rather than sitting unassigned in the wallet.
Confirm the condition
Someone has to decide that the goods arrived, the milestone was met or the dispute was settled.
Your platform records the evidence, such as a carrier’s delivery scan, the buyer’s approval or an inspector’s report, and then asks for a release or a refund. When buyer and seller disagree, the payment stays held until your dispute process or arbitrator rules.
Act on deadlines and stuck payments
Handled by Goldsky ComposeA buyer who never confirms, or an order nobody touches, shouldn’t leave money held for good.
On a schedule, every order past its deadline is released or refunded under the terms, and any order still held after a refused or failed payout is reported to your team. Checking only when someone acts misses the orders where nobody does.
A Compose task on a cron trigger can call your order API with
Run a task on a schedule (opens in a new tab)fetchfor orders past their deadline and start the release task for each one withcallTask.Release the payment or refund the buyer
Handled by Goldsky ComposeThe money moves only once the decision is made, and only to the side the terms name.
Each request names the order and the outcome, and the payout carries the order’s amount to the seller’s or buyer’s wallet. A payout built twice for one request pays twice, so it needs a fixed identity across retries.
With Goldsky, your app starts a Compose task with an authenticated HTTP call, and the task sends the stablecoin transfer from a webhook wallet at the escrow wallet’s address: Compose sends the signing endpoint you host a UserOperation (the transaction format smart-account wallets use) to sign, plus a one-time EIP-7702 authorization the first time the wallet sends on a chain, submits the transfer with gas sponsored once the signature comes back, and doesn’t send it again if the task retries.
Use a webhook wallet (opens in a new tab)Sign the payout
Moving escrowed funds takes a signature from a key held under rules about what it may pay.
Your signing endpoint holds the escrow rules: it reads the recipient and amount from the payout’s call data, checks them against the order, then asks your custody provider to sign, or refuses. A refused payout leaves the order held until your team looks at it.
Reconcile the escrow wallet
The wallet’s balance should always equal what your database says is held for open orders.
Each day, compare the wallet balance with the sum of the open orders’ escrow balances and look into any gap. A gap means a deposit nobody matched, a payout nobody recorded, or funds that don’t belong to any order.
Close the order
Seller, buyer and your books should all show where the money went.
When the release or refund reaches your ledger, mark the order paid out or refunded and tell both sides. Keep the condition evidence, the decision and both transaction hashes with the order, so anyone can trace the money from deposit to payout.
What to know about a custodial escrow wallet
- Open orders share one wallet, so which funds belong to which order lives only in your database, and the wallet balance has to be reconciled against it.
- Your custody provider’s approval policy is what stops a wrong payout; the task only asks it to sign.
- Buyers can’t check onchain that their payment is held for them.
- Deposits are tied to orders by sender and amount, or by a deposit address per order, as a join in your database.
What you control
- Your team
- Agree the release terms
- Deploy the escrow contract
- Mark the order funded
- Confirm the condition
- Close the order
Questions and answers
How does an escrow smart contract work?
An escrow smart contract takes the buyer’s stablecoins and pays them out only through functions it restricts, usually a release to the seller and a refund to the buyer. It records who paid, who is owed and how much, and often lets only one agent address call those functions. It can also let the buyer reclaim the funds after a deadline. The contract controls who can move the money; deciding whether the condition was met stays with the platform, an inspector or an arbitrator.
How is programmable escrow different from authorize and capture?
In programmable escrow, an agreed condition releases the money, such as confirmed delivery, an approved milestone or an inspector’s sign-off, and the hold lasts as long as the deal does. In authorize and capture, the merchant releases it by capturing the payment as orders ship, before a fixed deadline. Escrow protects a buyer who pays before delivery; authorize and capture guarantees a merchant’s funds before it fulfills an order.
Security and deployment
- SOC 2 Type IIIndependently audited security controls.
- Dedicated infrastructureSingle-tenant options for production workloads.
- Data residencyCloud, on-premises or co-located.
More use cases that automate payouts
- Stablecoin payroll and contractor payoutsPay contractors and staff in stablecoins and confirm each payout settled.
- Stablecoin payouts for marketplaces and creatorsPay sellers, gig workers and creators in stablecoins from a marketplace balance.
- Payout prefunding in USDCPrefund a payout network in USDC and track the balance so payouts never stall.
- Token distributions to holders and creditorsPay one asset out to thousands of holders, creditors or employees and prove each delivery.
- Airdrop eligibility lists and sybil filteringScore every address up to a snapshot block, remove sybil clusters and publish the list people claim against.
- Stablecoin disbursements for public-sector programsTrack government benefit or grant payments made in stablecoins, from issue to spend.
- Stablecoin merchant settlementPay each merchant’s settlement in stablecoins to the wallet and network it chose, on any day, and record the transaction against the settlement.
Use cases built the same way
- Authorize and capture stablecoin paymentsHold a buyer’s stablecoins in an escrow contract at checkout, capture them to the merchant as orders ship, void what can’t be filled and refund after capture.
- Cross-chain transfer trackingSee every cross-chain stablecoin transfer as settled, in flight or stalled, and catch the stuck ones.
- Tokenized stock mint and redeem against ordersTrigger mints and redemptions when a customer buys or sells, and record every step for the books.
- Prediction market creation and resolutionCreate and resolve prediction markets automatically, with every write retried and traced.
Run programmable escrow for B2B payments with Goldsky
We’ll map it to your systems and show you what Goldsky runs, so your team builds the product, not the pipelines underneath it.