How Escrows Work
Milestone payments for KOL deals, held by a contract on Base until the work is delivered.
Jump to a section
Overview
A project locks the full payment for a KOL deal in its own escrow contract on Base Sepolia. The deal is split into milestones, each with an amount and a deadline. When a milestone is delivered, its amount goes straight to the KOL wallet.
Nothing pays out on a timer by itself. A payment needs the project to release it, or verifier approval plus a review window, or a ruling by the platform arbiter. Funds can only go to the project, to the KOL, or as the platform fee on a KOL payout.
For Projects
For KOLs
The Escrow V2 factory is deploying soon. Until then new escrows use the first escrow contract (see Legacy Escrows below).
Roles
Four parties take part in a deal, each with a short, fixed list of actions.
| Role | Who | Can |
|---|---|---|
| Project | The wallet that creates and funds the escrow | Release any open milestone, dispute, withdraw its own dispute, reclaim expired milestones, agree to cancel, recover tokens sent by mistake. |
| KOL | The payee set at creation | Post proof, dispute, withdraw its own dispute, agree to cancel. Receives every payment. |
| Verifiers | Optional, up to 10 wallets set at creation | Approve a submitted milestone before its deadline. A set number of them (for example 2 of 3) must approve. |
| Arbiter | One platform Safe multisig for all escrows | Split a disputed milestone between the KOL and the project. Nothing else. |
| Anyone | Release an approved milestone once its review window has passed. |
- Verifiers cannot be the project, the KOL or the arbiter, and they never hold funds.
- The arbiter cannot touch an undisputed milestone or pick a recipient other than the two parties.
- Verifiers review their queue on the verifier dashboard.
Creating an Escrow
The project sets every term up front. They cannot be changed after funding.
- 1Enter the KOL wallet.Payments go to this address. Double check it.
- 2Pick the token.USDC, ETH or WETH. See Tokens below.
- 3Add milestones.Up to 20. Each one has an amount and a deadline in the future, at most 5 years away. Deadlines do not need to be in order.
- 4Add verifiers (optional).Up to 10, and how many must approve. With verifiers you also set a review window of up to 90 days.
- 5Approve and fund.Approve exactly the deal total, then create. The escrow is deployed and funded in one transaction. The fee is not added on top.
Milestone Lifecycle
Each milestone moves through its own states. A dispute on one never blocks the others.
| State | Meaning | Next |
|---|---|---|
| Pending | Funded, waiting for proof. | Submitted, Released, Disputed, or Refunded after the deadline |
| Submitted | The KOL posted proof. | Approved, Released, Disputed, or Refunded after the deadline |
| Approved | Enough verifiers approved before the deadline. | Released, or Disputed |
| Disputed | Frozen until the arbiter rules or the raiser withdraws. | Resolved, back to its previous state, or Refunded by mutual cancel |
| Released | Paid to the KOL, minus the fee. | Final |
| Refunded | Returned to the project, with no fee. | Final |
| Resolved | Split by the arbiter and paid out. | Final |
Proof Submission
- The KOL posts a public link to the delivered work before the milestone deadline. Its hash is stored on chain.
- Proof can be replaced until the first verifier approves it.
- Proof cannot be posted after the deadline.
- Proof links are public: they live in the transaction log.
Review Window and Auto Release
When enough verifiers approve, the milestone becomes Approved and its review window starts. During the window the project can still release early or raise a dispute. Once the window has passed, anyone can release the payment, so a silent project cannot hold an approved milestone back.
- The review window applies only when the deal has verifiers. It can be up to 90 days.
- Approvals only count before the deadline.
- Without verifiers, payment needs the project to release, a dispute ruling, or a mutual cancel.
- The project can release any open milestone at any time, approved or not, since it is the project's money.
Disputes and Arbiter Splits
- 1Raise.The project or the KOL disputes one milestone while it is Pending, Submitted or Approved, with a written reason. The reason is public in the transaction log.
- 2Freeze.Only that milestone is frozen. Every other milestone keeps working.
- 3Withdraw or rule.The person who raised it can withdraw it, and the milestone returns to its previous state. Otherwise the arbiter decides what share goes to the KOL.
- 4Pay out.The KOL share (minus the fee) and the project share are paid in the same transaction.
No automatic timeout
An unanswered dispute waits for the arbiter, a withdrawal by the raiser, or a mutual cancel. If the arbiter never acts, the owner can rotate the arbiter after a 2 day delay.
Clawback and Mutual Cancel
Clawback
If a milestone is still Pending or Submitted when its deadline passes, the project can reclaim that amount. Approved and Disputed milestones cannot be reclaimed, so the KOL is protected once verifiers have approved.
A KOL whose verifiers have not acted should raise a dispute before the deadline. Once it passes, the project can reclaim the milestone at once.
Mutual Cancel
Either side can ask to cancel. When the other side agrees, every milestone not yet paid, including disputed ones, goes back to the project and the escrow closes. A request can be withdrawn until the other side agrees. Refunds carry no fee.
Fees
- Platform fee: 2.5% of each released milestonedefault, capped at 5% by the contract.
- The fee is fixed for each escrow when it is created. Later fee changes never apply to it.
- It is charged only on amounts paid to the KOL: releases, auto releases and the KOL share of a dispute.
- The project funds exactly the deal total. Refunds, clawbacks and cancels carry no fee.
- A fee change needs a public 2 day delay.
- Gas on Base is usually a few cents per action.
ETH and ERC-20 Tokens
| Token | How it works |
|---|---|
| USDC | Approve the total, then create. Paid out in USDC. |
| ETH | Sent with the create transaction. The escrow holds it as WETH and pays out in WETH. |
| WETH | For wallets that already hold WETH. Approve, then create. |
- At the contract level any standard ERC-20 works. Tokens that take a fee on transfer are rejected when funding.
- USDC can block transfers to blocklisted wallets. If the KOL wallet is blocked, that payout cannot go through, and the milestone falls back to clawback or mutual cancel.
- Tokens sent to an escrow by mistake can be recovered by the project.
Worked Example
A 1,000.00 USDC deal in two milestones of 500.00 USDC, with one verifier, a 3 day review window and the 2.5% default fee.
- 1Funding.The project approves and deposits 1,000.00 USDC. Nothing is added for the fee.
- 2Milestone 1: proof.The KOL posts a link to the thread before the deadline.
- 3Milestone 1: approval.The verifier approves. The 3 day review window starts.
- 4Milestone 1: payout.The project releases on day 2, or anyone releases after day 3. The KOL receives 487.50 USDC and 12.50 USDC goes to the platform.
- 5Milestone 2: dispute.The project says the video missed the brief and disputes. The arbiter rules 60/40. The KOL receives 292.50 USDC (300.00 minus 7.50 fee) and the project gets 200.00 USDC back.
| USDC | |
|---|---|
| KOL received | 780.00 |
| Project refunded | 200.00 |
| Platform fees | 20.00 |
| Total | 1,000.00 |
Had milestone 2 expired with no proof instead, the project would reclaim the full 500.00 USDC with no fee.
Limits
- Up to 20 milestones and 10 verifiers per escrow.
- Each deadline must be in the future and at most 5 years away.
- Review window up to 90 days, only with verifiers.
- Terms are fixed at creation. To change them, mutually cancel and create a new escrow.
- The factory owner can pause new escrows. Existing escrows keep working.
Safety and Security
Not audited yet
Escrow V2 is tested, including on a fork of Base mainnet with real USDC and WETH. It has not had an external audit yet. Keep deal sizes reasonable.
- Funds can only leave an escrow to the project, to the KOL, or as the fee on a KOL payout. Collected fees can only go to the treasury.
- The owner has no function that moves escrowed funds and cannot renounce ownership.
- Fee and arbiter changes wait a public 2 day delay. A new arbiter must accept the role itself.
- No upgrades: a new version means a new factory, and existing escrows keep their code.
- Every function that moves funds is protected against reentrancy.
- Only trust an escrow that the factory confirms as its own.
Risks to Know
- The arbiter is trusted to split fairly.
- A token that later adds transfer fees or shrinks balances could stop the last payout.
- At the deadline it is a race: a KOL with silent verifiers must dispute in time.
Best Practices
For Projects
- Write the brief before you fund: what counts as done for each milestone, and where the proof will live.
- Split big deals into several smaller milestones.
- Leave enough time before each deadline for the KOL to deliver and for verifiers to approve.
- Pick verifiers both sides trust, and use more than one with a threshold such as 2 of 3.
- Release promptly when the work is good.
For KOLs
- Check the escrow is funded and the milestones match what you agreed before you start.
- Post proof early, well before the deadline.
- If verifiers have not acted as the deadline nears, raise a dispute before it passes.
- Use a wallet that can receive the payment token. A USDC blocklisted wallet cannot be paid.
- Keep your own copy of the delivered work and the brief.
For Developers
- Only trust an escrow if the factory confirms it with
isEscrow(address). - Proof links and dispute reasons are in the event logs (ProofSubmitted, DisputeRaised), not in storage.
- Read every milestone with getMilestones(), and use isAutoReleasable(id) and isReclaimable(id) to decide which actions to offer.
- Milestone status values: 0 Pending, 1 Submitted, 2 Approved, 3 Disputed, 4 Released, 5 Refunded, 6 Resolved.
// Project: approve exactly the total, then create (Escrow V2)
await usdc.approve(factory, total);
await factory.createEscrow(
kol, usdc, total,
[500e6, 500e6], // milestone amounts
[deadline1, deadline2], // unix seconds, each in the future
[verifier1, verifier2], 1, // verifiers and approvals needed
3 * 86400 // review window in seconds
);
// Or fund with ETH (held as WETH)
await factory.createEscrowETH(kol, amounts, deadlines, [], 0, 0, { value: total });
// KOL posts proof, a verifier approves, the project releases
await escrow.submitProof(0, keccak256(toBytes(url)), url);
await escrow.verifyMilestone(0);
await escrow.release(0);
// Disputes, clawback and mutual cancel
await escrow.raiseDispute(1, "reason"); // project or KOL
await escrow.resolveDispute(1, 6000); // arbiter: 60% to the KOL
await escrow.clawback(); // project, expired milestones
await escrow.requestCancel(); // both partiesLegacy Escrows
Escrows created before V2 use the first contract and are marked as legacy. They can still be viewed, approved and released. Their dates are not enforced, and a dispute on them freezes the whole escrow with no way to resolve it on chain, so raising one is turned off in the app.
FAQ
Who pays the escrow fee?
The KOL. The 2.5% default fee comes out of each payment to the KOL. The project funds exactly the deal total, and refunds carry no fee.
What if the project never releases?
If the deal has verifiers and they approve before the deadline, anyone can release the payment once the review window passes. Without verifiers, the KOL can raise a dispute for the arbiter to decide.
What if the KOL never delivers?
Once the deadline passes on a milestone that is still waiting for proof or approval, the project can reclaim that amount with no fee.
What if a dispute is never answered?
It waits for the arbiter, a withdrawal by the person who raised it, or a mutual cancel. There is no automatic timeout.
Does a dispute freeze the whole deal?
No. Only the disputed milestone is frozen. Every other milestone keeps working.
Which tokens can I use?
USDC, ETH and WETH in the app. ETH is held and paid out as WETH. Tokens that take a fee on transfer are rejected.
Can I change a deal after funding?
No. Terms are fixed at creation. Both sides can mutually cancel, which refunds every unpaid milestone, and then open a new escrow.
Can S4 Labs take the funds?
No. Funds can only go to the project, to the KOL, or as the fee on a KOL payout. The arbiter can only split a disputed milestone between the two parties.
Is Escrow V2 audited?
Not yet. It is tested, including on a fork of Base mainnet, and has not had an external audit. Keep deal sizes reasonable.