Skip to content

Instantly share code, notes, and snippets.

@RyanHendricks
Created May 17, 2018 17:22
Show Gist options
  • Save RyanHendricks/83d314e31f12cc0e25ac8dcf1d333609 to your computer and use it in GitHub Desktop.
Save RyanHendricks/83d314e31f12cc0e25ac8dcf1d333609 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.4.24+commit.e67f0147.js&optimize=true&gist=
pragma solidity ^0.4.22;
contract escrow {
address public buyer;
address public seller;
bool public initiated;
bool public finalized;
uint public sellerFunded;
uint public buyerFunded;
uint public sellerExpReceivable;
uint public buyerExpReceivable;
modifier notInitiated() {
require(initiated == false);
_;
}
modifier onlyBuyer() {
require(buyer == msg.sender);
_;
}
modifier onlySeller() {
require(seller == msg.sender);
_;
}
function escrow() {
finalized = false;
initiated = false;
}
function buyerInitiate(address _seller) public notInitiated {
buyer = msg.sender;
seller = _seller;
initiated = true;
}
function sellerInitiate(address _buyer) public notInitiated {
seller = msg.sender;
buyer = _buyer;
initiated = true;
}
function sellerAddETH(uint _expectedReceivable) public onlySeller payable {
if (sellerFunded > 0) {
revert();
}
sellerFunded = msg.value;
sellerExpReceivable = _expectedReceivable;
}
function buyerAddETH(uint _expectedReceivable) public onlyBuyer payable {
if (buyerFunded > 0) {
revert();
}
buyerFunded = msg.value;
buyerExpReceivable = _expectedReceivable;
}
function completeTrade() public {
if (buyerFunded == 0 || sellerFunded == 0) {
revert();
}
if (buyerFunded >= sellerExpReceivable && sellerFunded >= buyerExpReceivable) {
seller.transfer(sellerExpReceivable);
buyer.transfer(buyerExpReceivable);
seller.transfer(sellerFunded - buyerExpReceivable);
buyer.transfer(sellerFunded - buyerExpReceivable);
}
}
}
pragma solidity ^0.4.16;
// @title VeoEscrow -- trustless escrow smart contract for VEO<->ETH swaps
// @author ryanhendricks@gmail.com
/**
* This escrow contract uses a similar mechanism as the MAD escrow protocol.
* MAD = mutually assured destruction. The significance of this title is that
* both the buyer and seller are disincentivized to cheat since neither would
* be able to take actions that would harm the other party without also harming
* themselves to an equal extent.
*
* Imagine this scenario:
* Buyer A wants to purchase some VEO from Seller B using ETH. Let's assume
* that the 2 parties agree to make the trade for 10 VEO in exchange for 5 ETH.
* Who sends first? or do they use an escrow service?
* Without a trusted third party one of the parties will be taking on a large risk.
*
* The escrow contract eliminates the need for a 3rd party and works as follows:
* - BOTH Buyer A and Seller B deposit 5 ETH into the escrow contract.
* - Buyer A deposits an additional 5 ETH (or all 10 at once to save in txn fees).
* - Seller B sends the 10 VEO to Buyer A and Finalizes the escrow contract.
* - Buyer A confirms the receipt of VEO and also Finalizes the escrow contract.
* - Seller B receives their 5 ETH deposit and 5 ETH from Buyer A.
* - Buyer A receives their 5 ETH deposit.
* - If either party does not finalize then neither party receives any of the funds.
*
* Now let's imagine that either the buyer or the seller has bad intentions.
* Since BOTH parties must sign off to finalize the escrow otherwise BOTH lose their
* funds in the escrow contract they are disincentivized from not doing the right thing.
* If Buyer A receives the VEO but doesn't finalize then they will have paid 2x the original
* amount agreed upon in trade.
* If Seller B doesn't send the VEO they will lose the amount they would have received for
* the VEO in addition to not getting paid.
*
*
*/
contract VeoEscrow {
// Party A is the Buyer and Party B is the seller.
// The assignments are determined when calling initialize function
address public partyA; //BUYER
address public partyB; //SELLER
// Quantity of ETH being transferred to seller as agreed
// on by buyer and seller upon initiating the escrow contract.
uint256 public purchaseAmountTotal;
bool public initiated;
bool public finalized;
// Blocknumber at contract creation
uint public createdBlock;
// mutualEscrowAmount is the funds provided by BOTh
// buyer and seller in excess of the funds used for
// the actual trade/purchase
// this value should equal the purchase amount
uint256 public mutualEscrowAmount;
// Required funding quantity to execute trade
uint256 public partyArequiredFunding;
uint256 public partyBrequiredFunding;
// Buyer and seller current funding amounts
uint256 public partyAFundedAmount;
uint256 public partyBFundedAmount;
// set to TRUE when BOTH buyer and seller
// have funded contract in excess of respective requirements
bool public escrowFullyFunded;
// Once funded, both parties must finalize the trade/sale
bool public partyAfinalize;
bool public partyBfinalize;
event Initiated(address buyer, address seller, uint escrow, uint block);
// check to make sure contract not currently initiated
modifier notInitiated() {
require(initiated == false);
_;
}
modifier onlyPartyA() {
require(partyA == msg.sender);
_;
}
modifier onlyPartyB() {
require(partyB == msg.sender);
_;
}
modifier bothParties() {
require(partyA != msg.sender || partyB != msg.sender);
_;
}
modifier isTrueSender() {
require(msg.sender == tx.origin);
_;
}
// check to ensure contract is fully funded
// 1 - escrowFullyFunded bool should be true
// 2 - the sum of all funds should not be less
// than three times the mutualEscrowAmount
modifier isFullyFunded() {
require(escrowFullyFunded);
uint256 sum = partyAFundedAmount + partyBFundedAmount;
if (sum < mutualEscrowAmount * 3) {
revert();
}
_;
}
// Constructor
function escrow() {
finalized = false;
initiated = false;
createdBlock = block.number;
escrowFullyFunded = false;
}
/**
* @dev Initiate the escrow contract and allow funds to be sent for escrow
* @param _counterParty address of the other party for the trade
* @param _purchaseAmount uint256 amount of ETH to be paid for VEO
* @param _buyingNotSelling bool indicating whether initiator is buyer or seller
*/
function Initiate(
address _counterParty,
uint256 _purchaseAmount,
bool _buyingNotSelling // TRUE if Buyer; FALSE if seller;
)
notInitiated
isTrueSender
public returns
(bool) {
purchaseAmountTotal = _purchaseAmount;
mutualEscrowAmount = _purchaseAmount * 3;
if (_buyingNotSelling == true) {
partyA = msg.sender; //Buyer
partyB = _counterParty; //Seller
partyArequiredFunding = _purchaseAmount * 2;
partyBrequiredFunding = _purchaseAmount;
} else if (_buyingNotSelling == false) {
partyA = _counterParty; //Buyer
partyB = msg.sender; //Seller
partyArequiredFunding = _purchaseAmount;
partyBrequiredFunding = _purchaseAmount * 2;
} else {
revert(); // Fallback
}
initiated = true;
return true;
}
// fund contract function to be called by both parties when sending
// ETH to the contract and also check if fully funded after funds received
function fundContract()
bothParties
isTrueSender
public payable returns (bool fullyFunded) {
if (partyA == msg.sender) {
uint256 amountA = partyAFundedAmount;
partyAFundedAmount = amountA + msg.value;
}
else if (partyB == msg.sender) {
uint256 amountB = partyBFundedAmount;
partyBFundedAmount = amountB + msg.value;
} else {
revert();
}
return checkFundingStatus();
}
// dev tool - delete for production
function simulatefundContract(address _sender, uint _amount)
public returns (bool fullyFunded) {
if (_sender == partyA) {
uint256 amountA = partyAFundedAmount;
partyAFundedAmount = amountA + _amount;
}
if (_sender == partyB) {
uint256 amountB = partyBFundedAmount;
partyBFundedAmount = amountB + _amount;
}
checkFundingStatus();
return true;
}
// @dev internal function to check funding status
// @dev if both buyer and seller have sent enough ETH
// as per required amounts than set escrowFullyFunded to true
function checkFundingStatus() internal returns(bool) {
if (partyAFundedAmount < partyArequiredFunding) {
revert();
}
else if (partyBFundedAmount < partyBrequiredFunding) {
revert();
} else if (partyBFundedAmount > partyBrequiredFunding && partyAFundedAmount > partyArequiredFunding) {
escrowFullyFunded = true;
return true;
}
else {
return false;
}
}
// @dev Once fully funded, both parties must finalize the transaction
// @dev and once both finalizations are received the funds are released accordingly
function completeTrade() bothParties isFullyFunded public returns (bool) {
if (partyA == msg.sender) {
partyAfinalize = true;
} else if (partyB == msg.sender) {
partyBfinalize = true;
} else {
revert();
}
if (partyBfinalize == true && partyAfinalize == true) {
finalized = checkFundingStatus();
}
// Transfer both escrow excess funds back to buyer and seller
// Then selfdestruct contract with remaining funds sent to the buyer to
// protect the buyer from seller attempting to finalize prior to sending
// deliverable or having not funded their excess escrow requirement.
if (finalized == true && partyBfinalize == true && partyBfinalize == true) {
partyB.transfer(partyAFundedAmount);
partyA.transfer(partyBFundedAmount);
selfdestruct(partyA);
}
}
}
pragma solidity ^0.4.16;
// @title VeoEscrow -- trustless escrow smart contract for VEO<->ETH swaps
// @author ryanhendricks@gmail.com
/**
* This escrow contract uses a similar mechanism as the MAD escrow protocol.
* MAD = mutually assured destruction. The significance of this title is that
* both the buyer and seller are disincentivized to cheat since neither would
* be able to take actions that would harm the other party without also harming
* themselves to an equal extent.
*
* Imagine this scenario:
* Buyer A wants to purchase some VEO from Seller B using ETH. Let's assume
* that the 2 parties agree to make the trade for 10 VEO in exchange for 5 ETH.
* Who sends first? or do they use an escrow service?
* Without a trusted third party one of the parties will be taking on a large risk.
*
* The escrow contract eliminates the need for a 3rd party and works as follows:
* - BOTH Buyer A and Seller B deposit 5 ETH into the escrow contract.
* - Buyer A deposits an additional 5 ETH (or all 10 at once to save in txn fees).
* - Seller B sends the 10 VEO to Buyer A and Finalizes the escrow contract.
* - Buyer A confirms the receipt of VEO and also Finalizes the escrow contract.
* - Seller B receives their 5 ETH deposit and 5 ETH from Buyer A.
* - Buyer A receives their 5 ETH deposit.
* - If either party does not finalize then neither party receives any of the funds.
*
* Now let's imagine that either the buyer or the seller has bad intentions.
* Since BOTH parties must sign off to finalize the escrow otherwise BOTH lose their
* funds in the escrow contract they are disincentivized from not doing the right thing.
* If Buyer A receives the VEO but doesn't finalize then they will have paid 2x the original
* amount agreed upon in trade.
* If Seller B doesn't send the VEO they will lose the amount they would have received for
* the VEO in addition to not getting paid.
*
*
*/
contract VeoEscrow {
// Party A is the Buyer and Party B is the seller.
// The assignments are determined when calling initialize function
address public partyA; //BUYER
address public partyB; //SELLER
// Quantity of ETH being transferred to seller as agreed
// on by buyer and seller upon initiating the escrow contract.
uint256 public purchaseAmountTotal;
bool public initiated;
bool public finalized;
// Blocknumber at contract creation
uint public createdBlock;
// mutualEscrowAmount is the funds provided by BOTh
// buyer and seller in excess of the funds used for
// the actual trade/purchase
// this value should equal the purchase amount
uint256 public mutualEscrowAmount;
// Required funding quantity to execute trade
uint256 public partyArequiredFunding;
uint256 public partyBrequiredFunding;
// Buyer and seller current funding amounts
uint256 public partyAFundedAmount;
uint256 public partyBFundedAmount;
// set to TRUE when BOTH buyer and seller
// have funded contract in excess of respective requirements
bool public escrowFullyFunded;
// Once funded, both parties must finalize the trade/sale
bool public partyAfinalize;
bool public partyBfinalize;
event Initiated(address buyer, address seller, uint escrow, uint block);
// check to make sure contract not currently initiated
modifier notInitiated() {
require(initiated == false);
_;
}
modifier onlyPartyA() {
require(partyA == msg.sender);
_;
}
modifier onlyPartyB() {
require(partyB == msg.sender);
_;
}
modifier bothParties() {
require(partyA == msg.sender || partyB == msg.sender);
_;
}
modifier isTrueSender() {
require(msg.sender == tx.origin);
_;
}
// check to ensure contract is fully funded
// 1 - escrowFullyFunded bool should be true
// 2 - the sum of all funds should not be less
// than three times the mutualEscrowAmount
modifier isFullyFunded() {
require(escrowFullyFunded == true);
_;
}
// Constructor
constructor(VeoEscrow) {
finalized = false;
initiated = false;
createdBlock = block.number;
escrowFullyFunded = false;
}
/**
* @dev Initiate the escrow contract and allow funds to be sent for escrow
* @param _counterParty address of the other party for the trade
* @param _purchaseAmount uint256 amount of ETH to be paid for VEO
* @param _buyingNotSelling bool indicating whether initiator is buyer or seller
*/
function Initiate(
address _counterParty,
uint256 _purchaseAmount,
bool _buyingNotSelling // TRUE if Buyer; FALSE if seller;
)
notInitiated
isTrueSender
public returns
(bool) {
purchaseAmountTotal = _purchaseAmount;
mutualEscrowAmount = _purchaseAmount * 3;
if (_buyingNotSelling == true) {
partyA = msg.sender; //Buyer
partyB = _counterParty; //Seller
partyArequiredFunding = _purchaseAmount * 2;
partyBrequiredFunding = _purchaseAmount;
} else if (_buyingNotSelling == false) {
partyA = _counterParty; //Buyer
partyB = msg.sender; //Seller
partyArequiredFunding = _purchaseAmount;
partyBrequiredFunding = _purchaseAmount * 2;
} else {
revert(); // Fallback
}
initiated = true;
return true;
}
// fund contract function to be called by both parties when sending
// ETH to the contract and also check if fully funded after funds received
function fundContract()
bothParties
isTrueSender
public payable returns (bool fullyFunded) {
if (partyA == msg.sender && partyAFundedAmount < partyArequiredFunding) {
uint256 amountA = partyAFundedAmount;
partyAFundedAmount = amountA + msg.value;
}
else if (partyB == msg.sender && partyBFundedAmount < partyBrequiredFunding) {
uint256 amountB = partyBFundedAmount;
partyBFundedAmount = amountB + msg.value;
} else {
revert();
}
return checkFundingStatus();
}
// dev tool - delete for production
function simulatefundContract(address _sender, uint _amount)
public returns (bool fullyFunded) {
if (_sender == partyA) {
uint256 amountA = partyAFundedAmount;
partyAFundedAmount = amountA + _amount;
}
if (_sender == partyB) {
uint256 amountB = partyBFundedAmount;
partyBFundedAmount = amountB + _amount;
}
return checkFundingStatus();
}
// @dev internal function to check funding status
// @dev if both buyer and seller have sent enough ETH
// as per required amounts than set escrowFullyFunded to true
function checkFundingStatus() public returns(bool) {
if (partyAFundedAmount > partyArequiredFunding && partyBFundedAmount > partyBrequiredFunding ) {
escrowFullyFunded = true;
}
return(escrowFullyFunded);
}
// @dev Once fully funded, both parties must finalize the transaction
// @dev and once both finalizations are received the funds are released accordingly
function completeTrade() public returns (bool) {
address _sender = msg.sender;
if (_sender == partyA) {
partyAfinalize = true;
}
if (_sender == partyB) {
partyBfinalize = true;
}
if (partyBfinalize == true && partyAfinalize == true) {
finalized = true;
finalize();
}
}
// Transfer both escrow excess funds back to buyer and seller
// Then selfdestruct contract with remaining funds sent to the buyer to
// protect the buyer from seller attempting to finalize prior to sending
// deliverable or having not funded their excess escrow requirement.
function finalize() internal {
if (finalized == true && partyBfinalize == true && partyBfinalize == true) {
// partyB.transfer(partyAFundedAmount);
// partyA.transfer(partyBFundedAmount);
// partyA.transfer(address(this).balance);
createdBlock = 1337;
}
}
}
pragma solidity ^0.4.22;
contract blockTime {
// block time stamp at conctract creation
uint public timeStamp;
constructor(blockTime) {
timeStamp = block.timestamp;
}
function getTimeStamp() public view returns (uint) {
return block.timestamp;
}
function getTimeElapsed() public view returns (uint) {
return block.timestamp - timeStamp;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment