Blockchain

Constructing an Ethereum Escrow Contract

Ethereum

We need a sophisticated escrow contract where the payment is to be split upon delivery of goods between the seller and the escrow (that gets a commission).

The escrow contract is deployed by the escrow which is the owner of the contract.

The buyer has to pay, upon which the seller should deliver the goods within a fixed time. If not delivered in time, the buyer is fully refunded. Otherwise, the buyer has a fixed time duration to approve or decline the goods. If neither approved nor declined, within the time frame, it is considered approved.

If the buyer declined the goods, it receives a full refund. If the buyer approved the goods, the payment is split between the escrow and the seller.

    
contract Escrow {

    bool wasPaid;
    bool wasSent;
    bool wasDelivered;
    bool commissionPaid;
    bool payoutPaid; 
    bool approved;

    uint256 timeToDeliver;
    uint256 timeToApprove;

    uint256 paymentTime; 

    uint256 commissionPercentage;

    address owner;
    address buyer;
    address seller;

    uint256 fee;
    uint256 payout;

    modifier canStillDeliver() {
            now < paymentTime + timeToDeliver;
          _;
    }

    modifier canStillApprove() {
            now < paymentTime + timeToDeliver + timeToApprove;
          _;
    }      

    modifier onlySeller() {
            require(msg.sender == seller);
            _;
    }

    modifier onlyBuyer() {
            require(msg.sender == buyer);
            _;
    }

    modifier onlyOwner() {
            require(msg.sender == owner);
            _;
    }    

    constructor(uint256 _timeToDeliver, uint256 _timeToApprove, address _buyer, address _seller, uint256 _commissionPercentage) public {
            timeToDeliver = _timeToDeliver;
            timeToApprove = _timeToApprove;
            buyer = _buyer;
            seller = _seller;
            commissionPercentage = _commissionPercentage;
    }

    // Buyer pays
    function pay() public payable {
            wasPaid = true;
            paymentTime = now;
    }

    // Seller sent the goods
    function sent() canStilDeliver onlySeller public {
            wasSent = true;
    }

    // Goods arrived and approved by buyer
    function arrived(bool _approved) canStillApprove onlyBuyer public {
          wasDelivered = true;
          if (_approved) {
            disburse();
          } 
    }

    // Split the money between the seller and the escrow
    function disburse() internal {
          fee = (this.balance).mul(commissionPercentage).div(100);
          payout = this.balance.sub(fee);  
    }

    //   Nothing sent in time, refund the buyer in full
    function expiredDeliver() onlyOwner public {
          require(!wasSent);
          buyer.transfer(this.balance);
    }

    // Buyer did not approve or decline in time, refund the buyer in full
    function expiredApproval() onlyOwner public {
          require(wasSent && !wasDelivered);
          wasDelivered = true;
          approved = true;
          disburse();
    }  

    // Seller gets paid 
    function redeemPayout() onlySeller public {
        require(wasDelivered && !payoutPaid && appproved);  
        payoutPaid = true;
        seller.transfer(payout); 
    }

    // Escrow gets its commission
    function redeemEscrow() onlyOwner public {
        require(wasDelivered && !commissionPaid && approved);  
        commissionPaid = true;
        owner.transfer(fee);
    }      

}

Yoram Kornatzky

Yoram Kornatzky