i want to build escrow smart contract with one particular ERC20 standard token. i want to hold token in escrow as a guarantee for transaction. and on some condition those tokens should go back to sellers account.

so in my app party A is use some services of party B but party B is not trusted so party B will keep some token in escrow and after some condition party B will get those tokens back. its like one way transaction escrow.

but what conditions we can use like if condition. also Can i send tokens to smartContract and if i can then how to send those tokens back to Party B's wallet or how to send received tokens from escrow smartcontract to any wallet owner person

and if i am the owner of the tokens and i am not able to understand who can deploy escrow.cause if i deploy escrow and im the owner of the tokens then i can go to that token function and use transferfrom() function and use escrow address to get back my tokens so how to prevent this question.so how to safely lock those tokens in escrow. because almost 90% tutorials are about ether not about tokens on ethers.

2 Answers 2


I'm having a bit difficulties following your writing, so I'll make this a bit more generalized.

If you are the one who released the token then you have decided how the tokens can be transferred. Most likely you as the contract owner have full power to transfer any amount of tokens to whoever you wish, or maybe even remove tokens from someone (yes, tokens can be removed as they only exist within the same contract, they are never actually 'sent' anywhere).

So if you have full power over the tokens you can just do whatever you want with them - hold some in any sort of escrow for example if your contract supports such functionality.

If you did not create the token contract (but it was created by someone else) you can act as an escrow and get the tokens transferred to your account. When the escrow service is no longer needed, you can either authorize (approve function in ERC20) the transfer back to someone or directly transfer them with the transfer function.


We created a solution for escrow functionality for ERC20 tokens.

The code we used is as follows.

pragma solidity ^0.4.21;

import "../zeppelin-solidity/contracts/token/ERC20/ERC20.sol";
import "../zeppelin-solidity/contracts/ownership/Ownable.sol";
import "../webshop/Webshop.sol";

contract Escrow is Ownable {
    enum PaymentStatus { Pending, Completed, Refunded }

    event PaymentCreation(uint indexed orderId, address indexed customer, uint value);
    event PaymentCompletion(uint indexed orderId, address indexed customer, uint value, PaymentStatus status);

    struct Payment {
        address customer;
        uint value;
        PaymentStatus status;
        bool refundApproved;

    mapping(uint => Payment) public payments;
    ERC20 public currency;
    address public collectionAddress;
    Webshop public webshop;

    function Escrow(ERC20 _currency, address _collectionAddress) public {
        currency = _currency;
        collectionAddress = _collectionAddress;
        webshop = Webshop(msg.sender);

    function createPayment(uint _orderId, address _customer, uint _value) external onlyOwner {
        payments[_orderId] = Payment(_customer, _value, PaymentStatus.Pending, false);
        emit PaymentCreation(_orderId, _customer, _value);

    function release(uint _orderId) external {
        completePayment(_orderId, collectionAddress, PaymentStatus.Completed);

    function refund(uint _orderId) external {
        completePayment(_orderId, msg.sender, PaymentStatus.Refunded);

    function approveRefund(uint _orderId) external {
        require(msg.sender == collectionAddress);
        Payment storage payment = payments[_orderId];
        payment.refundApproved = true;

    function completePayment(uint _orderId, address _receiver, PaymentStatus _status) private {
        Payment storage payment = payments[_orderId];
        require(payment.customer == msg.sender);
        require(payment.status == PaymentStatus.Pending);
        if (_status == PaymentStatus.Refunded) {
        currency.transfer(_receiver, payment.value);
        webshop.changeOrderStatus(_orderId, Webshop.OrderStatus.Completed);
        payment.status = _status;
        emit PaymentCompletion(_orderId, payment.customer, payment.value, _status);

The article, including the code can be found on https://medium.com/@s_van_laar/how-to-build-an-escrow-contract-with-an-ethereum-erc20-token-bfc4825b0dd7

  • Link-only answers are discouraged. Please include enough in the body of your answer that it is still useful and relevent even if all links are broken. May 2, 2018 at 14:14
  • @TjadenHess Entered the code and referred to the original article. Please remove the -1
    – Sander
    Jun 26, 2018 at 8:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.