Skip to content

Instantly share code, notes, and snippets.

@joemarct
Last active February 22, 2023 08:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joemarct/5bfe1a5e2a2c3cbc151d8497c34d670c to your computer and use it in GitHub Desktop.
Save joemarct/5bfe1a5e2a2c3cbc151d8497c34d670c to your computer and use it in GitHub Desktop.
pragma cashscript ^0.7.5;
/**
* @title Escrow Contract
* An escrow is a financial arrangement where a third party holds and regulates the payment
* of funds required for two parties involved in a transaction. The funds are held by the
* escrow service until it is confirmed that all of the terms of an agreement between the buyer
* and seller have been met, at which point the funds are released.
* @dev The arbiter is a person or entity that is appointed or selected to act as a neutral and
* impartial third party in a dispute or conflict.
* @dev The arbiter can transfer funds to only either the seller or buyer.
* @dev The seller has the authority to 'release' the funds directly to the buyer.
* @dev The seller can only 'release' the funds to the buyer and not to any other address.
* @dev The buyer cannot interact with the contract.
* @param arbiter The public key hash of arbiter.
* @param buyer The public key hash of buyer.
* @param seller The public key hash of seller.
*/
contract Escrow(bytes20 arbiter, bytes20 buyer, bytes20 seller) {
/**
* Releases the funds to the buyer.
* @dev Limits the number of input and output to 1.
* @dev Fails if the caller is neither the arbiter nor the seller.
* @dev Fails if the transaction amount is insufficient or incorrect.
* @dev Fails if the recipient is not buyer.
* @param pk The public key of the arbiter.
* @param s The signature of the arbiter.
*/
function release(pubkey pk, sig s) {
// Requires that caller is only either the arbiter or the seller
require(hash160(pk) == arbiter || hash160(pk) == seller);
require(checkSig(s, pk));
// Require input & output count to 1
require(tx.inputs.length == 1);
require(tx.outputs.length == 1);
// Checks that the correct amount is sent
int minerFee = 1000; // hardcoded fee
int amount = tx.inputs[this.activeInputIndex].value - minerFee;
require(tx.outputs[0].value == amount);
// Requires that recipient is buyer
bytes25 buyerLock = new LockingBytecodeP2PKH(buyer);
bool sendsToBuyer = tx.outputs[0].lockingBytecode == buyerLock;
require(sendsToBuyer);
}
/**
* Refunds the funds back to the seller.
* @dev Limits the number of input and output to 1.
* @dev Fails if caller is not arbiter.
* @dev Fails if amount is insufficient or incorrect.
* @dev Fails if the recipient is not the seller.
* @param pk The public key of the arbiter.
* @param s The signature of the arbiter.
*/
function refund(pubkey pk, sig s) {
// Requires that caller is the arbiter
require(hash160(pk) == arbiter);
require(checkSig(s, pk));
// Require input & output count to 1
require(tx.inputs.length == 1);
require(tx.outputs.length == 1);
// Checks that the correct amount is sent
int minerFee = 1000; // hardcoded fee
int amount = tx.inputs[this.activeInputIndex].value - minerFee;
require(tx.outputs[0].value == amount);
// Requires that recipient is seller
bytes25 sellerLock = new LockingBytecodeP2PKH(seller);
bool sendsToSeller = tx.outputs[0].lockingBytecode == sellerLock;
require(sendsToSeller);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment