Created
August 1, 2019 20:38
-
-
Save crypto-perry/1911fb502a472884dd76ee4cf35172ec 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.5.1+commit.c8a2cb62.js&optimize=true&gist=
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.5.0; | |
import './tradeoracleinterface.sol'; | |
contract FuturesEscrow { | |
enum TradeState {None, Filled, Closed} | |
event Deposit(address account, uint256 amount); | |
event Withdrawal(address account, uint256 amount); | |
event CompletedTrade(bytes32 tradeId, bytes32 buyer, uint256 amount); | |
event NewTrade(bytes32 tradeId, address indexed buyer, address indexed seller, uint256 price, uint256 deposit, uint256 amount, uint256 expiration); | |
struct Trade { | |
address payable buyer; | |
address payable seller; | |
uint256 price; | |
uint256 deposit; | |
uint256 amount; | |
uint256 expiration; | |
TradeState state; | |
} | |
mapping (bytes32 => Trade) public trades; | |
mapping (address => uint256) public balances; | |
mapping (address => bytes32) public addrOnOther; // hashes of user's address on other blockchain (the hash of a string) | |
TradeOracle tradeVerifier; | |
address owner; | |
modifier onlyOwner { | |
require(msg.sender == owner); | |
_; | |
} | |
constructor() public { | |
owner = msg.sender; | |
} | |
function setTradeVerifier(address tradeOracle) public onlyOwner { | |
tradeVerifier = TradeOracle(tradeOracle); | |
} | |
function completeTrade(bytes32 tradeId) public { | |
Trade memory trade = trades[tradeId]; | |
require(trade.state == TradeState.Filled); | |
require(trade.expiration > now); | |
require(tradeVerifier.recordSale(addrOnOther[trade.seller], trade.amount)); | |
trades[tradeId].state = TradeState.Closed; | |
balances[owner] += computeFee(trade.price) * 2; // change our balance | |
emit CompletedTrade(tradeId, addrOnOther[trade.buyer], trade.amount); | |
trade.seller.transfer(trade.deposit + trade.price); | |
} | |
function expireTrade(bytes32 tradeId) public onlyOwner { | |
Trade memory trade = trades[tradeId]; | |
require(trade.state == TradeState.Filled); | |
require(trade.expiration < now); | |
trades[tradeId].state = TradeState.Closed; | |
balances[owner] += computeFee(trade.price) * 2; // change our balance | |
emit CompletedTrade(tradeId, addrOnOther[trade.seller], trade.amount); | |
trade.buyer.transfer(trade.deposit + trade.price); | |
} | |
function linkOtherAddress(string memory addr) public { | |
require(addrOnOther[msg.sender] == 0); | |
addrOnOther[msg.sender] = keccak256(abi.encodePacked(addr)); | |
} | |
function linkOtherAddress(address ethAddress, string memory addr) public onlyOwner { | |
addrOnOther[ethAddress] = keccak256(abi.encodePacked(addr)); | |
} | |
function() external payable { | |
balances[msg.sender] += msg.value; | |
emit Deposit(msg.sender, msg.value); | |
} | |
// Anyone (including us) can only withdraw the amount allocated in balances. | |
// So we can only ever take the fees. | |
function withdraw(uint256 amount) public { | |
require(balances[msg.sender] >= amount); | |
balances[msg.sender] -= amount; | |
msg.sender.transfer(amount); | |
emit Withdrawal(msg.sender, amount); | |
} | |
// Anyone (including us) can only withdraw the amount allocated in balances. | |
// So we can only ever take the fees. | |
function withdrawFor(address payable user, uint256 amount) public onlyOwner { | |
require(balances[user] >= amount); | |
balances[user] -= amount; | |
user.transfer(amount); | |
emit Withdrawal(user, amount); | |
} | |
function makeTrade(bytes32 tradeId, address payable buyer, address payable seller, uint256 price, uint256 deposit, uint256 amount, uint256 expireAfter) public onlyOwner { | |
require(trades[tradeId].state == TradeState.None); | |
require(buyer != seller); | |
uint256 fee = computeFee(price); | |
require(balances[buyer] >= price + fee); | |
require(balances[seller] >= deposit + fee); | |
balances[buyer] -= (price + fee); // change buyer balance | |
balances[seller] -= (deposit + fee); // change seller balance | |
// notice how the fees are not accounted for here, they will be given to us only when the trade is complete or expired. | |
uint256 expiration = now + (expireAfter * 1 hours); | |
trades[tradeId] = Trade(buyer, seller, price, deposit, amount, expiration, TradeState.Filled); | |
emit NewTrade(tradeId, buyer, seller, price, deposit, amount, expiration); | |
} | |
function computeFee(uint256 price) private pure returns (uint256) { | |
uint256 fee = price * 5; | |
require(fee / 5 == price); // Check overflow | |
return fee / 1000; // This is the fee we take on each side (0.5% * price) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.5.0; | |
import './tradeoracleinterface.sol'; | |
contract ManualTradeVerifier is TradeOracle { | |
constructor(address escrow) TradeOracle(escrow) public {} | |
function registerDepositManually(bytes32 seller, uint256 amount) public onlyOwner { | |
balances[seller] += amount; | |
} | |
function forceDecreaseBalance(bytes32 seller, uint256 amount) public onlyOwner { | |
balances[seller] -= amount; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.5.0; | |
contract OtcButlerEventStorage { | |
event Deposit(address account, uint256 amount); | |
event Withdrawal(address account, uint256 amount); | |
struct Trade { | |
address payable buyer; | |
address payable seller; | |
uint256 price; | |
uint256 deposit; | |
uint256 amount; | |
uint256 expiration; | |
TradeState state; | |
} | |
mapping (bytes32 => Trade) trades; | |
mapping (address => uint256) balances; | |
mapping (address => bytes32) hashAddresses; | |
TradeOracle tradeVerifier; | |
address owner; | |
modifier onlyOwner { | |
require(msg.sender == owner); | |
_; | |
} | |
constructor() public { | |
owner = msg.sender; | |
} | |
function setTradeVerifier(address tradeOracle) public onlyOwner { | |
tradeVerifier = TradeOracle(tradeOracle); | |
} | |
function completeTrade(bytes32 tradeId, bytes memory proof) public { | |
Trade memory trade = trades[tradeId]; | |
require(trade.state == TradeState.Filled); | |
require(trade.expiration > now); | |
require(tradeVerifier.verifyTrade(hashAddresses[trade.buyer], hashAddresses[trade.seller], trade.amount, tradeId, proof)); | |
trades[tradeId].state = TradeState.Closed; | |
balances[owner] += computeFee(trade.price) * 2; // change our balance | |
trade.seller.transfer(trade.deposit + trade.price); | |
} | |
function expireTrade(bytes32 tradeId) public onlyOwner { | |
Trade memory trade = trades[tradeId]; | |
require(trade.state == TradeState.Filled); | |
require(trade.expiration < now); | |
trades[tradeId].state = TradeState.Closed; | |
balances[owner] += computeFee(trade.price) * 2; // change our balance | |
trade.buyer.transfer(trade.deposit + trade.price); | |
} | |
function linkHashAddress(bytes32 addressHash) public { | |
require(hashAddresses[msg.sender] == 0); | |
hashAddresses[msg.sender] = addressHash; | |
} | |
function linkHashAddress(address ethAddress, bytes32 addressHash) public onlyOwner { | |
hashAddresses[ethAddress] = addressHash; | |
} | |
function() external payable { | |
balances[msg.sender] += msg.value; | |
emit Deposit(msg.sender, msg.value); | |
} | |
// Anyone (including us) can only withdraw the amount allocated in balances. | |
// So we can only ever take the fees. | |
function withdraw(uint256 amount) public { | |
require(balances[msg.sender] >= amount); | |
balances[msg.sender] -= amount; | |
msg.sender.transfer(amount); | |
emit Withdrawal(msg.sender, amount); | |
} | |
// Anyone (including us) can only withdraw the amount allocated in balances. | |
// So we can only ever take the fees. | |
function withdraw(address payable user, uint256 amount) public onlyOwner { | |
require(balances[user] >= amount); | |
balances[user] -= amount; | |
user.transfer(amount); | |
emit Withdrawal(user, amount); | |
} | |
function makeTrade(bytes32 tradeId, address payable buyer, address payable seller, uint256 price, uint256 deposit, uint256 amount, uint256 expireAfter) public onlyOwner { | |
uint256 fee = computeFee(price); | |
require(balances[buyer] >= price + fee); | |
require(balances[seller] >= deposit + fee); | |
require(trades[tradeId].state == TradeState.None); | |
balances[buyer] -= (price + fee); // change buyer balance | |
balances[seller] -= (deposit + fee); // change seller balance | |
// notice how the fees are not accounted for here, they will be given to us only when the trade is complete or expired. | |
trades[tradeId] = Trade(buyer, seller, price, deposit, amount, now + (expireAfter * 1 hours), TradeState.Filled); | |
} | |
function computeFee(uint256 price) private pure returns (uint256) { | |
uint256 fee = price * 5; | |
require(fee / 5 == price); // Check overflow | |
return fee / 1000; // This is the fee we take on each side (0.5% * price) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.5.0; | |
contract TradeOracle { | |
mapping (bytes32 => uint256) balances; | |
address owner; | |
address escrowContract; | |
modifier onlyOwner { | |
require(msg.sender == owner); | |
_; | |
} | |
modifier onlyEscrow { | |
require(msg.sender == escrowContract); | |
_; | |
} | |
constructor(address escrow) public { | |
owner = msg.sender; | |
escrowContract = escrow; | |
} | |
function setEscrowContract(address escrow) public onlyOwner { | |
escrowContract = escrow; | |
} | |
function recordSale(bytes32 seller, uint256 amount) external onlyEscrow returns (bool) { | |
require(balances[seller] >= amount); | |
balances[seller] -= amount; | |
return true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment