Escrow fundamentals
Smart Contract Escrow, Explained
A smart contract escrow is a program on Ethereum that holds ETH or stablecoins and moves them only when its published rules are met.
· 4 min read · DeFiEscrow
A smart contract escrow is an escrow whose rules are a program on a blockchain. The program has an address. It can receive ETH or tokens. It will send them onward only by running the functions that were deployed with it. There is no separate "escrow balance" hiding in a spreadsheet. The balance is the contract's balance, and the permitted movements are the code.
DeFiEscrow is one implementation of that idea on Ethereum. The contract is called MultiPartyEscrowHybridDAOv1 in the source, version 1.2.1. You do not need to read Solidity to use it. You do need a picture of the state machine, because every button in the app is one of those functions.
The states, in order
A single escrow is always in exactly one state.
- Created. The terms exist and funding is open. Not every deposit has arrived.
- Funded. Deposits match the required total. Approvals are open.
- Approved. Every required party has approved. Release is allowed.
- Disputed. Someone objected. Release is frozen.
- Released. Payouts are credited. Parties can withdraw what they were owed.
- Terminated. The deal was cancelled. Depositors can withdraw what they paid.
There is no "partially released" state and no "negotiating" state. If you need a different commercial outcome, you need different terms at creation, or a later escrow.
The protocol page draws the same machine for people who want the short technical note. The rest of this article is what each step feels like from a wallet.
Create
createEscrow records the deal. The caller provides an escrow id, the token (the zero address means ETH), the party addresses, how much each must deposit, how much each will receive, a funding deadline, and an approval deadline. The approval deadline has to be after the funding deadline. Both have to be in the future at the moment of creation.
The sums have to match: total deposits equal total receipts. The fee recipient has to be one of the parties and has to be allocated at least the required fee. After this transaction confirms, the terms do not have an edit function. That immutability is the product. It is also why you review the summary in the app before you sign.
Anyone can create an escrow. Creation does not make the creator an administrator. Afterward, the creator has no special power unless their wallet is also one of the parties.
Deposit and approve
deposit can be called only by a party who owes a deposit, only for the exact amount, and only before the funding deadline. The state has to be Created, or Funded if you are topping up a deal that is somehow being completed in the same state window. When the running total of deposits equals the required total, the state becomes Funded.
For USDC and USDT, the party first approves the contract to spend the tokens, then deposit pulls them. The contract measures the balance change and rejects the deposit if it received a different amount than it expected. That is a guard against odd token behavior. ETH is sent as the value of the transaction itself, and the value must match the required deposit exactly.
approve is allowed only once the escrow is Funded (or already Approved, for a party who has not yet approved). It is refused after the approval deadline. Every participant must approve, except the protocol fee address, which the contract skips so the fee line cannot veto the deal. When the last required approval lands, the state becomes Approved.
You cannot pre-approve while funding is still open and incomplete. The contract will not accept the signature early.
Release, dispute, and the exits
release can be called by anyone, but only in the Approved state. It does not push tokens out in a loop. It credits each party's withdrawable balance with their willReceive amount and marks the escrow Released. withdraw or withdrawTo then sends that balance. Pull payments are deliberate: a single recipient with a broken receiver cannot jam the accounting for everyone else.
raiseDispute is available to any party while the state is Funded or Approved. The escrow freezes. removeDispute can be called only by the wallet that raised it, and it returns the escrow to the state it had before. It does not move the deadlines.
If a dispute is still open after 30 days, anyone may call resolveDisputeTimeout. The escrow becomes Terminated and depositors are credited their deposits, not their hoped-for payouts. Separately, cancelAfterTimeout terminates an escrow that missed its funding deadline before it was fully funded, or missed its approval deadline before it reached Approved. Deadlines and disputes each have their own guide because people mix them up.
One function is easy to over-read. During a dispute, submitDAORecommendation can store a 32-byte value. Any caller can set it. It does not change balances, approvals, or who gets paid. It is a note, not a ruling.
What "the code moved the money" does not mean
A smart contract escrow enforces the rules it contains. It does not understand your PDF, your inspection report, or your idea of fairness. If those documents say something the functions do not say, the documents do not execute. The limits are short and worth reading before you structure a price, a commission, or a milestone.
The app is a form in front of these functions. How DeFiEscrow works follows one deal from the first screen to the withdrawal, with the same states you just read.