An Escrow Smart Contract in SmartPy

Solomon Lederer, PhD
Aug 26 · 3 min read

Below is an example escrow contract in SmartPy — A new smart contract language for Tezos. This contract can be used when transacting with a physical item e.g. Alice wants to buy a harmonica from Bob. [This contract is based on a demo in Solidity I saw years ago. If you know who originated this solution, please let me know so I can give appropriate credit.]

For a primer on SmartPy see my intro video here.

This contract works as follows:

  1. The seller sets the price of the item and deposits twice that price into the contract i.e. if the price is 1 token, the seller deposits 2.
  2. The buyer deposits 2 tokens as well. Simply by depositing 2 tokens, that person is marked as the buyer.
    Note: The reason they deposit extra money is to lock both parties into an arrangement that neither party can unilaterally walk away from.
  3. At this point the contract has 4 tokens that is now in its control. There are only 2 ways to get the money out:
  4. Option A: The buyer receives her item. She confirms that the item is received which allows her to get her extra deposit back (1 token) and send the seller the remaining 3 tokens (1 for the item and 2 for his deposit).
  5. Option B: The seller can roll everything back and refund the buyer. The buyer gets her 2 tokens back, and the seller gets his 2 tokens back as well. He would do this in a scenario where he cannot ship the item, changes his mind, etc.
  6. That’s it. Note how the typical concerns with transacting without an escrow are now gone. The seller doesn’t have to worry about sending the item and never getting paid, because he can see that the buyer has already put up the money in the smart contract and is compelled to follow through. Conversely, the buyer doesn’t have to worry about selling money to a seller that will never ship the item, because she never sends the money into the seller’s hands.

Link to the script on [note this may only work on the dev version of]

import smartpy as sp#Both buyer and seller must send in twice the value of the item they are transacting on. This ensures that both parties are committed to see the transaction through to the end.class Escrow(sp.Contract):
def __init__(self):
self.init(seller = sp.none, buyer = sp.none, price = 0)
def setSeller(self, params):
#ensure seller hasn't already been set
sp.verify (

#the seller sets the price and must send 2x the price in tez = params.price
sp.verify (sp.amount == sp.tez( * 2)) = sp.Some(sp.sender)
def setBuyer(self, params):
#ensure that there already is a seller
sp.verify (
#ensure buyer hasnt already been set
sp.verify (

sp.verify (sp.amount == sp.tez( * 2)) = sp.Some(sp.sender)

def confirmReceived(self, params):
sp.verify (sp.sender ==
sp.send (, sp.tez(
sp.send (, sp.balance)
def refundBuyer(self, params):
sp.verify (sp.sender ==
sp.send (, sp.tez(2 *
sp.send (, sp.balance)

#clear out buyer and seller
def resetContract(self): = sp.none = sp.none = 0
@addTest(name = "Test Escrow")
def testEscrow():
html = ""
seller = "AAA"
buyer = "BBB"
myContract = Escrow() #set the seller and price
html += myContract.setSeller(price = 1).run(sp.address(seller), amount = sp.tez(2)).html()

#set the buyer
html += myContract.setBuyer().run(sp.address(buyer), amount = sp.tez(2)).html()

# buyer confirms they received item
html += myContract.confirmReceived().run(sp.address("BBB")).html()

# seller decides to refund buyer
# html += myContract.refundBuyer().run(sp.address(seller)).html()


Link to the script on

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade