Skip to content

Instantly share code, notes, and snippets.

@bitcoinwarrior1
Created August 21, 2020 14:12
Show Gist options
  • Save bitcoinwarrior1/bf18c19fbfd82e0f0e857c160c1c0c74 to your computer and use it in GitHub Desktop.
Save bitcoinwarrior1/bf18c19fbfd82e0f0e857c160c1c0c74 to your computer and use it in GitHub Desktop.
/*
This contract is a POC that allows anyone to buy a crypto pair like DAI:ETH via a signed order from a market maker.
Example:
Alice is a crypto whale with a lot of ETH and is willing to sell that ETH for DAI
Bob is a HODLER that wants to buy DAI:ETH once it hits a certain price.
- Alice and Bob are willing to trade at 1 ETH to 200 DAI so Bob sends a request to alice to buy 1 eth for 200 dai
- Alice's bot automatically accepts this offer as it hits her desired price range so she signs a message that states "Sell 1 ETH from my balance to Bob for 200 DAI, expiring in 5 minutes"
- Bob receives the approved request and submits it to this contract within the expiry. 200 DAI is deducted from his balance and 1 ETH is deducted from Alice's balance.
*/
pragma solidity ^0.5.11;
interface Token {
function allowance(address _owner, address _spender) external view returns (uint256 remaining);
function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);
}
contract BuyPairsWithSignedOrders {
constructor() public {
}
/*
Swap a pair like ETH:DAI via a signed order
@Requires this contract is approved to move funds from the buyer and seller
@Param pair1 the address of the asset that the seller wishes to sell
@Param pair2 the address of the asset that the buyer is willing to use to buy the sellers asset
@Param the amount of pair1 that the seller is willing to sell
@Param the price of pair1 in relation to pair2
@Param expiry, the timestamp for which this deal must be executed within (in block time)
@Param v: signature param for signed message
@Param r: signature param for signed message
@Param s: signature param for signed message
*/
function swapPair(
address pair1,
address pair2,
uint256 amount,
uint256 price,
uint256 expiry,
uint8 v,
bytes32 r,
bytes32 s
) public returns(bool) {
//order cannot be expired
require(expiry >= block.timestamp);
bytes32 messageHash = keccak256(abi.encodePacked(pair1, pair2, price, msg.sender));
address seller = ecrecover(messageHash, v, r, s);
Token tokenPair1 = Token(pair1);
Token tokenPair2 = Token(pair2);
//check that the seller has enough to sell and has approved this contract to move the funds
require(tokenPair1.allowance(seller, address(this)) >= amount);
//check that the buyer has enough to buy and has approved this contract to move the funds
require(tokenPair2.allowance(msg.sender, address(this)) >= (amount * price));
//do trade
require(tokenPair1.transferFrom(seller, msg.sender, amount));
require(tokenPair2.transferFrom(msg.sender, seller, (amount * price)));
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment