Address Contract Partially Verified
Address
0xaA5bBD5A177A588b9F213505cA3740b444Dbd586
Balance
4.6877 ETH
Nonce
1
Code Size
6594 bytes
Creator
0x23cc32A2...8F99 at tx 0x4914e62c...c93ba9
Indexed Transactions
0
Contract Bytecode
6594 bytes
0x6080604052600436106101325763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166322fdd3ea81146101375780632453ffa81461018257806341f9377f14610197578063514fcac7146101b457806353e1a7a0146101cc57806361d027b3146101e15780636fb768e81461021257806378d067dd1461022757806387bda8f21461024257806389a447e01461025a578063a4ff9c341461026f578063c0ee0b8a1461027a578063c49063e7146102e3578063c655de64146102fe578063cb2bb26414610313578063cf6ff1731461032d578063d4fac45d14610354578063d6e435851461037b578063e3319e82146103a7578063eeb3377a146103c9578063f2037fec146103f9578063fc5f42411461040e578063ff700e5214610423575b600080fd5b34801561014357600080fd5b50610170600160a060020a0360043581169060243581169060443590606435906084359060a4351661043e565b60408051918252519081900360200190f35b34801561018e57600080fd5b50610170610474565b3480156101a357600080fd5b506101b260043560243561047a565b005b3480156101c057600080fd5b506101b26004356104a8565b3480156101d857600080fd5b50610170610660565b3480156101ed57600080fd5b506101f6610666565b60408051600160a060020a039092168252519081900360200190f35b34801561021e57600080fd5b50610170610675565b34801561023357600080fd5b5061017060043560243561067b565b34801561024e57600080fd5b50610170600435610738565b34801561026657600080fd5b5061017061074d565b6101b2600435610753565b34801561028657600080fd5b50604080516020600460443581810135601f81018490048402850184019095528484526101b2948235600160a060020a031694602480359536959460649492019190819084018382808284375094975061077d9650505050505050565b3480156102ef57600080fd5b50610170600435602435610882565b34801561030a57600080fd5b506101706108fb565b610170600160a060020a0360043516602435604435610901565b34801561033957600080fd5b506101b2600435600160a060020a0360243516604435610933565b34801561036057600080fd5b50610170600160a060020a0360043581169060243516610962565b34801561038757600080fd5b5061039360043561098e565b604080519115158252519081900360200190f35b610170600160a060020a036004358116906024359060443590606435166109aa565b3480156103d557600080fd5b50610170600160a060020a03600435811690602435166044356064356084356109dd565b34801561040557600080fd5b506101b2610a27565b34801561041a57600080fd5b50610170610a83565b34801561042f57600080fd5b50610170600435602435610a89565b60008080861161044d57600080fd5b6104578887610b64565b905061046833898984898989610d6b565b98975050505050505050565b60035481565b600654600160a060020a0316331461049157600080fd5b80151561049d57600080fd5b600b91909155600c55565b6000805460ff16156104b957600080fd5b506000805460ff1916600117815581815260026020526040812060048101549091106104e457600080fd5b805460a060020a900460ff1615156104fb57600080fd5b8054600160a060020a0316331461051157600080fd5b600481015433600090815260016020818152604080842092860154600160a060020a0316845291905290205461054c9163ffffffff61104a16565b3360009081526001602081815260408084209286018054600160a060020a03908116865293909252909220929092558254600484015491546105939391821692911661105c565b151561059e57600080fd5b6000828152600260208181526040808420805474ffffffffffffffffffffffffffffffffffffffffff1916815560018101805473ffffffffffffffffffffffffffffffffffffffff1990811690915593810180548516905560038101805490941690935560048301849055600583018490556006909201929092558051848152429281019290925280517faa2a006d186dc89a3d6851834c85d16226329ac40bcad6531a5756a38ed1c90f9281900390910190a150506000805460ff19169055565b60095481565b600854600160a060020a031681565b600b5481565b600081815260026020526040812060045460018201548391600160a060020a03918216911614156106f5576106d182600601546106c584600501548861116490919063ffffffff16565b9063ffffffff61119316565b90506106ee600a546106c56009548461116490919063ffffffff16565b9250610730565b6004546002830154600160a060020a039081169116141561072b576106ee600a546106c56009548861116490919063ffffffff16565b600092505b505092915050565b60009081526002602052604090206004015490565b600a5481565b6000341161076057600080fd5b60045461077a9033908390600160a060020a0316346111aa565b50565b80511580156107965750600554600160a060020a031633145b156107aa576107a4826113cb565b5061087d565b8051605414156107fe576107a483336107ca84604063ffffffff6113ec16565b856107dc86600063ffffffff61141c16565b6107ed87602063ffffffff61141c16565b600454600160a060020a0316610d6b565b805160681415610857576107a4833361081e84604063ffffffff6113ec16565b8561083086600063ffffffff61141c16565b61084187602063ffffffff61141c16565b61085288605463ffffffff6113ec16565b610d6b565b8051602014156101325761087d8361087683600063ffffffff61141c16565b33856111aa565b505050565b600080808415156108965760009250610730565b6000848152600260205260409020805490925060a060020a900460ff1615156108c25760009250610730565b6108dd600c546106c5600b548861116490919063ffffffff16565b90508060075410156108f3576007549250610730565b809250610730565b60075481565b600034811061090f57600080fd5b60045461092b903390600160a060020a03168634878784610d6b565b949350505050565b6000811161094057600080fd5b600061094c8383610b64565b1161095657600080fd5b61087d338484846111aa565b600160a060020a0380821660009081526001602090815260408083209386168352929052205492915050565b60009081526002602052604090205460a060020a900460ff1690565b60003481106109b857600080fd5b6004546109d4903390600160a060020a03168734888888610d6b565b95945050505050565b6000808085116109ec57600080fd5b6109f68786610b64565b9050610a1c338888848888600460009054906101000a9004600160a060020a0316610d6b565b979650505050505050565b600654600090600160a060020a03163314610a4157600080fd5b600754600010610a5057600080fd5b50600780546000909155600654600554610a7891600160a060020a039081169184911661105c565b151561077a57600080fd5b600c5481565b60008080808511610a9957600080fd5b60008481526002602052604090206004546001820154919350600160a060020a0391821691161480610add57506004546002830154600160a060020a039081169116145b15610b3557600954600a54610af79163ffffffff61104a16565b9050610b2e816106c584600501546106c5600a54610b2288600601548c61116490919063ffffffff16565b9063ffffffff61116416565b9250610b57565b610b5482600501546106c584600601548861116490919063ffffffff16565b92505b6000831161073057600080fd5b6000805481908190819060ff1615610b7b57600080fd5b6000805460ff19166001178155604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051889550600160a060020a038616926370a0823192602480820193602093909283900390910190829087803b158015610bee57600080fd5b505af1158015610c02573d6000803e3d6000fd5b505050506040513d6020811015610c1857600080fd5b5051604080517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018890529051919350600160a060020a038516916323b872dd916064808201926020929091908290030181600087803b158015610c8c57600080fd5b505af1158015610ca0573d6000803e3d6000fd5b505050506040513d6020811015610cb657600080fd5b5050604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051600160a060020a038516916370a082319160248083019260209291908290030181600087803b158015610d1957600080fd5b505af1158015610d2d573d6000803e3d6000fd5b505050506040513d6020811015610d4357600080fd5b50519050610d57818363ffffffff61104a16565b6000805460ff191690559695505050505050565b6000805460ff1615610d7c57600080fd5b6000805460ff191660011781558511610d9457600080fd5b60008411610da157600080fd5b60008311610dae57600080fd5b600160a060020a038781169087161415610dc757600080fd5b600360008154809291906001019190505590506101006040519081016040528089600160a060020a0316815260200160011515815260200188600160a060020a0316815260200187600160a060020a0316815260200183600160a060020a03168152602001868152602001858152602001848152506002600083815260200190815260200160002060008201518160000160006101000a815481600160a060020a030219169083600160a060020a0316021790555060208201518160000160146101000a81548160ff02191690831515021790555060408201518160010160006101000a815481600160a060020a030219169083600160a060020a0316021790555060608201518160020160006101000a815481600160a060020a030219169083600160a060020a0316021790555060808201518160030160006101000a815481600160a060020a030219169083600160a060020a0316021790555060a0820151816004015560c0820151816005015560e08201518160060155905050610f9f85600160008b600160a060020a0316600160a060020a0316815260200190815260200160002060008a600160a060020a0316600160a060020a031681526020019081526020016000205461143c90919063ffffffff16565b600160a060020a03808a1660008181526001602090815260408083208d86168085529083529281902095909555845186815290810192909252818401528882166060820152908416608082015260a0810187905260c0810186905260e081018590524261010082015290517f9684ab37f360879637d39ea3a41f58c0705a15f80d518ec92bd1c7383ef8a61a918190036101200190a16000805460ff19169055979650505050505050565b60008282111561105657fe5b50900390565b600454600090600160a060020a03838116911614156110b157604051600160a060020a0385169084156108fc029085906000818181858888f193505050501580156110ab573d6000803e3d6000fd5b5061115a565b81600160a060020a031663a9059cbb85856040518363ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050602060405180830381600087803b15801561112d57600080fd5b505af1158015611141573d6000803e3d6000fd5b505050506040513d602081101561115757600080fd5b50505b5060019392505050565b6000828202831580611180575082848281151561117d57fe5b04145b151561118857fe5b8091505b5092915050565b60008082848115156111a157fe5b04949350505050565b60008054819060ff16156111bd57600080fd5b6000805460ff1916600117905560035485106111d857600080fd5b600083116111e557600080fd5b6000858152600260205260409020805490925060a060020a900460ff16151561120d57600080fd5b8154600160a060020a038781169116141561122757600080fd5b6002820154600160a060020a0385811691161461124357600080fd5b6004546003830154600160a060020a03908116911614611276576003820154600160a060020a0316321461127657600080fd5b6004546001830154600160a060020a03908116911614156112a35761129c86868561144b565b90506112d7565b6004546002830154600160a060020a03908116911614156112c95761129c8686856115bf565b6112d486868561173d565b90505b6112e18187611880565b15156112ec57600080fd5b60008581526002602052604090206004015415156113b9576000858152600260208181526040808420805474ffffffffffffffffffffffffffffffffffffffffff1916815560018101805473ffffffffffffffffffffffffffffffffffffffff1990811690915593810180548516905560038101805490941690935560048301849055600583018490556006909201929092558051878152429281019290925280517feb3b41be12efa25c0c65725eeff2e2ad0250e2e5de2aa939e18f36aa656e98809281900390910190a15b50506000805460ff1916905550505050565b6007546000906113e1908363ffffffff61143c16565b600755506001919050565b6000808260140184511015151561140257600080fd5b505001602001516c01000000000000000000000000900490565b6000808260200184511015151561143257600080fd5b5050016020015190565b60008282018381101561118857fe5b6000828152600260205260408120600681015460058201548391829161147d91906106c590889063ffffffff61116416565b915061149a600a546106c56009548561116490919063ffffffff16565b9050600082116114a957600080fd5b60048301548211156114ba57600080fd5b60048301546114cf908363ffffffff61104a16565b6004840155825460028401546114f391600160a060020a039081169188911661105c565b15156114fe57600080fd5b61152587611512848463ffffffff61104a16565b6001860154600160a060020a031661105c565b151561153057600080fd5b82547f01f5d7c359dba416997ea6c723ea4663e9ad524f956ed8bb3b5234e6475a7285908890600160a060020a031688611570868663ffffffff61104a16565b60408051600160a060020a0395861681529390941660208401528284019190915260608201526080810188905260a081018490524260c082015290519081900360e00190a19695505050505050565b6000828152600260205260408120600a54600954839182916115ed91906106c590889063ffffffff61116416565b915061161283600601546106c58560050154610b22868a61104a90919063ffffffff16565b90506000811161162157600080fd5b600483015481111561163257600080fd5b6004830154611647908263ffffffff61104a16565b6004840155825461167e90600160a060020a031661166b878563ffffffff61104a16565b6002860154600160a060020a031661105c565b151561168957600080fd5b60018301546116a49088908390600160a060020a031661105c565b15156116af57600080fd5b82547f01f5d7c359dba416997ea6c723ea4663e9ad524f956ed8bb3b5234e6475a7285908890600160a060020a031688846116f08a8863ffffffff61104a16565b60408051600160a060020a039687168152949095166020850152838501929092526060830152608082015260a081018590524260c082015290519081900360e00190a15095945050505050565b600082815260026020526040812060068101546005820154839161176c916106c590879063ffffffff61116416565b90506000811161177b57600080fd5b600482015481111561178c57600080fd5b60048201546117a1908263ffffffff61104a16565b6004830155815460028301546117c591600160a060020a039081169187911661105c565b15156117d057600080fd5b815460a060020a900460ff1615156117e757600080fd5b60018201546118029087908390600160a060020a031661105c565b151561180d57600080fd5b815460408051600160a060020a03808a16825290921660208301528181018790526060820183905260808201869052600060a08301524260c0830152517f01f5d7c359dba416997ea6c723ea4663e9ad524f956ed8bb3b5234e6475a72859181900360e00190a150600095945050505050565b600080831515611893576001915061118c565b6008546004546118b191600160a060020a039081169187911661105c565b15156118bc57600080fd5b60075415156118ce576001915061118c565b6118e9600c546106c5600b548761116490919063ffffffff16565b90508015156118fb576001915061118c565b60075481111561190a57506007545b60075461191d908263ffffffff61104a16565b6007556005546119399084908390600160a060020a031661105c565b151561194457600080fd5b60408051600160a060020a038516815260208101839052428183015290517f5a9ec13c12ca9563a7b3108125f74c57ed388bb313394ea50f7e4a71b01497c29181900360600190a150600193925050505600a165627a7a72305820b0946e0e1d3d1e148149c2bb4e2cd4e7a7e4ff34839dd14ff5edcfedca71a0cb0029
Verified Source Code Partial Match
Compiler: v0.4.24+commit.e67f0147
EVM: byzantium
Optimization: Yes (200 runs)
Exchange.sol 614 lines
// Saturn Protocol
// File: contracts/SafeMath.sol
pragma solidity ^0.4.24;
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
// File: contracts/BytesLib.sol
// from
// https://github.com/GNSPS/solidity-bytes-utils/blob/master/contracts/BytesLib.sol
library BytesLib {
function toAddress(bytes _bytes, uint _start) internal pure returns (address) {
require(_bytes.length >= (_start + 20));
address tempAddress;
assembly {
tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
}
return tempAddress;
}
function toUint(bytes _bytes, uint _start) internal pure returns (uint256) {
require(_bytes.length >= (_start + 32));
uint256 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x20), _start))
}
return tempUint;
}
}
// File: contracts/ERC223.sol
contract ERC223 {
uint public totalSupply;
function balanceOf(address who) constant public returns (uint);
function name() constant public returns (string _name);
function symbol() constant public returns (string _symbol);
function decimals() constant public returns (uint8 _decimals);
function totalSupply() constant public returns (uint256 _supply);
function transfer(address to, uint value) public returns (bool ok);
function transfer(address to, uint value, bytes data) public returns (bool ok);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event ERC223Transfer(address indexed _from, address indexed _to, uint256 _value, bytes _data);
}
contract ContractReceiver {
function tokenFallback(address _from, uint _value, bytes _data) public;
}
contract ERC223I is ERC223 {
using SafeMath for uint;
mapping(address => uint) balances;
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
function name() constant public returns (string _name) {
return name;
}
function symbol() constant public returns (string _symbol) {
return symbol;
}
function decimals() constant public returns (uint8 _decimals) {
return decimals;
}
function totalSupply() constant public returns (uint256 _totalSupply) {
return totalSupply;
}
function transfer(address _to, uint _value, bytes _data) public returns (bool success) {
if (isContract(_to)) {
return transferToContract(_to, _value, _data);
} else {
return transferToAddress(_to, _value, _data);
}
}
function transfer(address _to, uint _value) public returns (bool success) {
bytes memory empty;
if (isContract(_to)) {
return transferToContract(_to, _value, empty);
} else {
return transferToAddress(_to, _value, empty);
}
}
function isContract(address _addr) private view returns (bool is_contract) {
uint length;
assembly {
length := extcodesize(_addr)
}
return (length > 0);
}
function transferToAddress(address _to, uint _value, bytes _data) private returns (bool success) {
if (balanceOf(msg.sender) < _value) revert();
balances[msg.sender] = balanceOf(msg.sender).sub(_value);
balances[_to] = balanceOf(_to).add(_value);
Transfer(msg.sender, _to, _value);
ERC223Transfer(msg.sender, _to, _value, _data);
return true;
}
function transferToContract(address _to, uint _value, bytes _data) private returns (bool success) {
if (balanceOf(msg.sender) < _value) revert();
balances[msg.sender] = balanceOf(msg.sender).sub(_value);
balances[_to] = balanceOf(_to).add(_value);
ContractReceiver reciever = ContractReceiver(_to);
reciever.tokenFallback(msg.sender, _value, _data);
Transfer(msg.sender, _to, _value);
ERC223Transfer(msg.sender, _to, _value, _data);
return true;
}
function balanceOf(address _owner) constant public returns (uint balance) {
return balances[_owner];
}
}
// File: contracts/Exchange.sol
// Saturn Protocol
contract ERC20 {
function totalSupply() public view returns (uint);
function balanceOf(address holder) public view returns (uint);
function allowance(address holder, address other) public view returns (uint);
function approve(address other, uint amount) public returns (bool);
function transfer(address to, uint amount) public returns (bool);
function transferFrom(
address from, address to, uint amount
) public returns (bool);
}
contract Exchange is ContractReceiver {
using SafeMath for uint256;
using BytesLib for bytes;
bool private rentrancy_lock = false;
modifier nonReentrant() {
require(!rentrancy_lock);
rentrancy_lock = true;
_;
rentrancy_lock = false;
}
struct Order {
address owner;
bool active;
address sellToken;
address buyToken;
address ring;
uint256 amount;
uint256 priceMul;
uint256 priceDiv;
}
// person => token => balance
mapping(address => mapping(address => uint256)) private balances;
mapping(uint256 => Order) private orderBook;
uint256 public orderCount;
address private etherAddress = 0x0;
address private saturnToken;
address private admin;
uint256 public tradeMiningBalance;
address public treasury;
uint256 public feeMul;
uint256 public feeDiv;
uint256 public tradeMiningMul;
uint256 public tradeMiningDiv;
event NewOrder(
uint256 id,
address owner,
address sellToken,
address buyToken,
address ring,
uint256 amount,
uint256 priceMul,
uint256 priceDiv,
uint256 time
);
event OrderCancelled(
uint256 id,
uint256 time
);
event OrderFulfilled(
uint256 id,
uint256 time
);
event Trade(
address from,
address to,
uint256 orderId,
uint256 soldTokens,
uint256 boughtTokens,
uint256 feePaid,
uint256 time
);
event Mined(
address trader,
uint256 amount,
uint256 time
);
function Exchange(
address _saturnToken,
address _treasury,
uint256 _feeMul,
uint256 _feeDiv,
uint256 _tradeMiningMul,
uint256 _tradeMiningDiv
) public {
saturnToken = _saturnToken;
treasury = _treasury;
feeMul = _feeMul;
feeDiv = _feeDiv;
tradeMiningMul = _tradeMiningMul;
tradeMiningDiv = _tradeMiningDiv;
admin = msg.sender;
}
function() payable public { revert(); }
//////////////////
// public views //
//////////////////
// add views for prices too
// and for order owner too
function getBalance(address token, address user) view public returns(uint256) {
return balances[user][token];
}
function isOrderActive(uint256 orderId) view public returns(bool) {
return orderBook[orderId].active;
}
function remainingAmount(uint256 orderId) view public returns(uint256) {
return orderBook[orderId].amount;
}
function getBuyTokenAmount(uint256 desiredSellTokenAmount, uint256 orderId) public view returns(uint256 amount) {
require(desiredSellTokenAmount > 0);
Order storage order = orderBook[orderId];
if (order.sellToken == etherAddress || order.buyToken == etherAddress) {
uint256 feediff = feeDiv.sub(feeMul);
amount = desiredSellTokenAmount.mul(order.priceDiv).mul(feeDiv).div(order.priceMul).div(feediff);
} else {
amount = desiredSellTokenAmount.mul(order.priceDiv).div(order.priceMul);
}
require(amount > 0);
}
function calcFees(uint256 amount, uint256 orderId) public view returns(uint256 fees) {
Order storage order = orderBook[orderId];
if (order.sellToken == etherAddress) {
uint256 sellTokenAmount = amount.mul(order.priceMul).div(order.priceDiv);
fees = sellTokenAmount.mul(feeMul).div(feeDiv);
} else if (order.buyToken == etherAddress) {
fees = amount.mul(feeMul).div(feeDiv);
} else {
fees = 0;
}
return fees;
}
function tradeMiningAmount(uint256 fees, uint256 orderId) public view returns(uint256) {
if (fees == 0) { return 0; }
Order storage order = orderBook[orderId];
if (!order.active) { return 0; }
uint256 tokenAmount = fees.mul(tradeMiningMul).div(tradeMiningDiv);
if (tradeMiningBalance < tokenAmount) {
return tradeMiningBalance;
} else {
return tokenAmount;
}
}
////////////////////
// public methods //
////////////////////
function withdrawTradeMining() public {
if (msg.sender != admin) { revert(); }
require(tradeMiningBalance > 0);
uint toSend = tradeMiningBalance;
tradeMiningBalance = 0;
require(sendTokensTo(admin, toSend, saturnToken));
}
function changeTradeMiningPrice(uint256 newMul, uint256 newDiv) public {
if (msg.sender != admin) { revert(); }
require(newDiv != 0);
tradeMiningMul = newMul;
tradeMiningDiv = newDiv;
}
// handle incoming ERC223 tokens
function tokenFallback(address from, uint value, bytes data) public {
// depending on length of data
// this should be either an order creating transaction
// or an order taking transaction
// or a transaction allocating tokens for trade mining
if (data.length == 0 && msg.sender == saturnToken) {
_topUpTradeMining(value);
} else if (data.length == 84) {
_newOrder(from, msg.sender, data.toAddress(64), value, data.toUint(0), data.toUint(32), etherAddress);
} else if (data.length == 104) {
_newOrder(from, msg.sender, data.toAddress(64), value, data.toUint(0), data.toUint(32), data.toAddress(84));
} else if (data.length == 32) {
_executeOrder(from, data.toUint(0), msg.sender, value);
} else {
// unknown payload!
revert();
}
}
function sellEther(
address buyToken,
uint256 priceMul,
uint256 priceDiv
) public payable returns(uint256 orderId) {
require(msg.value > 0);
return _newOrder(msg.sender, etherAddress, buyToken, msg.value, priceMul, priceDiv, etherAddress);
}
function sellEtherWithRing(
address buyToken,
uint256 priceMul,
uint256 priceDiv,
address ring
) public payable returns(uint256 orderId) {
require(msg.value > 0);
return _newOrder(msg.sender, etherAddress, buyToken, msg.value, priceMul, priceDiv, ring);
}
function buyOrderWithEth(uint256 orderId) public payable {
require(msg.value > 0);
_executeOrder(msg.sender, orderId, etherAddress, msg.value);
}
function sellERC20Token(
address sellToken,
address buyToken,
uint256 amount,
uint256 priceMul,
uint256 priceDiv
) public returns(uint256 orderId) {
require(amount > 0);
uint256 pulledAmount = pullTokens(sellToken, amount);
return _newOrder(msg.sender, sellToken, buyToken, pulledAmount, priceMul, priceDiv, etherAddress);
}
function sellERC20TokenWithRing(
address sellToken,
address buyToken,
uint256 amount,
uint256 priceMul,
uint256 priceDiv,
address ring
) public returns(uint256 orderId) {
require(amount > 0);
uint256 pulledAmount = pullTokens(sellToken, amount);
return _newOrder(msg.sender, sellToken, buyToken, pulledAmount, priceMul, priceDiv, ring);
}
function buyOrderWithERC20Token(
uint256 orderId,
address token,
uint256 amount
) public {
require(amount > 0);
require(pullTokens(token, amount) > 0);
_executeOrder(msg.sender, orderId, token, amount);
}
function cancelOrder(uint256 orderId) public nonReentrant {
Order storage order = orderBook[orderId];
require(order.amount > 0);
require(order.active);
require(msg.sender == order.owner);
balances[msg.sender][order.sellToken] = balances[msg.sender][order.sellToken].sub(order.amount);
require(sendTokensTo(order.owner, order.amount, order.sellToken));
// deleting the order refunds the caller some gas
// this also sets order.active to false
delete orderBook[orderId];
emit OrderCancelled(orderId, now);
}
/////////////////////
// private methods //
/////////////////////
function _newOrder(
address owner,
address sellToken,
address buyToken,
uint256 amount,
uint256 priceMul,
uint256 priceDiv,
address ring
) private nonReentrant returns(uint256 orderId) {
/////////////////////////
// step 1. validations //
/////////////////////////
require(amount > 0);
require(priceMul > 0);
require(priceDiv > 0);
require(sellToken != buyToken);
///////////////////////////////
// step 2. Update order book //
///////////////////////////////
orderId = orderCount++;
orderBook[orderId] = Order(owner, true, sellToken, buyToken, ring, amount, priceMul, priceDiv);
balances[owner][sellToken] = balances[owner][sellToken].add(amount);
emit NewOrder(orderId, owner, sellToken, buyToken, ring, amount, priceMul, priceDiv, now);
}
function _executeBuyOrder(address trader, uint256 orderId, uint256 buyTokenAmount) private returns(uint256) {
// buytoken: tkn
// selltoken: ether
Order storage order = orderBook[orderId];
uint256 sellTokenAmount = buyTokenAmount.mul(order.priceMul).div(order.priceDiv);
uint256 fees = sellTokenAmount.mul(feeMul).div(feeDiv);
require(sellTokenAmount > 0);
require(sellTokenAmount <= order.amount);
order.amount = order.amount.sub(sellTokenAmount);
// send tokens to order owner
require(sendTokensTo(order.owner, buyTokenAmount, order.buyToken));
// send ether to trader
require(sendTokensTo(trader, sellTokenAmount.sub(fees), order.sellToken));
emit Trade(trader, order.owner, orderId, sellTokenAmount.sub(fees), buyTokenAmount, fees, now);
return fees;
}
function _executeSellOrder(address trader, uint256 orderId, uint256 buyTokenAmount) private returns(uint256) {
// buytoken: ether
// selltoken: tkn
Order storage order = orderBook[orderId];
uint256 fees = buyTokenAmount.mul(feeMul).div(feeDiv);
uint256 sellTokenAmount = buyTokenAmount.sub(fees).mul(order.priceMul).div(order.priceDiv);
require(sellTokenAmount > 0);
require(sellTokenAmount <= order.amount);
order.amount = order.amount.sub(sellTokenAmount);
// send ether to order owner
require(sendTokensTo(order.owner, buyTokenAmount.sub(fees), order.buyToken));
// send token to trader
require(sendTokensTo(trader, sellTokenAmount, order.sellToken));
emit Trade(trader, order.owner, orderId, sellTokenAmount, buyTokenAmount.sub(fees), fees, now);
return fees;
}
function _executeTokenSwap(address trader, uint256 orderId, uint256 buyTokenAmount) private returns(uint256) {
// no ether was exchanged
Order storage order = orderBook[orderId];
uint256 sellTokenAmount = buyTokenAmount.mul(order.priceMul).div(order.priceDiv);
require(sellTokenAmount > 0);
require(sellTokenAmount <= order.amount);
order.amount = order.amount.sub(sellTokenAmount);
require(sendTokensTo(order.owner, buyTokenAmount, order.buyToken));
require(order.active);
require(sendTokensTo(trader, sellTokenAmount, order.sellToken));
emit Trade(trader, order.owner, orderId, sellTokenAmount, buyTokenAmount, 0, now);
return 0;
}
function _executeOrder(address trader, uint256 orderId, address buyToken, uint256 buyTokenAmount) private nonReentrant {
/////////////////////////
// step 0. validations //
/////////////////////////
require(orderId < orderCount);
require(buyTokenAmount > 0);
Order storage order = orderBook[orderId];
require(order.active);
require(trader != order.owner);
require(buyToken == order.buyToken);
// enforce exclusivity
if (order.ring != etherAddress) { require(order.ring == tx.origin); }
////////////////////////////
// step 1. token exchange //
////////////////////////////
uint256 fees;
if (order.sellToken == etherAddress) {
// buy order: taker sends ether, gets tokens
fees = _executeBuyOrder(trader, orderId, buyTokenAmount);
} else if (order.buyToken == etherAddress) {
// sell order: taker sends tokens, gets ether
fees = _executeSellOrder(trader, orderId, buyTokenAmount);
} else {
fees = _executeTokenSwap(trader, orderId, buyTokenAmount);
}
////////////////////////////
// step 2. fees & wrap up //
////////////////////////////
// collect fees and issue trade mining
require(_tradeMiningAndFees(fees, trader));
// deleting the order refunds the caller some gas
if (orderBook[orderId].amount == 0) {
delete orderBook[orderId];
emit OrderFulfilled(orderId, now);
}
}
function _tradeMiningAndFees(uint256 fees, address trader) private returns(bool) {
if (fees == 0) { return true; }
// step one: send fees to the treasury
require(sendTokensTo(treasury, fees, etherAddress));
if (tradeMiningBalance == 0) { return true; }
// step two: calculate reward
uint256 tokenAmount = fees.mul(tradeMiningMul).div(tradeMiningDiv);
if (tokenAmount == 0) { return true; }
if (tokenAmount > tradeMiningBalance) { tokenAmount = tradeMiningBalance; }
// account for sent tokens
tradeMiningBalance = tradeMiningBalance.sub(tokenAmount);
// step three: send the reward to the trader
require(sendTokensTo(trader, tokenAmount, saturnToken));
emit Mined(trader, tokenAmount, now);
return true;
}
function sendTokensTo(
address destination,
uint256 amount,
address tkn
) private returns(bool) {
if (tkn == etherAddress) {
destination.transfer(amount);
} else {
// works with both ERC223 and ERC20
ERC20(tkn).transfer(destination, amount);
}
return true;
}
// ERC20 fixture
function pullTokens(address token, uint256 amount) private nonReentrant returns(uint256) {
ERC20 tkn = ERC20(token);
// need to do this balance dance in order to account for deflationary tokens
uint256 balanceBefore = tkn.balanceOf(address(this));
tkn.transferFrom(msg.sender, address(this), amount);
uint256 balanceAfter = tkn.balanceOf(address(this));
return balanceAfter.sub(balanceBefore);
}
function _topUpTradeMining(uint256 amount) private returns(bool) {
tradeMiningBalance = tradeMiningBalance.add(amount);
return true;
}
}
Read Contract
calcFees 0x78d067dd → uint256
feeDiv 0x89a447e0 → uint256
feeMul 0x53e1a7a0 → uint256
getBalance 0xd4fac45d → uint256
getBuyTokenAmount 0xff700e52 → uint256
isOrderActive 0xd6e43585 → bool
orderCount 0x2453ffa8 → uint256
remainingAmount 0x87bda8f2 → uint256
tradeMiningAmount 0xc49063e7 → uint256
tradeMiningBalance 0xc655de64 → uint256
tradeMiningDiv 0xfc5f4241 → uint256
tradeMiningMul 0x6fb768e8 → uint256
treasury 0x61d027b3 → address
Write Contract 10 functions
These functions modify contract state and require a wallet transaction to execute.
buyOrderWithERC20Token 0xcf6ff173
uint256 orderId
address token
uint256 amount
buyOrderWithEth 0xa4ff9c34
uint256 orderId
cancelOrder 0x514fcac7
uint256 orderId
changeTradeMiningPrice 0x41f9377f
uint256 newMul
uint256 newDiv
sellERC20Token 0xeeb3377a
address sellToken
address buyToken
uint256 amount
uint256 priceMul
uint256 priceDiv
returns: uint256
sellERC20TokenWithRing 0x22fdd3ea
address sellToken
address buyToken
uint256 amount
uint256 priceMul
uint256 priceDiv
address ring
returns: uint256
sellEther 0xcb2bb264
address buyToken
uint256 priceMul
uint256 priceDiv
returns: uint256
sellEtherWithRing 0xe3319e82
address buyToken
uint256 priceMul
uint256 priceDiv
address ring
returns: uint256
tokenFallback 0xc0ee0b8a
address from
uint256 value
bytes data
withdrawTradeMining 0xf2037fec
No parameters
Token Balances (3)
View Transfers →Recent Transactions
No transactions found for this address