Transaction Hash:
Block:
9912803 at Apr-21-2020 01:10:51 AM +UTC
Transaction Fee:
0.00050943 ETH
$1.02
Gas Used:
84,905 Gas / 6 Gwei
Emitted Events:
| 181 |
GoalTimeToken.Transfer( from=[Receiver] Exchange, to=[Sender] 0xd49b69b45cea566a0357bbe781536f3841028f7f, tokens=30000000000000000000 )
|
| 182 |
Exchange.Trade( from=[Sender] 0xd49b69b45cea566a0357bbe781536f3841028f7f, to=0x6bb031d8eb6b2c9dcb667a061e7863a16ffe4e5e, orderId=23488, soldTokens=30000000000000000000, boughtTokens=69360000000000000, feePaid=173834586466165, time=1587431451 )
|
| 183 |
Saturn.Transfer( _from=[Receiver] Exchange, _to=[Sender] 0xd49b69b45cea566a0357bbe781536f3841028f7f, _value=17383 )
|
| 184 |
Saturn.ERC223Transfer( _from=[Receiver] Exchange, _to=[Sender] 0xd49b69b45cea566a0357bbe781536f3841028f7f, _value=17383, _data=0x )
|
| 185 |
Exchange.Mined( trader=[Sender] 0xd49b69b45cea566a0357bbe781536f3841028f7f, amount=17383, time=1587431451 )
|
| 186 |
Exchange.OrderFulfilled( id=23488, time=1587431451 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x6bB031D8...16FFe4e5e | 0.196775493753924499 Eth | 0.266135493753924499 Eth | 0.06936 | ||
|
0x84A0d77c...010577051
Miner
| 448.450596124164222811 Eth | 448.451105554164222811 Eth | 0.00050943 | ||
| 0x91688542...00675f9EC | |||||
| 0x92EEb915...B6Af6d5fD | 21.63662192504585905 Eth | 21.636795759632325215 Eth | 0.000173834586466165 | ||
| 0xaA5bBD5A...444Dbd586 | (Saturn Network 2) | ||||
| 0xb9440022...794Bd76c8 | |||||
| 0xD49b69B4...841028F7F |
0.365021260184424947 Eth
Nonce: 1296
|
0.294977995597958782 Eth
Nonce: 1297
| 0.070043264586466165 |
Execution Trace
ETH 0.069533834586466165
Exchange.buyOrderWithEth( orderId=23488 )
- ETH 0.06936
0x6bb031d8eb6b2c9dcb667a061e7863a16ffe4e5e.CALL( ) -
GoalTimeToken.transfer( to=0xD49b69B45cea566a0357bBe781536f3841028F7F, tokens=30000000000000000000 ) => ( success=True )
- ETH 0.000173834586466165
0x92eeb915dafe3803f8a9d12000765c3b6af6d5fd.CALL( ) -
Saturn.transfer( _to=0xD49b69B45cea566a0357bBe781536f3841028F7F, _value=17383 ) => ( success=True )
buyOrderWithEth[Exchange (ln:386)]
_executeOrder[Exchange (ln:388)]_executeBuyOrder[Exchange (ln:547)]div[Exchange (ln:475)]mul[Exchange (ln:475)]div[Exchange (ln:476)]mul[Exchange (ln:476)]sub[Exchange (ln:480)]sendTokensTo[Exchange (ln:482)]transfer[Exchange (ln:592)]transfer[Exchange (ln:595)]
sendTokensTo[Exchange (ln:484)]transfer[Exchange (ln:592)]transfer[Exchange (ln:595)]
sub[Exchange (ln:484)]Trade[Exchange (ln:486)]sub[Exchange (ln:486)]
_executeSellOrder[Exchange (ln:550)]div[Exchange (ln:494)]mul[Exchange (ln:494)]div[Exchange (ln:495)]mul[Exchange (ln:495)]sub[Exchange (ln:495)]sub[Exchange (ln:500)]sendTokensTo[Exchange (ln:502)]transfer[Exchange (ln:592)]transfer[Exchange (ln:595)]
sub[Exchange (ln:502)]sendTokensTo[Exchange (ln:504)]transfer[Exchange (ln:592)]transfer[Exchange (ln:595)]
Trade[Exchange (ln:506)]sub[Exchange (ln:506)]
_executeTokenSwap[Exchange (ln:552)]div[Exchange (ln:513)]mul[Exchange (ln:513)]sub[Exchange (ln:517)]sendTokensTo[Exchange (ln:519)]transfer[Exchange (ln:592)]transfer[Exchange (ln:595)]
sendTokensTo[Exchange (ln:521)]transfer[Exchange (ln:592)]transfer[Exchange (ln:595)]
Trade[Exchange (ln:523)]
_tradeMiningAndFees[Exchange (ln:559)]sendTokensTo[Exchange (ln:570)]transfer[Exchange (ln:592)]transfer[Exchange (ln:595)]
div[Exchange (ln:574)]mul[Exchange (ln:574)]sub[Exchange (ln:579)]sendTokensTo[Exchange (ln:581)]transfer[Exchange (ln:592)]transfer[Exchange (ln:595)]
Mined[Exchange (ln:582)]
OrderFulfilled[Exchange (ln:563)]
File 1 of 3: Exchange
File 2 of 3: GoalTimeToken
File 3 of 3: Saturn
// 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;
}
}File 2 of 3: GoalTimeToken
pragma solidity ^0.4.24;
// ----------------------------------------------------------------------------
// 'GTX' token contract
//
// Deployed to : 0x04DBEDd79600BC937e84aD26bAF6E651fa9DCf2c
// Symbol : GTX
// Name : GoalTime N
// Total supply: 1000000000
// Decimals : 18
//
// Enjoy.
//
// (c) by Moritz Neto with BokkyPooBah / Bok Consulting Pty Ltd Au 2017. The MIT Licence.
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// Safe maths
// ----------------------------------------------------------------------------
contract SafeMath {
function safeAdd(uint a, uint b) public pure returns (uint c) {
c = a + b;
require(c >= a);
}
function safeSub(uint a, uint b) public pure returns (uint c) {
require(b <= a);
c = a - b;
}
function safeMul(uint a, uint b) public pure returns (uint c) {
c = a * b;
require(a == 0 || c / a == b);
}
function safeDiv(uint a, uint b) public pure returns (uint c) {
require(b > 0);
c = a / b;
}
}
// ----------------------------------------------------------------------------
// ERC Token Standard #20 Interface
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
// ----------------------------------------------------------------------------
contract ERC20Interface {
function totalSupply() public constant returns (uint);
function balanceOf(address tokenOwner) public constant returns (uint balance);
function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);
event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
// ----------------------------------------------------------------------------
// Contract function to receive approval and execute function in one call
//
// Borrowed from MiniMeToken
// ----------------------------------------------------------------------------
contract ApproveAndCallFallBack {
function receiveApproval(address from, uint256 tokens, address token, bytes data) public;
}
// ----------------------------------------------------------------------------
// Owned contract
// ----------------------------------------------------------------------------
contract Owned {
address public owner;
address public newOwner;
event OwnershipTransferred(address indexed _from, address indexed _to);
constructor() public {
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function transferOwnership(address _newOwner) public onlyOwner {
newOwner = _newOwner;
}
function acceptOwnership() public {
require(msg.sender == newOwner);
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
newOwner = address(0);
}
}
// ----------------------------------------------------------------------------
// ERC20 Token, with the addition of symbol, name and decimals and assisted
// token transfers
// ----------------------------------------------------------------------------
contract GoalTimeToken is ERC20Interface, Owned, SafeMath {
string public symbol;
string public name;
uint8 public decimals;
uint public _totalSupply;
mapping(address => uint) balances;
mapping(address => mapping(address => uint)) allowed;
// ------------------------------------------------------------------------
// Constructor
// ------------------------------------------------------------------------
constructor() public {
symbol = "GTX";
name = "GoalTime N";
decimals = 18;
_totalSupply = 100000000000000000000000000;
balances[0x04DBEDd79600BC937e84aD26bAF6E651fa9DCf2c] = _totalSupply;
emit Transfer(address(0), 0x04DBEDd79600BC937e84aD26bAF6E651fa9DCf2c, _totalSupply);
}
// ------------------------------------------------------------------------
// Total supply
// ------------------------------------------------------------------------
function totalSupply() public constant returns (uint) {
return _totalSupply - balances[address(0)];
}
// ------------------------------------------------------------------------
// Get the token balance for account tokenOwner
// ------------------------------------------------------------------------
function balanceOf(address tokenOwner) public constant returns (uint balance) {
return balances[tokenOwner];
}
// ------------------------------------------------------------------------
// Transfer the balance from token owner's account to to account
// - Owner's account must have sufficient balance to transfer
// - 0 value transfers are allowed
// ------------------------------------------------------------------------
function transfer(address to, uint tokens) public returns (bool success) {
balances[msg.sender] = safeSub(balances[msg.sender], tokens);
balances[to] = safeAdd(balances[to], tokens);
emit Transfer(msg.sender, to, tokens);
return true;
}
// ------------------------------------------------------------------------
// Token owner can approve for spender to transferFrom(...) tokens
// from the token owner's account
//
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
// recommends that there are no checks for the approval double-spend attack
// as this should be implemented in user interfaces
// ------------------------------------------------------------------------
function approve(address spender, uint tokens) public returns (bool success) {
allowed[msg.sender][spender] = tokens;
emit Approval(msg.sender, spender, tokens);
return true;
}
// ------------------------------------------------------------------------
// Transfer tokens from the from account to the to account
//
// The calling account must already have sufficient tokens approve(...)-d
// for spending from the from account and
// - From account must have sufficient balance to transfer
// - Spender must have sufficient allowance to transfer
// - 0 value transfers are allowed
// ------------------------------------------------------------------------
function transferFrom(address from, address to, uint tokens) public returns (bool success) {
balances[from] = safeSub(balances[from], tokens);
allowed[from][msg.sender] = safeSub(allowed[from][msg.sender], tokens);
balances[to] = safeAdd(balances[to], tokens);
emit Transfer(from, to, tokens);
return true;
}
// ------------------------------------------------------------------------
// Returns the amount of tokens approved by the owner that can be
// transferred to the spender's account
// ------------------------------------------------------------------------
function allowance(address tokenOwner, address spender) public constant returns (uint remaining) {
return allowed[tokenOwner][spender];
}
// ------------------------------------------------------------------------
// Token owner can approve for spender to transferFrom(...) tokens
// from the token owner's account. The spender contract function
// receiveApproval(...) is then executed
// ------------------------------------------------------------------------
function approveAndCall(address spender, uint tokens, bytes data) public returns (bool success) {
allowed[msg.sender][spender] = tokens;
emit Approval(msg.sender, spender, tokens);
ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);
return true;
}
// ------------------------------------------------------------------------
// Don't accept ETH
// ------------------------------------------------------------------------
function () public payable {
revert();
}
// ------------------------------------------------------------------------
// Owner can transfer out any accidentally sent ERC20 tokens
// ------------------------------------------------------------------------
function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) {
return ERC20Interface(tokenAddress).transfer(owner, tokens);
}
}File 3 of 3: Saturn
pragma solidity ^0.4.18;
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
/**
* @dev Multiplies two numbers, throws on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
assert(c / a == b);
return c;
}
/**
* @dev Integer division of two numbers, truncating the quotient.
*/
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;
}
/**
* @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
/**
* @dev Adds two numbers, throws on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
contract ERC223 {
uint public totalSupply;
function balanceOf(address who) constant returns (uint);
function name() constant returns (string _name);
function symbol() constant returns (string _symbol);
function decimals() constant returns (uint8 _decimals);
function totalSupply() constant returns (uint256 _supply);
function transfer(address to, uint value) returns (bool ok);
function transfer(address to, uint value, bytes data) 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);
}
contract ERC223Token is ERC223 {
using SafeMath for uint;
mapping(address => uint) balances;
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
// Function to access name of token .
function name() constant returns (string _name) {
return name;
}
// Function to access symbol of token .
function symbol() constant returns (string _symbol) {
return symbol;
}
// Function to access decimals of token .
function decimals() constant returns (uint8 _decimals) {
return decimals;
}
// Function to access total supply of tokens .
function totalSupply() constant returns (uint256 _totalSupply) {
return totalSupply;
}
// Function that is called when a user or another contract wants to transfer funds .
function transfer(address _to, uint _value, bytes _data) returns (bool success) {
if(isContract(_to)) {
return transferToContract(_to, _value, _data);
}
else {
return transferToAddress(_to, _value, _data);
}
}
// Standard function transfer similar to ERC20 transfer with no _data .
// Added due to backwards compatibility reasons .
function transfer(address _to, uint _value) returns (bool success) {
//standard function transfer similar to ERC20 transfer with no _data
//added due to backwards compatibility reasons
bytes memory empty;
if(isContract(_to)) {
return transferToContract(_to, _value, empty);
}
else {
return transferToAddress(_to, _value, empty);
}
}
//assemble the given address bytecode. If bytecode exists then the _addr is a contract.
function isContract(address _addr) private returns (bool is_contract) {
uint length;
assembly {
//retrieve the size of the code on target address, this needs assembly
length := extcodesize(_addr)
}
if(length>0) {
return true;
}
else {
return false;
}
}
//function that is called when transaction target is an address
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 that is called when transaction target is a contract
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 returns (uint balance) {
return balances[_owner];
}
}
contract Saturn is ERC223Token {
string public name = "Saturn DAO Token";
string public symbol = "SATURN";
uint public decimals = 4;
uint public totalSupply = 1000000000 * 10**4;
function Saturn() {
balances[msg.sender] = totalSupply;
}
}