feat: Created simple escrow contract

This commit is contained in:
Richard Ramos 2018-12-17 16:10:38 -04:00
parent dc4308c597
commit 3b29f750d0
3 changed files with 134 additions and 0 deletions

View File

@ -54,6 +54,9 @@ module.exports = {
contracts: {
License: {
args: [ "0x0", 1 ]
},
Escrow: {
args: ["$License"]
}
}
},

95
contracts/escrow.sol Normal file
View File

@ -0,0 +1,95 @@
pragma solidity ^0.5.0;
import "./ownable.sol";
import "./pausable.sol";
import "./license.sol";
/**
* @title Escrow
* @dev Escrow contract for buying/selling ETH. Current implementation lacks arbitrage, marking trx as paid, and ERC20 support
*/
contract Escrow is Pausable {
constructor(address _license) public {
license = License(_license);
}
struct EscrowTransaction {
address payable seller;
address payable buyer;
uint amount;
uint expirationTime;
bool released;
bool canceled;
}
EscrowTransaction[] public transactions;
License public license;
event Created(address indexed seller, address indexed buyer, uint amount, uint escrowId);
event Paid(uint escrowId);
event Canceled(uint escrowId);
function create(address payable _buyer, uint _expirationTime) public payable whenNotPaused {
require(_expirationTime > (block.timestamp + 600), "Expiration time must be at least 10min in the future");
require(msg.value > 0, "ETH amount is required"); // TODO: abstract this to use ERC20. Maybe thru the use of wETH
require(license.isLicenseOwners(msg.sender), "Must be a valid seller to create escrow transactions");
uint escrowId = transactions.length++;
transactions[escrowId].seller = msg.sender;
transactions[escrowId].buyer = _buyer;
transactions[escrowId].amount = msg.value;
transactions[escrowId].expirationTime = _expirationTime;
transactions[escrowId].released = false;
transactions[escrowId].canceled = false;
emit Created(msg.sender, _buyer, msg.value, escrowId);
}
function release(uint _escrowId) public whenNotPaused {
require(_escrowId < transactions.length, "Invalid escrow id");
EscrowTransaction storage trx = transactions[_escrowId];
require(trx.released == false, "Transaction already released");
require(trx.canceled == false, "Transaction already canceled");
require(trx.expirationTime > block.timestamp, "Transaction already expired");
require(trx.seller == msg.sender, "Function can only be invoked by the escrow owner");
trx.released = true;
trx.buyer.transfer(trx.amount); // TODO: transfer fee to Status
emit Paid(_escrowId);
}
function cancel(uint _escrowId) public whenNotPaused {
require(_escrowId < transactions.length, "Invalid escrow id");
EscrowTransaction storage trx = transactions[_escrowId];
require(trx.released == false, "Transaction already released");
require(trx.canceled == false, "Transaction already canceled");
require(trx.seller == msg.sender, "Function can only be invoked by the escrow owner");
trx.canceled = true;
trx.seller.transfer(trx.amount);
emit Canceled(_escrowId);
}
function withdraw_emergency(uint _escrowId) public whenPaused {
require(_escrowId < transactions.length, "Invalid escrow id");
EscrowTransaction storage trx = transactions[_escrowId];
require(trx.released == false, "Transaction already released");
require(trx.canceled == false, "Transaction already canceled");
trx.canceled = true;
trx.seller.transfer(trx.amount);
emit Canceled(_escrowId);
}
}

36
contracts/pausable.sol Normal file
View File

@ -0,0 +1,36 @@
pragma solidity ^0.5.0;
import "./ownable.sol";
contract Pausable is Ownable {
event Paused();
event Unpaused();
bool public paused;
constructor () internal {
paused = false;
}
modifier whenNotPaused() {
require(!paused, "Contract must be unpaused");
_;
}
modifier whenPaused() {
require(paused, "Contract must be paused");
_;
}
function pause() public onlyOwner whenNotPaused {
paused = true;
emit Paused();
}
function unpause() public onlyOwner whenPaused {
paused = false;
emit Unpaused();
}
}