Skip to content

Instantly share code, notes, and snippets.

@JonnyLatte
Created July 5, 2017 11:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JonnyLatte/43f3d1cc2f78906241c07d64631f23d5 to your computer and use it in GitHub Desktop.
Save JonnyLatte/43f3d1cc2f78906241c07d64631f23d5 to your computer and use it in GitHub Desktop.
cryptoderivatives research hard coded delagate call forwarded token seller
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