ETH Price: $2,003.39 (+0.71%)

Transaction Decoder

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 Code
0x6bB031D8...16FFe4e5e 0.196775493753924499 Eth0.266135493753924499 Eth0.06936
448.450596124164222811 Eth448.451105554164222811 Eth0.00050943
0x91688542...00675f9EC
0x92EEb915...B6Af6d5fD 21.63662192504585905 Eth21.636795759632325215 Eth0.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 )
    File 1 of 3: Exchange
    // 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;
      }
    }