Created
July 5, 2017 11:43
-
-
Save JonnyLatte/43f3d1cc2f78906241c07d64631f23d5 to your computer and use it in GitHub Desktop.
cryptoderivatives research hard coded delagate call forwarded token seller
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.4.12; | |
// https://github.com/ethereum/EIPs/issues/20 | |
contract ERC20 { | |
event Transfer(address indexed from, address indexed to, uint value); | |
event Approval( address indexed owner, address indexed spender, uint value); | |
function totalSupply() constant returns (uint supply); | |
function balanceOf( address who ) constant returns (uint value); | |
function allowance(address owner, address spender) constant returns (uint _allowance); | |
function transfer( address to, uint value) returns (bool ok); | |
function transferFrom( address from, address to, uint value) returns (bool ok); | |
function approve(address spender, uint value) returns (bool ok); | |
} | |
contract Owned { | |
address public owner; | |
event OwnershipTransferred(address indexed _from, address indexed _to); | |
function Owned() { | |
owner = msg.sender; | |
} | |
modifier onlyOwner { | |
if (msg.sender != owner) throw; | |
_; | |
} | |
function transferOwnership(address newOwner) onlyOwner { | |
OwnershipTransferred(owner, newOwner); | |
owner = newOwner; | |
} | |
} | |
library SafeMath | |
{ | |
function safeMul(uint a, uint b) internal returns (uint) { | |
uint c = a * b; | |
require(a == 0 || c / a == b); | |
return c; | |
} | |
function safeDiv(uint a, uint b) internal returns (uint) { | |
require(b > 0); | |
uint c = a / b; | |
require(a == b * c + a % b); | |
return c; | |
} | |
function safeSub(uint a, uint b) internal returns (uint) { | |
require(b <= a); | |
return a - b; | |
} | |
function safeAdd(uint a, uint b) internal returns (uint) { | |
uint c = a + b; | |
require(c>=a && c>=b); | |
return c; | |
} | |
function max(uint a, uint b) internal constant returns (uint) { | |
return a >= b ? a : b; | |
} | |
function min(uint a, uint b) internal constant returns (uint) { | |
return a < b ? a : b; | |
} | |
} | |
// contract can sell tokens for ETH | |
// prices are in amount of wei per batch of token units | |
library sendToken { | |
function transferToken(address to, address token, uint amount) internal { | |
require(ERC20(token).transfer(to, amount)); | |
} | |
} | |
contract Seller | |
{ | |
using SafeMath for uint; | |
using sendToken for address; | |
uint public constant units = 1; | |
address public constant asset = 0x73e8fA3459E5aaF8E103E0f8d66EbEe531320dF0; | |
uint public unitPrice; | |
address public owner; | |
event OwnershipTransferred(address indexed _from, address indexed _to); | |
modifier onlyOwner { | |
if (msg.sender != owner) throw; | |
_; | |
} | |
function transferOwnership(address newOwner) onlyOwner { | |
OwnershipTransferred(owner, newOwner); | |
owner = newOwner; | |
} | |
event OnTrade(address taker, uint assetValueOfTrade); | |
// this contract is intended to be generated atomicly as a delegatcall forwarder | |
// this means that owner will not be set in the constructor | |
// init allows a one time initialzation of the contract's values | |
function init(address _owner, uint _unitPrice) { | |
require(owner == 0x0); | |
owner = _owner; | |
unitPrice = _unitPrice; | |
} | |
function makerWithdrawAsset(uint amount) onlyOwner | |
{ | |
owner.transferToken(asset,amount); | |
} | |
function makerWithdrawERC20Token(address tokenAddress, uint amount) onlyOwner | |
{ | |
owner.transferToken(tokenAddress,amount); | |
} | |
function makerWithdrawEther(uint256 amount) onlyOwner | |
{ | |
owner.transfer(amount); | |
} | |
function() payable | |
{ | |
// trades are done in unitLots where each lot represents a trade of "unit" amount of tokens for "unitPrice" amount of ether | |
// the most that can be traded is the amount of ether sent divided by the unitPrice or the amount of tokens available divided by the units | |
// whichever is lower | |
uint tradeLots = msg.value.safeDiv(unitPrice).min( ERC20(asset).balanceOf(address(this)).safeDiv(units) ); | |
uint etherValueOfTrade = tradeLots.safeMul(unitPrice); // the total ether value to be exchanged | |
uint assetValueOfTrade = tradeLots.safeMul(units); // the total token value to be exchanged | |
if(msg.value > etherValueOfTrade) // if the total ether value to be traded is smaller than what is sent return the rest as change | |
{ | |
msg.sender.transfer(msg.value - etherValueOfTrade); | |
} | |
if(assetValueOfTrade > 0) // tranfer the total token value of the trade to the buyer | |
{ | |
msg.sender.transferToken(asset,assetValueOfTrade); | |
OnTrade(msg.sender, assetValueOfTrade); | |
} | |
} | |
} | |
contract ForwardFactoryInterface { | |
function createForwarder(address target) returns (address fwdContract); | |
} | |
// This contract deploys TokenSeller contracts and logs the event | |
contract SellerFactory is Owned { | |
event TradeListing(address indexed ownerAddress, address tokenSellerAddress, uint sellPrice); | |
event OwnerWithdrewERC20Token(address indexed tokenAddress, uint tokens); | |
//address public fowardFactory = 0x2F9b71403ECb431d571A67456964090566566DA5; // kovan | |
function createSaleContract(uint sellPrice) returns (address seller) { | |
require(sellPrice != 0); | |
//seller = ForwardFactoryInterface(fowardFactory).createForwarder(templateContract); | |
assembly { | |
let contractCode := mload(0x40) // Find empty storage location using "free memory pointer" | |
//0x9c5b220A72F3664c1461390Ec30714bD8DAca561 --> kovan test token address ebedded in the 2 literals, along with the delagate call bytecodes | |
//see: https://www.reddit.com/r/ethdev/comments/6i5n66/delegatecall_forwarder_factories/djrfxs8/ | |
//deployment reqires making a hard coded seller deploying it then hard coding this address | |
//0x602e600c600039602e6000f3366000600037610100600036600073__________ | |
mstore(contractCode, 0x602e600c600039602e6000f33660006000376101006000366000739c5b220A72) // First part of the bytecode, shifted left 5 bytes | |
//0x______________________________5af41558576101006000f3000000000000 | |
mstore(add(contractCode, 0x20), 0xF3664c1461390Ec30714bD8DAca5615af41558576101006000f3000000000000) // Final part of bytec | |
seller := create(0, contractCode, 0x3A) // total length 58 dec = 3a | |
switch extcodesize(seller) case 0 { invalid() } | |
} | |
Seller(seller).init(msg.sender,sellPrice); | |
// Record that this factory created the trader | |
TradeListing(msg.sender, seller, sellPrice); | |
} | |
function ownerWithdrawERC20Token(address tokenAddress, uint tokens) onlyOwner returns (bool ok) { | |
OwnerWithdrewERC20Token(tokenAddress, tokens); | |
return ERC20(tokenAddress).transfer(owner, tokens); | |
} | |
// Prevents accidental sending of ether to the factory | |
function () { | |
throw; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment